1 /***************************************************************************/
5 /* The FreeType services (specification only). */
7 /* Copyright 2003-2018 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
18 /*************************************************************************/
20 /* Each module can export one or more `services'. Each service is */
21 /* identified by a constant string and modeled by a pointer; the latter */
22 /* generally corresponds to a structure containing function pointers. */
24 /* Note that a service's data cannot be a mere function pointer because */
25 /* in C it is possible that function pointers might be implemented */
26 /* differently than data pointers (e.g. 48 bits instead of 32). */
28 /*************************************************************************/
39 * FT_FACE_FIND_SERVICE
42 * This macro is used to look up a service from a face's driver module.
46 * The source face handle.
49 * A string describing the service as defined in the service's
50 * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
51 * `multi-masters'). It is automatically prefixed with
56 * A variable that receives the service pointer. Will be NULL
61 #define FT_FACE_FIND_SERVICE( face, ptr, id ) \
63 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
64 FT_Pointer _tmp_ = NULL; \
65 FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \
68 if ( module->clazz->get_interface ) \
69 _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
75 #define FT_FACE_FIND_SERVICE( face, ptr, id ) \
77 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
78 FT_Pointer _tmp_ = NULL; \
80 if ( module->clazz->get_interface ) \
81 _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
90 * FT_FACE_FIND_GLOBAL_SERVICE
93 * This macro is used to look up a service from all modules.
97 * The source face handle.
100 * A string describing the service as defined in the service's
101 * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
102 * `multi-masters'). It is automatically prefixed with
107 * A variable that receives the service pointer. Will be NULL
112 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \
114 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
116 FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \
119 _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
125 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \
127 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
131 _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
138 /*************************************************************************/
139 /*************************************************************************/
141 /***** S E R V I C E D E S C R I P T O R S *****/
143 /*************************************************************************/
144 /*************************************************************************/
147 * The following structure is used to _describe_ a given service
148 * to the library. This is useful to build simple static service lists.
150 typedef struct FT_ServiceDescRec_
152 const char* serv_id
; /* service name */
153 const void* serv_data
; /* service pointer/data */
157 typedef const FT_ServiceDescRec
* FT_ServiceDesc
;
160 /*************************************************************************/
163 /* FT_DEFINE_SERVICEDESCREC1 */
164 /* FT_DEFINE_SERVICEDESCREC2 */
165 /* FT_DEFINE_SERVICEDESCREC3 */
166 /* FT_DEFINE_SERVICEDESCREC4 */
167 /* FT_DEFINE_SERVICEDESCREC5 */
168 /* FT_DEFINE_SERVICEDESCREC6 */
169 /* FT_DEFINE_SERVICEDESCREC7 */
170 /* FT_DEFINE_SERVICEDESCREC8 */
173 /* Used to initialize an array of FT_ServiceDescRec structures. */
175 /* When FT_CONFIG_OPTION_PIC is defined a `create' function needs to */
176 /* be called with a pointer to return an allocated array. As soon as */
177 /* it is no longer needed, a `destroy' function needs to be called to */
178 /* release that allocation. */
180 /* These functions should be manually called from the `pic_init' and */
181 /* `pic_free' functions of your module (see FT_DEFINE_MODULE). */
183 /* When FT_CONFIG_OPTION_PIC is not defined the array will be */
184 /* allocated in the global scope (or the scope where the macro is */
187 #ifndef FT_CONFIG_OPTION_PIC
189 #define FT_DEFINE_SERVICEDESCREC1( class_, \
190 serv_id_1, serv_data_1 ) \
191 static const FT_ServiceDescRec class_[] = \
193 { serv_id_1, serv_data_1 }, \
197 #define FT_DEFINE_SERVICEDESCREC2( class_, \
198 serv_id_1, serv_data_1, \
199 serv_id_2, serv_data_2 ) \
200 static const FT_ServiceDescRec class_[] = \
202 { serv_id_1, serv_data_1 }, \
203 { serv_id_2, serv_data_2 }, \
207 #define FT_DEFINE_SERVICEDESCREC3( class_, \
208 serv_id_1, serv_data_1, \
209 serv_id_2, serv_data_2, \
210 serv_id_3, serv_data_3 ) \
211 static const FT_ServiceDescRec class_[] = \
213 { serv_id_1, serv_data_1 }, \
214 { serv_id_2, serv_data_2 }, \
215 { serv_id_3, serv_data_3 }, \
219 #define FT_DEFINE_SERVICEDESCREC4( class_, \
220 serv_id_1, serv_data_1, \
221 serv_id_2, serv_data_2, \
222 serv_id_3, serv_data_3, \
223 serv_id_4, serv_data_4 ) \
224 static const FT_ServiceDescRec class_[] = \
226 { serv_id_1, serv_data_1 }, \
227 { serv_id_2, serv_data_2 }, \
228 { serv_id_3, serv_data_3 }, \
229 { serv_id_4, serv_data_4 }, \
233 #define FT_DEFINE_SERVICEDESCREC5( class_, \
234 serv_id_1, serv_data_1, \
235 serv_id_2, serv_data_2, \
236 serv_id_3, serv_data_3, \
237 serv_id_4, serv_data_4, \
238 serv_id_5, serv_data_5 ) \
239 static const FT_ServiceDescRec class_[] = \
241 { serv_id_1, serv_data_1 }, \
242 { serv_id_2, serv_data_2 }, \
243 { serv_id_3, serv_data_3 }, \
244 { serv_id_4, serv_data_4 }, \
245 { serv_id_5, serv_data_5 }, \
249 #define FT_DEFINE_SERVICEDESCREC6( class_, \
250 serv_id_1, serv_data_1, \
251 serv_id_2, serv_data_2, \
252 serv_id_3, serv_data_3, \
253 serv_id_4, serv_data_4, \
254 serv_id_5, serv_data_5, \
255 serv_id_6, serv_data_6 ) \
256 static const FT_ServiceDescRec class_[] = \
258 { serv_id_1, serv_data_1 }, \
259 { serv_id_2, serv_data_2 }, \
260 { serv_id_3, serv_data_3 }, \
261 { serv_id_4, serv_data_4 }, \
262 { serv_id_5, serv_data_5 }, \
263 { serv_id_6, serv_data_6 }, \
267 #define FT_DEFINE_SERVICEDESCREC7( class_, \
268 serv_id_1, serv_data_1, \
269 serv_id_2, serv_data_2, \
270 serv_id_3, serv_data_3, \
271 serv_id_4, serv_data_4, \
272 serv_id_5, serv_data_5, \
273 serv_id_6, serv_data_6, \
274 serv_id_7, serv_data_7 ) \
275 static const FT_ServiceDescRec class_[] = \
277 { serv_id_1, serv_data_1 }, \
278 { serv_id_2, serv_data_2 }, \
279 { serv_id_3, serv_data_3 }, \
280 { serv_id_4, serv_data_4 }, \
281 { serv_id_5, serv_data_5 }, \
282 { serv_id_6, serv_data_6 }, \
283 { serv_id_7, serv_data_7 }, \
287 #define FT_DEFINE_SERVICEDESCREC8( class_, \
288 serv_id_1, serv_data_1, \
289 serv_id_2, serv_data_2, \
290 serv_id_3, serv_data_3, \
291 serv_id_4, serv_data_4, \
292 serv_id_5, serv_data_5, \
293 serv_id_6, serv_data_6, \
294 serv_id_7, serv_data_7, \
295 serv_id_8, serv_data_8 ) \
296 static const FT_ServiceDescRec class_[] = \
298 { serv_id_1, serv_data_1 }, \
299 { serv_id_2, serv_data_2 }, \
300 { serv_id_3, serv_data_3 }, \
301 { serv_id_4, serv_data_4 }, \
302 { serv_id_5, serv_data_5 }, \
303 { serv_id_6, serv_data_6 }, \
304 { serv_id_7, serv_data_7 }, \
305 { serv_id_8, serv_data_8 }, \
309 #define FT_DEFINE_SERVICEDESCREC9( class_, \
310 serv_id_1, serv_data_1, \
311 serv_id_2, serv_data_2, \
312 serv_id_3, serv_data_3, \
313 serv_id_4, serv_data_4, \
314 serv_id_5, serv_data_5, \
315 serv_id_6, serv_data_6, \
316 serv_id_7, serv_data_7, \
317 serv_id_8, serv_data_8, \
318 serv_id_9, serv_data_9 ) \
319 static const FT_ServiceDescRec class_[] = \
321 { serv_id_1, serv_data_1 }, \
322 { serv_id_2, serv_data_2 }, \
323 { serv_id_3, serv_data_3 }, \
324 { serv_id_4, serv_data_4 }, \
325 { serv_id_5, serv_data_5 }, \
326 { serv_id_6, serv_data_6 }, \
327 { serv_id_7, serv_data_7 }, \
328 { serv_id_8, serv_data_8 }, \
329 { serv_id_9, serv_data_9 }, \
333 #define FT_DEFINE_SERVICEDESCREC10( class_, \
334 serv_id_1, serv_data_1, \
335 serv_id_2, serv_data_2, \
336 serv_id_3, serv_data_3, \
337 serv_id_4, serv_data_4, \
338 serv_id_5, serv_data_5, \
339 serv_id_6, serv_data_6, \
340 serv_id_7, serv_data_7, \
341 serv_id_8, serv_data_8, \
342 serv_id_9, serv_data_9, \
343 serv_id_10, serv_data_10 ) \
344 static const FT_ServiceDescRec class_[] = \
346 { serv_id_1, serv_data_1 }, \
347 { serv_id_2, serv_data_2 }, \
348 { serv_id_3, serv_data_3 }, \
349 { serv_id_4, serv_data_4 }, \
350 { serv_id_5, serv_data_5 }, \
351 { serv_id_6, serv_data_6 }, \
352 { serv_id_7, serv_data_7 }, \
353 { serv_id_8, serv_data_8 }, \
354 { serv_id_9, serv_data_9 }, \
355 { serv_id_10, serv_data_10 }, \
359 #else /* FT_CONFIG_OPTION_PIC */
361 #define FT_DEFINE_SERVICEDESCREC1( class_, \
362 serv_id_1, serv_data_1 ) \
364 FT_Destroy_Class_ ## class_( FT_Library library, \
365 FT_ServiceDescRec* clazz ) \
367 FT_Memory memory = library->memory; \
375 FT_Create_Class_ ## class_( FT_Library library, \
376 FT_ServiceDescRec** output_class ) \
378 FT_ServiceDescRec* clazz = NULL; \
380 FT_Memory memory = library->memory; \
383 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 2 ) ) \
386 clazz[0].serv_id = serv_id_1; \
387 clazz[0].serv_data = serv_data_1; \
388 clazz[1].serv_id = NULL; \
389 clazz[1].serv_data = NULL; \
391 *output_class = clazz; \
396 #define FT_DEFINE_SERVICEDESCREC2( class_, \
397 serv_id_1, serv_data_1, \
398 serv_id_2, serv_data_2 ) \
400 FT_Destroy_Class_ ## class_( FT_Library library, \
401 FT_ServiceDescRec* clazz ) \
403 FT_Memory memory = library->memory; \
411 FT_Create_Class_ ## class_( FT_Library library, \
412 FT_ServiceDescRec** output_class ) \
414 FT_ServiceDescRec* clazz = NULL; \
416 FT_Memory memory = library->memory; \
419 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 3 ) ) \
422 clazz[0].serv_id = serv_id_1; \
423 clazz[0].serv_data = serv_data_1; \
424 clazz[1].serv_id = serv_id_2; \
425 clazz[1].serv_data = serv_data_2; \
426 clazz[2].serv_id = NULL; \
427 clazz[2].serv_data = NULL; \
429 *output_class = clazz; \
434 #define FT_DEFINE_SERVICEDESCREC3( class_, \
435 serv_id_1, serv_data_1, \
436 serv_id_2, serv_data_2, \
437 serv_id_3, serv_data_3 ) \
439 FT_Destroy_Class_ ## class_( FT_Library library, \
440 FT_ServiceDescRec* clazz ) \
442 FT_Memory memory = library->memory; \
450 FT_Create_Class_ ## class_( FT_Library library, \
451 FT_ServiceDescRec** output_class ) \
453 FT_ServiceDescRec* clazz = NULL; \
455 FT_Memory memory = library->memory; \
458 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 4 ) ) \
461 clazz[0].serv_id = serv_id_1; \
462 clazz[0].serv_data = serv_data_1; \
463 clazz[1].serv_id = serv_id_2; \
464 clazz[1].serv_data = serv_data_2; \
465 clazz[2].serv_id = serv_id_3; \
466 clazz[2].serv_data = serv_data_3; \
467 clazz[3].serv_id = NULL; \
468 clazz[3].serv_data = NULL; \
470 *output_class = clazz; \
475 #define FT_DEFINE_SERVICEDESCREC4( class_, \
476 serv_id_1, serv_data_1, \
477 serv_id_2, serv_data_2, \
478 serv_id_3, serv_data_3, \
479 serv_id_4, serv_data_4 ) \
481 FT_Destroy_Class_ ## class_( FT_Library library, \
482 FT_ServiceDescRec* clazz ) \
484 FT_Memory memory = library->memory; \
492 FT_Create_Class_ ## class_( FT_Library library, \
493 FT_ServiceDescRec** output_class ) \
495 FT_ServiceDescRec* clazz = NULL; \
497 FT_Memory memory = library->memory; \
500 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 5 ) ) \
503 clazz[0].serv_id = serv_id_1; \
504 clazz[0].serv_data = serv_data_1; \
505 clazz[1].serv_id = serv_id_2; \
506 clazz[1].serv_data = serv_data_2; \
507 clazz[2].serv_id = serv_id_3; \
508 clazz[2].serv_data = serv_data_3; \
509 clazz[3].serv_id = serv_id_4; \
510 clazz[3].serv_data = serv_data_4; \
511 clazz[4].serv_id = NULL; \
512 clazz[4].serv_data = NULL; \
514 *output_class = clazz; \
519 #define FT_DEFINE_SERVICEDESCREC5( class_, \
520 serv_id_1, serv_data_1, \
521 serv_id_2, serv_data_2, \
522 serv_id_3, serv_data_3, \
523 serv_id_4, serv_data_4, \
524 serv_id_5, serv_data_5 ) \
526 FT_Destroy_Class_ ## class_( FT_Library library, \
527 FT_ServiceDescRec* clazz ) \
529 FT_Memory memory = library->memory; \
537 FT_Create_Class_ ## class_( FT_Library library, \
538 FT_ServiceDescRec** output_class ) \
540 FT_ServiceDescRec* clazz = NULL; \
542 FT_Memory memory = library->memory; \
545 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 6 ) ) \
548 clazz[0].serv_id = serv_id_1; \
549 clazz[0].serv_data = serv_data_1; \
550 clazz[1].serv_id = serv_id_2; \
551 clazz[1].serv_data = serv_data_2; \
552 clazz[2].serv_id = serv_id_3; \
553 clazz[2].serv_data = serv_data_3; \
554 clazz[3].serv_id = serv_id_4; \
555 clazz[3].serv_data = serv_data_4; \
556 clazz[4].serv_id = serv_id_5; \
557 clazz[4].serv_data = serv_data_5; \
558 clazz[5].serv_id = NULL; \
559 clazz[5].serv_data = NULL; \
561 *output_class = clazz; \
566 #define FT_DEFINE_SERVICEDESCREC6( class_, \
567 serv_id_1, serv_data_1, \
568 serv_id_2, serv_data_2, \
569 serv_id_3, serv_data_3, \
570 serv_id_4, serv_data_4, \
571 serv_id_5, serv_data_5, \
572 serv_id_6, serv_data_6 ) \
574 FT_Destroy_Class_ ## class_( FT_Library library, \
575 FT_ServiceDescRec* clazz ) \
577 FT_Memory memory = library->memory; \
585 FT_Create_Class_ ## class_( FT_Library library, \
586 FT_ServiceDescRec** output_class ) \
588 FT_ServiceDescRec* clazz = NULL; \
590 FT_Memory memory = library->memory; \
593 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 7 ) ) \
596 clazz[0].serv_id = serv_id_1; \
597 clazz[0].serv_data = serv_data_1; \
598 clazz[1].serv_id = serv_id_2; \
599 clazz[1].serv_data = serv_data_2; \
600 clazz[2].serv_id = serv_id_3; \
601 clazz[2].serv_data = serv_data_3; \
602 clazz[3].serv_id = serv_id_4; \
603 clazz[3].serv_data = serv_data_4; \
604 clazz[4].serv_id = serv_id_5; \
605 clazz[4].serv_data = serv_data_5; \
606 clazz[5].serv_id = serv_id_6; \
607 clazz[5].serv_data = serv_data_6; \
608 clazz[6].serv_id = NULL; \
609 clazz[6].serv_data = NULL; \
611 *output_class = clazz; \
616 #define FT_DEFINE_SERVICEDESCREC7( class_, \
617 serv_id_1, serv_data_1, \
618 serv_id_2, serv_data_2, \
619 serv_id_3, serv_data_3, \
620 serv_id_4, serv_data_4, \
621 serv_id_5, serv_data_5, \
622 serv_id_6, serv_data_6, \
623 serv_id_7, serv_data_7 ) \
625 FT_Destroy_Class_ ## class_( FT_Library library, \
626 FT_ServiceDescRec* clazz ) \
628 FT_Memory memory = library->memory; \
636 FT_Create_Class_ ## class_( FT_Library library, \
637 FT_ServiceDescRec** output_class ) \
639 FT_ServiceDescRec* clazz = NULL; \
641 FT_Memory memory = library->memory; \
644 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 8 ) ) \
647 clazz[0].serv_id = serv_id_1; \
648 clazz[0].serv_data = serv_data_1; \
649 clazz[1].serv_id = serv_id_2; \
650 clazz[1].serv_data = serv_data_2; \
651 clazz[2].serv_id = serv_id_3; \
652 clazz[2].serv_data = serv_data_3; \
653 clazz[3].serv_id = serv_id_4; \
654 clazz[3].serv_data = serv_data_4; \
655 clazz[4].serv_id = serv_id_5; \
656 clazz[4].serv_data = serv_data_5; \
657 clazz[5].serv_id = serv_id_6; \
658 clazz[5].serv_data = serv_data_6; \
659 clazz[6].serv_id = serv_id_7; \
660 clazz[6].serv_data = serv_data_7; \
661 clazz[7].serv_id = NULL; \
662 clazz[7].serv_data = NULL; \
664 *output_class = clazz; \
669 #define FT_DEFINE_SERVICEDESCREC8( class_, \
670 serv_id_1, serv_data_1, \
671 serv_id_2, serv_data_2, \
672 serv_id_3, serv_data_3, \
673 serv_id_4, serv_data_4, \
674 serv_id_5, serv_data_5, \
675 serv_id_6, serv_data_6, \
676 serv_id_7, serv_data_7, \
677 serv_id_8, serv_data_8 ) \
679 FT_Destroy_Class_ ## class_( FT_Library library, \
680 FT_ServiceDescRec* clazz ) \
682 FT_Memory memory = library->memory; \
690 FT_Create_Class_ ## class_( FT_Library library, \
691 FT_ServiceDescRec** output_class ) \
693 FT_ServiceDescRec* clazz = NULL; \
695 FT_Memory memory = library->memory; \
698 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 9 ) ) \
701 clazz[0].serv_id = serv_id_1; \
702 clazz[0].serv_data = serv_data_1; \
703 clazz[1].serv_id = serv_id_2; \
704 clazz[1].serv_data = serv_data_2; \
705 clazz[2].serv_id = serv_id_3; \
706 clazz[2].serv_data = serv_data_3; \
707 clazz[3].serv_id = serv_id_4; \
708 clazz[3].serv_data = serv_data_4; \
709 clazz[4].serv_id = serv_id_5; \
710 clazz[4].serv_data = serv_data_5; \
711 clazz[5].serv_id = serv_id_6; \
712 clazz[5].serv_data = serv_data_6; \
713 clazz[6].serv_id = serv_id_7; \
714 clazz[6].serv_data = serv_data_7; \
715 clazz[7].serv_id = serv_id_8; \
716 clazz[7].serv_data = serv_data_8; \
717 clazz[8].serv_id = NULL; \
718 clazz[8].serv_data = NULL; \
720 *output_class = clazz; \
725 #define FT_DEFINE_SERVICEDESCREC9( class_, \
726 serv_id_1, serv_data_1, \
727 serv_id_2, serv_data_2, \
728 serv_id_3, serv_data_3, \
729 serv_id_4, serv_data_4, \
730 serv_id_5, serv_data_5, \
731 serv_id_6, serv_data_6, \
732 serv_id_7, serv_data_7, \
733 serv_id_8, serv_data_8, \
734 serv_id_9, serv_data_9 ) \
736 FT_Destroy_Class_ ## class_( FT_Library library, \
737 FT_ServiceDescRec* clazz ) \
739 FT_Memory memory = library->memory; \
747 FT_Create_Class_ ## class_( FT_Library library, \
748 FT_ServiceDescRec** output_class ) \
750 FT_ServiceDescRec* clazz = NULL; \
752 FT_Memory memory = library->memory; \
755 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 10 ) ) \
758 clazz[0].serv_id = serv_id_1; \
759 clazz[0].serv_data = serv_data_1; \
760 clazz[1].serv_id = serv_id_2; \
761 clazz[1].serv_data = serv_data_2; \
762 clazz[2].serv_id = serv_id_3; \
763 clazz[2].serv_data = serv_data_3; \
764 clazz[3].serv_id = serv_id_4; \
765 clazz[3].serv_data = serv_data_4; \
766 clazz[4].serv_id = serv_id_5; \
767 clazz[4].serv_data = serv_data_5; \
768 clazz[5].serv_id = serv_id_6; \
769 clazz[5].serv_data = serv_data_6; \
770 clazz[6].serv_id = serv_id_7; \
771 clazz[6].serv_data = serv_data_7; \
772 clazz[7].serv_id = serv_id_8; \
773 clazz[7].serv_data = serv_data_8; \
774 clazz[8].serv_id = serv_id_9; \
775 clazz[8].serv_data = serv_data_9; \
776 clazz[9].serv_id = NULL; \
777 clazz[9].serv_data = NULL; \
779 *output_class = clazz; \
784 #define FT_DEFINE_SERVICEDESCREC10( class_, \
785 serv_id_1, serv_data_1, \
786 serv_id_2, serv_data_2, \
787 serv_id_3, serv_data_3, \
788 serv_id_4, serv_data_4, \
789 serv_id_5, serv_data_5, \
790 serv_id_6, serv_data_6, \
791 serv_id_7, serv_data_7, \
792 serv_id_8, serv_data_8, \
793 serv_id_9, serv_data_9, \
794 serv_id_10, serv_data_10 ) \
796 FT_Destroy_Class_ ## class_( FT_Library library, \
797 FT_ServiceDescRec* clazz ) \
799 FT_Memory memory = library->memory; \
807 FT_Create_Class_ ## class_( FT_Library library, \
808 FT_ServiceDescRec** output_class ) \
810 FT_ServiceDescRec* clazz = NULL; \
812 FT_Memory memory = library->memory; \
815 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 11 ) ) \
818 clazz[ 0].serv_id = serv_id_1; \
819 clazz[ 0].serv_data = serv_data_1; \
820 clazz[ 1].serv_id = serv_id_2; \
821 clazz[ 1].serv_data = serv_data_2; \
822 clazz[ 2].serv_id = serv_id_3; \
823 clazz[ 2].serv_data = serv_data_3; \
824 clazz[ 3].serv_id = serv_id_4; \
825 clazz[ 3].serv_data = serv_data_4; \
826 clazz[ 4].serv_id = serv_id_5; \
827 clazz[ 4].serv_data = serv_data_5; \
828 clazz[ 5].serv_id = serv_id_6; \
829 clazz[ 5].serv_data = serv_data_6; \
830 clazz[ 6].serv_id = serv_id_7; \
831 clazz[ 6].serv_data = serv_data_7; \
832 clazz[ 7].serv_id = serv_id_8; \
833 clazz[ 7].serv_data = serv_data_8; \
834 clazz[ 8].serv_id = serv_id_9; \
835 clazz[ 8].serv_data = serv_data_9; \
836 clazz[ 9].serv_id = serv_id_10; \
837 clazz[ 9].serv_data = serv_data_10; \
838 clazz[10].serv_id = NULL; \
839 clazz[10].serv_data = NULL; \
841 *output_class = clazz; \
846 #endif /* FT_CONFIG_OPTION_PIC */
850 * Parse a list of FT_ServiceDescRec descriptors and look for
851 * a specific service by ID. Note that the last element in the
852 * array must be { NULL, NULL }, and that the function should
853 * return NULL if the service isn't available.
855 * This function can be used by modules to implement their
856 * `get_service' method.
858 FT_BASE( FT_Pointer
)
859 ft_service_list_lookup( FT_ServiceDesc service_descriptors
,
860 const char* service_id
);
863 /*************************************************************************/
864 /*************************************************************************/
866 /***** S E R V I C E S C A C H E *****/
868 /*************************************************************************/
869 /*************************************************************************/
872 * This structure is used to store a cache for several frequently used
873 * services. It is the type of `face->internal->services'. You
874 * should only use FT_FACE_LOOKUP_SERVICE to access it.
876 * All fields should have the type FT_Pointer to relax compilation
877 * dependencies. We assume the developer isn't completely stupid.
879 * Each field must be named `service_XXXX' where `XXX' corresponds to
880 * the correct FT_SERVICE_ID_XXXX macro. See the definition of
881 * FT_FACE_LOOKUP_SERVICE below how this is implemented.
884 typedef struct FT_ServiceCacheRec_
886 FT_Pointer service_POSTSCRIPT_FONT_NAME
;
887 FT_Pointer service_MULTI_MASTERS
;
888 FT_Pointer service_METRICS_VARIATIONS
;
889 FT_Pointer service_GLYPH_DICT
;
890 FT_Pointer service_PFR_METRICS
;
891 FT_Pointer service_WINFNT
;
893 } FT_ServiceCacheRec
, *FT_ServiceCache
;
897 * A magic number used within the services cache.
900 /* ensure that value `1' has the same width as a pointer */
901 #define FT_SERVICE_UNAVAILABLE ((FT_Pointer)~(FT_PtrDist)1)
906 * FT_FACE_LOOKUP_SERVICE
909 * This macro is used to look up a service from a face's driver module
914 * The source face handle containing the cache.
917 * The field name in the cache.
924 * A variable receiving the service data. NULL if not available.
928 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \
931 FT_Pointer* Pptr = (FT_Pointer*)&(ptr); \
934 svc = FT_FACE( face )->internal->services. service_ ## id; \
935 if ( svc == FT_SERVICE_UNAVAILABLE ) \
937 else if ( svc == NULL ) \
939 FT_FACE_FIND_SERVICE( face, svc, id ); \
941 FT_FACE( face )->internal->services. service_ ## id = \
942 (FT_Pointer)( svc != NULL ? svc \
943 : FT_SERVICE_UNAVAILABLE ); \
950 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \
955 svc = FT_FACE( face )->internal->services. service_ ## id; \
956 if ( svc == FT_SERVICE_UNAVAILABLE ) \
958 else if ( svc == NULL ) \
960 FT_FACE_FIND_SERVICE( face, svc, id ); \
962 FT_FACE( face )->internal->services. service_ ## id = \
963 (FT_Pointer)( svc != NULL ? svc \
964 : FT_SERVICE_UNAVAILABLE ); \
972 * A macro used to define new service structure types.
975 #define FT_DEFINE_SERVICE( name ) \
976 typedef struct FT_Service_ ## name ## Rec_ \
977 FT_Service_ ## name ## Rec ; \
978 typedef struct FT_Service_ ## name ## Rec_ \
979 const * FT_Service_ ## name ; \
980 struct FT_Service_ ## name ## Rec_
985 * The header files containing the services.
988 #define FT_SERVICE_BDF_H <freetype/internal/services/svbdf.h>
989 #define FT_SERVICE_CFF_TABLE_LOAD_H <freetype/internal/services/svcfftl.h>
990 #define FT_SERVICE_CID_H <freetype/internal/services/svcid.h>
991 #define FT_SERVICE_FONT_FORMAT_H <freetype/internal/services/svfntfmt.h>
992 #define FT_SERVICE_GLYPH_DICT_H <freetype/internal/services/svgldict.h>
993 #define FT_SERVICE_GX_VALIDATE_H <freetype/internal/services/svgxval.h>
994 #define FT_SERVICE_KERNING_H <freetype/internal/services/svkern.h>
995 #define FT_SERVICE_METRICS_VARIATIONS_H <freetype/internal/services/svmetric.h>
996 #define FT_SERVICE_MULTIPLE_MASTERS_H <freetype/internal/services/svmm.h>
997 #define FT_SERVICE_OPENTYPE_VALIDATE_H <freetype/internal/services/svotval.h>
998 #define FT_SERVICE_PFR_H <freetype/internal/services/svpfr.h>
999 #define FT_SERVICE_POSTSCRIPT_CMAPS_H <freetype/internal/services/svpscmap.h>
1000 #define FT_SERVICE_POSTSCRIPT_INFO_H <freetype/internal/services/svpsinfo.h>
1001 #define FT_SERVICE_POSTSCRIPT_NAME_H <freetype/internal/services/svpostnm.h>
1002 #define FT_SERVICE_PROPERTIES_H <freetype/internal/services/svprop.h>
1003 #define FT_SERVICE_SFNT_H <freetype/internal/services/svsfnt.h>
1004 #define FT_SERVICE_TRUETYPE_ENGINE_H <freetype/internal/services/svtteng.h>
1005 #define FT_SERVICE_TRUETYPE_GLYF_H <freetype/internal/services/svttglyf.h>
1006 #define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h>
1007 #define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h>
1013 #endif /* FTSERV_H_ */