1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftserv.h                                                               */
4 /*                                                                         */
5 /*    The FreeType services (specification only).                          */
6 /*                                                                         */
7 /*  Copyright 2003-2017 by                                                 */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9 /*                                                                         */
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.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17 
18   /*************************************************************************/
19   /*                                                                       */
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.   */
23   /*                                                                       */
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).         */
27   /*                                                                       */
28   /*************************************************************************/
29 
30 
31 #ifndef FTSERV_H_
32 #define FTSERV_H_
33 
34 
35 FT_BEGIN_HEADER
36 
37   /*
38    * @macro:
39    *   FT_FACE_FIND_SERVICE
40    *
41    * @description:
42    *   This macro is used to look up a service from a face's driver module.
43    *
44    * @input:
45    *   face ::
46    *     The source face handle.
47    *
48    *   id ::
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
52    *     `FT_SERVICE_ID_'.
53    *
54    * @output:
55    *   ptr ::
56    *     A variable that receives the service pointer.  Will be NULL
57    *     if not found.
58    */
59 #ifdef __cplusplus
60 
61 #define FT_FACE_FIND_SERVICE( face, ptr, id )                               \
62   FT_BEGIN_STMNT                                                            \
63     FT_Module    module = FT_MODULE( FT_FACE( face )->driver );             \
64     FT_Pointer   _tmp_  = NULL;                                             \
65     FT_Pointer*  _pptr_ = (FT_Pointer*)&(ptr);                              \
66                                                                             \
67                                                                             \
68     if ( module->clazz->get_interface )                                     \
69       _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
70     *_pptr_ = _tmp_;                                                        \
71   FT_END_STMNT
72 
73 #else /* !C++ */
74 
75 #define FT_FACE_FIND_SERVICE( face, ptr, id )                               \
76   FT_BEGIN_STMNT                                                            \
77     FT_Module   module = FT_MODULE( FT_FACE( face )->driver );              \
78     FT_Pointer  _tmp_  = NULL;                                              \
79                                                                             \
80     if ( module->clazz->get_interface )                                     \
81       _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
82     ptr = _tmp_;                                                            \
83   FT_END_STMNT
84 
85 #endif /* !C++ */
86 
87 
88   /*
89    * @macro:
90    *   FT_FACE_FIND_GLOBAL_SERVICE
91    *
92    * @description:
93    *   This macro is used to look up a service from all modules.
94    *
95    * @input:
96    *   face ::
97    *     The source face handle.
98    *
99    *   id ::
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
103    *     `FT_SERVICE_ID_'.
104    *
105    * @output:
106    *   ptr ::
107    *     A variable that receives the service pointer.  Will be NULL
108    *     if not found.
109    */
110 #ifdef __cplusplus
111 
112 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )                  \
113   FT_BEGIN_STMNT                                                      \
114     FT_Module    module = FT_MODULE( FT_FACE( face )->driver );       \
115     FT_Pointer   _tmp_;                                               \
116     FT_Pointer*  _pptr_ = (FT_Pointer*)&(ptr);                        \
117                                                                       \
118                                                                       \
119     _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
120     *_pptr_ = _tmp_;                                                  \
121   FT_END_STMNT
122 
123 #else /* !C++ */
124 
125 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )                  \
126   FT_BEGIN_STMNT                                                      \
127     FT_Module   module = FT_MODULE( FT_FACE( face )->driver );        \
128     FT_Pointer  _tmp_;                                                \
129                                                                       \
130                                                                       \
131     _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
132     ptr   = _tmp_;                                                    \
133   FT_END_STMNT
134 
135 #endif /* !C++ */
136 
137 
138   /*************************************************************************/
139   /*************************************************************************/
140   /*****                                                               *****/
141   /*****         S E R V I C E   D E S C R I P T O R S                 *****/
142   /*****                                                               *****/
143   /*************************************************************************/
144   /*************************************************************************/
145 
146   /*
147    *  The following structure is used to _describe_ a given service
148    *  to the library.  This is useful to build simple static service lists.
149    */
150   typedef struct  FT_ServiceDescRec_
151   {
152     const char*  serv_id;     /* service name         */
153     const void*  serv_data;   /* service pointer/data */
154 
155   } FT_ServiceDescRec;
156 
157   typedef const FT_ServiceDescRec*  FT_ServiceDesc;
158 
159 
160   /*************************************************************************/
161   /*                                                                       */
162   /* <Macro>                                                               */
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                                          */
171   /*                                                                       */
172   /* <Description>                                                         */
173   /*    Used to initialize an array of FT_ServiceDescRec structures.       */
174   /*                                                                       */
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.                                           */
179   /*                                                                       */
180   /*    These functions should be manually called from the `pic_init' and  */
181   /*    `pic_free' functions of your module (see FT_DEFINE_MODULE).        */
182   /*                                                                       */
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     */
185   /*    used).                                                             */
186   /*                                                                       */
187 #ifndef FT_CONFIG_OPTION_PIC
188 
189 #define FT_DEFINE_SERVICEDESCREC1( class_,                                  \
190                                    serv_id_1, serv_data_1 )                 \
191   static const FT_ServiceDescRec  class_[] =                                \
192   {                                                                         \
193     { serv_id_1, serv_data_1 },                                             \
194     { NULL, NULL }                                                          \
195   };
196 
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_[] =                                \
201   {                                                                         \
202     { serv_id_1, serv_data_1 },                                             \
203     { serv_id_2, serv_data_2 },                                             \
204     { NULL, NULL }                                                          \
205   };
206 
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_[] =                                \
212   {                                                                         \
213     { serv_id_1, serv_data_1 },                                             \
214     { serv_id_2, serv_data_2 },                                             \
215     { serv_id_3, serv_data_3 },                                             \
216     { NULL, NULL }                                                          \
217   };
218 
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_[] =                                \
225   {                                                                         \
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 },                                             \
230     { NULL, NULL }                                                          \
231   };
232 
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_[] =                                \
240   {                                                                         \
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 },                                             \
246     { NULL, NULL }                                                          \
247   };
248 
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_[] =                                \
257   {                                                                         \
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 },                                             \
264     { NULL, NULL }                                                          \
265   };
266 
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_[] =                                \
276   {                                                                         \
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 },                                             \
284     { NULL, NULL }                                                          \
285   };
286 
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_[] =                                \
297   {                                                                         \
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 },                                             \
306     { NULL, NULL }                                                          \
307   };
308 
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_[] =                                \
320   {                                                                         \
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 },                                             \
330     { NULL, NULL }                                                          \
331   };
332 
333 #else /* FT_CONFIG_OPTION_PIC */
334 
335 #define FT_DEFINE_SERVICEDESCREC1( class_,                                  \
336                                    serv_id_1, serv_data_1 )                 \
337   void                                                                      \
338   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
339                                FT_ServiceDescRec*  clazz )                  \
340   {                                                                         \
341     FT_Memory  memory = library->memory;                                    \
342                                                                             \
343                                                                             \
344     if ( clazz )                                                            \
345       FT_FREE( clazz );                                                     \
346   }                                                                         \
347                                                                             \
348   FT_Error                                                                  \
349   FT_Create_Class_ ## class_( FT_Library           library,                 \
350                               FT_ServiceDescRec**  output_class )           \
351   {                                                                         \
352     FT_ServiceDescRec*  clazz  = NULL;                                      \
353     FT_Error            error;                                              \
354     FT_Memory           memory = library->memory;                           \
355                                                                             \
356                                                                             \
357     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 2 ) )                         \
358       return error;                                                         \
359                                                                             \
360     clazz[0].serv_id   = serv_id_1;                                         \
361     clazz[0].serv_data = serv_data_1;                                       \
362     clazz[1].serv_id   = NULL;                                              \
363     clazz[1].serv_data = NULL;                                              \
364                                                                             \
365     *output_class = clazz;                                                  \
366                                                                             \
367     return FT_Err_Ok;                                                       \
368   }
369 
370 #define FT_DEFINE_SERVICEDESCREC2( class_,                                  \
371                                    serv_id_1, serv_data_1,                  \
372                                    serv_id_2, serv_data_2 )                 \
373   void                                                                      \
374   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
375                                FT_ServiceDescRec*  clazz )                  \
376   {                                                                         \
377     FT_Memory  memory = library->memory;                                    \
378                                                                             \
379                                                                             \
380     if ( clazz )                                                            \
381       FT_FREE( clazz );                                                     \
382   }                                                                         \
383                                                                             \
384   FT_Error                                                                  \
385   FT_Create_Class_ ## class_( FT_Library           library,                 \
386                               FT_ServiceDescRec**  output_class )           \
387   {                                                                         \
388     FT_ServiceDescRec*  clazz  = NULL;                                      \
389     FT_Error            error;                                              \
390     FT_Memory           memory = library->memory;                           \
391                                                                             \
392                                                                             \
393     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 3 ) )                         \
394       return error;                                                         \
395                                                                             \
396     clazz[0].serv_id   = serv_id_1;                                         \
397     clazz[0].serv_data = serv_data_1;                                       \
398     clazz[1].serv_id   = serv_id_2;                                         \
399     clazz[1].serv_data = serv_data_2;                                       \
400     clazz[2].serv_id   = NULL;                                              \
401     clazz[2].serv_data = NULL;                                              \
402                                                                             \
403     *output_class = clazz;                                                  \
404                                                                             \
405     return FT_Err_Ok;                                                       \
406   }
407 
408 #define FT_DEFINE_SERVICEDESCREC3( class_,                                  \
409                                    serv_id_1, serv_data_1,                  \
410                                    serv_id_2, serv_data_2,                  \
411                                    serv_id_3, serv_data_3 )                 \
412   void                                                                      \
413   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
414                                FT_ServiceDescRec*  clazz )                  \
415   {                                                                         \
416     FT_Memory  memory = library->memory;                                    \
417                                                                             \
418                                                                             \
419     if ( clazz )                                                            \
420       FT_FREE( clazz );                                                     \
421   }                                                                         \
422                                                                             \
423   FT_Error                                                                  \
424   FT_Create_Class_ ## class_( FT_Library           library,                 \
425                               FT_ServiceDescRec**  output_class )           \
426   {                                                                         \
427     FT_ServiceDescRec*  clazz  = NULL;                                      \
428     FT_Error            error;                                              \
429     FT_Memory           memory = library->memory;                           \
430                                                                             \
431                                                                             \
432     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 4 ) )                         \
433       return error;                                                         \
434                                                                             \
435     clazz[0].serv_id   = serv_id_1;                                         \
436     clazz[0].serv_data = serv_data_1;                                       \
437     clazz[1].serv_id   = serv_id_2;                                         \
438     clazz[1].serv_data = serv_data_2;                                       \
439     clazz[2].serv_id   = serv_id_3;                                         \
440     clazz[2].serv_data = serv_data_3;                                       \
441     clazz[3].serv_id   = NULL;                                              \
442     clazz[3].serv_data = NULL;                                              \
443                                                                             \
444     *output_class = clazz;                                                  \
445                                                                             \
446     return FT_Err_Ok;                                                       \
447   }
448 
449 #define FT_DEFINE_SERVICEDESCREC4( class_,                                  \
450                                    serv_id_1, serv_data_1,                  \
451                                    serv_id_2, serv_data_2,                  \
452                                    serv_id_3, serv_data_3,                  \
453                                    serv_id_4, serv_data_4 )                 \
454   void                                                                      \
455   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
456                                FT_ServiceDescRec*  clazz )                  \
457   {                                                                         \
458     FT_Memory  memory = library->memory;                                    \
459                                                                             \
460                                                                             \
461     if ( clazz )                                                            \
462       FT_FREE( clazz );                                                     \
463   }                                                                         \
464                                                                             \
465   FT_Error                                                                  \
466   FT_Create_Class_ ## class_( FT_Library           library,                 \
467                               FT_ServiceDescRec**  output_class )           \
468   {                                                                         \
469     FT_ServiceDescRec*  clazz  = NULL;                                      \
470     FT_Error            error;                                              \
471     FT_Memory           memory = library->memory;                           \
472                                                                             \
473                                                                             \
474     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 5 ) )                         \
475       return error;                                                         \
476                                                                             \
477     clazz[0].serv_id   = serv_id_1;                                         \
478     clazz[0].serv_data = serv_data_1;                                       \
479     clazz[1].serv_id   = serv_id_2;                                         \
480     clazz[1].serv_data = serv_data_2;                                       \
481     clazz[2].serv_id   = serv_id_3;                                         \
482     clazz[2].serv_data = serv_data_3;                                       \
483     clazz[3].serv_id   = serv_id_4;                                         \
484     clazz[3].serv_data = serv_data_4;                                       \
485     clazz[4].serv_id   = NULL;                                              \
486     clazz[4].serv_data = NULL;                                              \
487                                                                             \
488     *output_class = clazz;                                                  \
489                                                                             \
490     return FT_Err_Ok;                                                       \
491   }
492 
493 #define FT_DEFINE_SERVICEDESCREC5( class_,                                  \
494                                    serv_id_1, serv_data_1,                  \
495                                    serv_id_2, serv_data_2,                  \
496                                    serv_id_3, serv_data_3,                  \
497                                    serv_id_4, serv_data_4,                  \
498                                    serv_id_5, serv_data_5 )                 \
499   void                                                                      \
500   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
501                                FT_ServiceDescRec*  clazz )                  \
502   {                                                                         \
503     FT_Memory  memory = library->memory;                                    \
504                                                                             \
505                                                                             \
506     if ( clazz )                                                            \
507       FT_FREE( clazz );                                                     \
508   }                                                                         \
509                                                                             \
510   FT_Error                                                                  \
511   FT_Create_Class_ ## class_( FT_Library           library,                 \
512                               FT_ServiceDescRec**  output_class )           \
513   {                                                                         \
514     FT_ServiceDescRec*  clazz  = NULL;                                      \
515     FT_Error            error;                                              \
516     FT_Memory           memory = library->memory;                           \
517                                                                             \
518                                                                             \
519     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 6 ) )                         \
520       return error;                                                         \
521                                                                             \
522     clazz[0].serv_id   = serv_id_1;                                         \
523     clazz[0].serv_data = serv_data_1;                                       \
524     clazz[1].serv_id   = serv_id_2;                                         \
525     clazz[1].serv_data = serv_data_2;                                       \
526     clazz[2].serv_id   = serv_id_3;                                         \
527     clazz[2].serv_data = serv_data_3;                                       \
528     clazz[3].serv_id   = serv_id_4;                                         \
529     clazz[3].serv_data = serv_data_4;                                       \
530     clazz[4].serv_id   = serv_id_5;                                         \
531     clazz[4].serv_data = serv_data_5;                                       \
532     clazz[5].serv_id   = NULL;                                              \
533     clazz[5].serv_data = NULL;                                              \
534                                                                             \
535     *output_class = clazz;                                                  \
536                                                                             \
537     return FT_Err_Ok;                                                       \
538   }
539 
540 #define FT_DEFINE_SERVICEDESCREC6( class_,                                  \
541                                    serv_id_1, serv_data_1,                  \
542                                    serv_id_2, serv_data_2,                  \
543                                    serv_id_3, serv_data_3,                  \
544                                    serv_id_4, serv_data_4,                  \
545                                    serv_id_5, serv_data_5,                  \
546                                    serv_id_6, serv_data_6 )                 \
547   void                                                                      \
548   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
549                                FT_ServiceDescRec*  clazz )                  \
550   {                                                                         \
551     FT_Memory  memory = library->memory;                                    \
552                                                                             \
553                                                                             \
554     if ( clazz )                                                            \
555       FT_FREE( clazz );                                                     \
556   }                                                                         \
557                                                                             \
558   FT_Error                                                                  \
559   FT_Create_Class_ ## class_( FT_Library           library,                 \
560                               FT_ServiceDescRec**  output_class)            \
561   {                                                                         \
562     FT_ServiceDescRec*  clazz  = NULL;                                      \
563     FT_Error            error;                                              \
564     FT_Memory           memory = library->memory;                           \
565                                                                             \
566                                                                             \
567     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 7 ) )                         \
568       return error;                                                         \
569                                                                             \
570     clazz[0].serv_id   = serv_id_1;                                         \
571     clazz[0].serv_data = serv_data_1;                                       \
572     clazz[1].serv_id   = serv_id_2;                                         \
573     clazz[1].serv_data = serv_data_2;                                       \
574     clazz[2].serv_id   = serv_id_3;                                         \
575     clazz[2].serv_data = serv_data_3;                                       \
576     clazz[3].serv_id   = serv_id_4;                                         \
577     clazz[3].serv_data = serv_data_4;                                       \
578     clazz[4].serv_id   = serv_id_5;                                         \
579     clazz[4].serv_data = serv_data_5;                                       \
580     clazz[5].serv_id   = serv_id_6;                                         \
581     clazz[5].serv_data = serv_data_6;                                       \
582     clazz[6].serv_id   = NULL;                                              \
583     clazz[6].serv_data = NULL;                                              \
584                                                                             \
585     *output_class = clazz;                                                  \
586                                                                             \
587     return FT_Err_Ok;                                                       \
588   }
589 
590 #define FT_DEFINE_SERVICEDESCREC7( class_,                                  \
591                                    serv_id_1, serv_data_1,                  \
592                                    serv_id_2, serv_data_2,                  \
593                                    serv_id_3, serv_data_3,                  \
594                                    serv_id_4, serv_data_4,                  \
595                                    serv_id_5, serv_data_5,                  \
596                                    serv_id_6, serv_data_6,                  \
597                                    serv_id_7, serv_data_7 )                 \
598   void                                                                      \
599   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
600                                FT_ServiceDescRec*  clazz )                  \
601   {                                                                         \
602     FT_Memory  memory = library->memory;                                    \
603                                                                             \
604                                                                             \
605     if ( clazz )                                                            \
606       FT_FREE( clazz );                                                     \
607   }                                                                         \
608                                                                             \
609   FT_Error                                                                  \
610   FT_Create_Class_ ## class_( FT_Library           library,                 \
611                               FT_ServiceDescRec**  output_class)            \
612   {                                                                         \
613     FT_ServiceDescRec*  clazz  = NULL;                                      \
614     FT_Error            error;                                              \
615     FT_Memory           memory = library->memory;                           \
616                                                                             \
617                                                                             \
618     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 8 ) )                         \
619       return error;                                                         \
620                                                                             \
621     clazz[0].serv_id   = serv_id_1;                                         \
622     clazz[0].serv_data = serv_data_1;                                       \
623     clazz[1].serv_id   = serv_id_2;                                         \
624     clazz[1].serv_data = serv_data_2;                                       \
625     clazz[2].serv_id   = serv_id_3;                                         \
626     clazz[2].serv_data = serv_data_3;                                       \
627     clazz[3].serv_id   = serv_id_4;                                         \
628     clazz[3].serv_data = serv_data_4;                                       \
629     clazz[4].serv_id   = serv_id_5;                                         \
630     clazz[4].serv_data = serv_data_5;                                       \
631     clazz[5].serv_id   = serv_id_6;                                         \
632     clazz[5].serv_data = serv_data_6;                                       \
633     clazz[6].serv_id   = serv_id_7;                                         \
634     clazz[6].serv_data = serv_data_7;                                       \
635     clazz[7].serv_id   = NULL;                                              \
636     clazz[7].serv_data = NULL;                                              \
637                                                                             \
638     *output_class = clazz;                                                  \
639                                                                             \
640     return FT_Err_Ok;                                                       \
641   }
642 
643 #define FT_DEFINE_SERVICEDESCREC8( class_,                                  \
644                                    serv_id_1, serv_data_1,                  \
645                                    serv_id_2, serv_data_2,                  \
646                                    serv_id_3, serv_data_3,                  \
647                                    serv_id_4, serv_data_4,                  \
648                                    serv_id_5, serv_data_5,                  \
649                                    serv_id_6, serv_data_6,                  \
650                                    serv_id_7, serv_data_7,                  \
651                                    serv_id_8, serv_data_8 )                 \
652   void                                                                      \
653   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
654                                FT_ServiceDescRec*  clazz )                  \
655   {                                                                         \
656     FT_Memory  memory = library->memory;                                    \
657                                                                             \
658                                                                             \
659     if ( clazz )                                                            \
660       FT_FREE( clazz );                                                     \
661   }                                                                         \
662                                                                             \
663   FT_Error                                                                  \
664   FT_Create_Class_ ## class_( FT_Library           library,                 \
665                               FT_ServiceDescRec**  output_class)            \
666   {                                                                         \
667     FT_ServiceDescRec*  clazz  = NULL;                                      \
668     FT_Error            error;                                              \
669     FT_Memory           memory = library->memory;                           \
670                                                                             \
671                                                                             \
672     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 9 ) )                         \
673       return error;                                                         \
674                                                                             \
675     clazz[0].serv_id   = serv_id_1;                                         \
676     clazz[0].serv_data = serv_data_1;                                       \
677     clazz[1].serv_id   = serv_id_2;                                         \
678     clazz[1].serv_data = serv_data_2;                                       \
679     clazz[2].serv_id   = serv_id_3;                                         \
680     clazz[2].serv_data = serv_data_3;                                       \
681     clazz[3].serv_id   = serv_id_4;                                         \
682     clazz[3].serv_data = serv_data_4;                                       \
683     clazz[4].serv_id   = serv_id_5;                                         \
684     clazz[4].serv_data = serv_data_5;                                       \
685     clazz[5].serv_id   = serv_id_6;                                         \
686     clazz[5].serv_data = serv_data_6;                                       \
687     clazz[6].serv_id   = serv_id_7;                                         \
688     clazz[6].serv_data = serv_data_7;                                       \
689     clazz[7].serv_id   = serv_id_8;                                         \
690     clazz[7].serv_data = serv_data_8;                                       \
691     clazz[8].serv_id   = NULL;                                              \
692     clazz[8].serv_data = NULL;                                              \
693                                                                             \
694     *output_class = clazz;                                                  \
695                                                                             \
696     return FT_Err_Ok;                                                       \
697   }
698 
699 #define FT_DEFINE_SERVICEDESCREC9( class_,                                  \
700                                    serv_id_1, serv_data_1,                  \
701                                    serv_id_2, serv_data_2,                  \
702                                    serv_id_3, serv_data_3,                  \
703                                    serv_id_4, serv_data_4,                  \
704                                    serv_id_5, serv_data_5,                  \
705                                    serv_id_6, serv_data_6,                  \
706                                    serv_id_7, serv_data_7,                  \
707                                    serv_id_8, serv_data_8,                  \
708                                    serv_id_9, serv_data_9 )                 \
709   void                                                                      \
710   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
711                                FT_ServiceDescRec*  clazz )                  \
712   {                                                                         \
713     FT_Memory  memory = library->memory;                                    \
714                                                                             \
715                                                                             \
716     if ( clazz )                                                            \
717       FT_FREE( clazz );                                                     \
718   }                                                                         \
719                                                                             \
720   FT_Error                                                                  \
721   FT_Create_Class_ ## class_( FT_Library           library,                 \
722                               FT_ServiceDescRec**  output_class)            \
723   {                                                                         \
724     FT_ServiceDescRec*  clazz  = NULL;                                      \
725     FT_Error            error;                                              \
726     FT_Memory           memory = library->memory;                           \
727                                                                             \
728                                                                             \
729     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 10 ) )                        \
730       return error;                                                         \
731                                                                             \
732     clazz[0].serv_id   = serv_id_1;                                         \
733     clazz[0].serv_data = serv_data_1;                                       \
734     clazz[1].serv_id   = serv_id_2;                                         \
735     clazz[1].serv_data = serv_data_2;                                       \
736     clazz[2].serv_id   = serv_id_3;                                         \
737     clazz[2].serv_data = serv_data_3;                                       \
738     clazz[3].serv_id   = serv_id_4;                                         \
739     clazz[3].serv_data = serv_data_4;                                       \
740     clazz[4].serv_id   = serv_id_5;                                         \
741     clazz[4].serv_data = serv_data_5;                                       \
742     clazz[5].serv_id   = serv_id_6;                                         \
743     clazz[5].serv_data = serv_data_6;                                       \
744     clazz[6].serv_id   = serv_id_7;                                         \
745     clazz[6].serv_data = serv_data_7;                                       \
746     clazz[7].serv_id   = serv_id_8;                                         \
747     clazz[7].serv_data = serv_data_8;                                       \
748     clazz[8].serv_id   = serv_id_9;                                         \
749     clazz[8].serv_data = serv_data_9;                                       \
750     clazz[9].serv_id   = NULL;                                              \
751     clazz[9].serv_data = NULL;                                              \
752                                                                             \
753     *output_class = clazz;                                                  \
754                                                                             \
755     return FT_Err_Ok;                                                       \
756   }
757 
758 #endif /* FT_CONFIG_OPTION_PIC */
759 
760 
761   /*
762    *  Parse a list of FT_ServiceDescRec descriptors and look for
763    *  a specific service by ID.  Note that the last element in the
764    *  array must be { NULL, NULL }, and that the function should
765    *  return NULL if the service isn't available.
766    *
767    *  This function can be used by modules to implement their
768    *  `get_service' method.
769    */
770   FT_BASE( FT_Pointer )
771   ft_service_list_lookup( FT_ServiceDesc  service_descriptors,
772                           const char*     service_id );
773 
774 
775   /*************************************************************************/
776   /*************************************************************************/
777   /*****                                                               *****/
778   /*****             S E R V I C E S   C A C H E                       *****/
779   /*****                                                               *****/
780   /*************************************************************************/
781   /*************************************************************************/
782 
783   /*
784    *  This structure is used to store a cache for several frequently used
785    *  services.  It is the type of `face->internal->services'.  You
786    *  should only use FT_FACE_LOOKUP_SERVICE to access it.
787    *
788    *  All fields should have the type FT_Pointer to relax compilation
789    *  dependencies.  We assume the developer isn't completely stupid.
790    *
791    *  Each field must be named `service_XXXX' where `XXX' corresponds to
792    *  the correct FT_SERVICE_ID_XXXX macro.  See the definition of
793    *  FT_FACE_LOOKUP_SERVICE below how this is implemented.
794    *
795    */
796   typedef struct  FT_ServiceCacheRec_
797   {
798     FT_Pointer  service_POSTSCRIPT_FONT_NAME;
799     FT_Pointer  service_MULTI_MASTERS;
800     FT_Pointer  service_METRICS_VARIATIONS;
801     FT_Pointer  service_GLYPH_DICT;
802     FT_Pointer  service_PFR_METRICS;
803     FT_Pointer  service_WINFNT;
804 
805   } FT_ServiceCacheRec, *FT_ServiceCache;
806 
807 
808   /*
809    *  A magic number used within the services cache.
810    */
811 
812   /* ensure that value `1' has the same width as a pointer */
813 #define FT_SERVICE_UNAVAILABLE  ((FT_Pointer)~(FT_PtrDist)1)
814 
815 
816   /*
817    * @macro:
818    *   FT_FACE_LOOKUP_SERVICE
819    *
820    * @description:
821    *   This macro is used to look up a service from a face's driver module
822    *   using its cache.
823    *
824    * @input:
825    *   face::
826    *     The source face handle containing the cache.
827    *
828    *   field ::
829    *     The field name in the cache.
830    *
831    *   id ::
832    *     The service ID.
833    *
834    * @output:
835    *   ptr ::
836    *     A variable receiving the service data.  NULL if not available.
837    */
838 #ifdef __cplusplus
839 
840 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
841   FT_BEGIN_STMNT                                               \
842     FT_Pointer   svc;                                          \
843     FT_Pointer*  Pptr = (FT_Pointer*)&(ptr);                   \
844                                                                \
845                                                                \
846     svc = FT_FACE( face )->internal->services. service_ ## id; \
847     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
848       svc = NULL;                                              \
849     else if ( svc == NULL )                                    \
850     {                                                          \
851       FT_FACE_FIND_SERVICE( face, svc, id );                   \
852                                                                \
853       FT_FACE( face )->internal->services. service_ ## id =    \
854         (FT_Pointer)( svc != NULL ? svc                        \
855                                   : FT_SERVICE_UNAVAILABLE );  \
856     }                                                          \
857     *Pptr = svc;                                               \
858   FT_END_STMNT
859 
860 #else /* !C++ */
861 
862 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
863   FT_BEGIN_STMNT                                               \
864     FT_Pointer  svc;                                           \
865                                                                \
866                                                                \
867     svc = FT_FACE( face )->internal->services. service_ ## id; \
868     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
869       svc = NULL;                                              \
870     else if ( svc == NULL )                                    \
871     {                                                          \
872       FT_FACE_FIND_SERVICE( face, svc, id );                   \
873                                                                \
874       FT_FACE( face )->internal->services. service_ ## id =    \
875         (FT_Pointer)( svc != NULL ? svc                        \
876                                   : FT_SERVICE_UNAVAILABLE );  \
877     }                                                          \
878     ptr = svc;                                                 \
879   FT_END_STMNT
880 
881 #endif /* !C++ */
882 
883   /*
884    *  A macro used to define new service structure types.
885    */
886 
887 #define FT_DEFINE_SERVICE( name )            \
888   typedef struct FT_Service_ ## name ## Rec_ \
889     FT_Service_ ## name ## Rec ;             \
890   typedef struct FT_Service_ ## name ## Rec_ \
891     const * FT_Service_ ## name ;            \
892   struct FT_Service_ ## name ## Rec_
893 
894   /* */
895 
896   /*
897    *  The header files containing the services.
898    */
899 
900 #define FT_SERVICE_BDF_H                <freetype/internal/services/svbdf.h>
901 #define FT_SERVICE_CID_H                <freetype/internal/services/svcid.h>
902 #define FT_SERVICE_GLYPH_DICT_H         <freetype/internal/services/svgldict.h>
903 #define FT_SERVICE_GX_VALIDATE_H        <freetype/internal/services/svgxval.h>
904 #define FT_SERVICE_KERNING_H            <freetype/internal/services/svkern.h>
905 #define FT_SERVICE_METRICS_VARIATIONS_H <freetype/internal/services/svmetric.h>
906 #define FT_SERVICE_MULTIPLE_MASTERS_H   <freetype/internal/services/svmm.h>
907 #define FT_SERVICE_OPENTYPE_VALIDATE_H  <freetype/internal/services/svotval.h>
908 #define FT_SERVICE_PFR_H                <freetype/internal/services/svpfr.h>
909 #define FT_SERVICE_POSTSCRIPT_CMAPS_H   <freetype/internal/services/svpscmap.h>
910 #define FT_SERVICE_POSTSCRIPT_INFO_H    <freetype/internal/services/svpsinfo.h>
911 #define FT_SERVICE_POSTSCRIPT_NAME_H    <freetype/internal/services/svpostnm.h>
912 #define FT_SERVICE_PROPERTIES_H         <freetype/internal/services/svprop.h>
913 #define FT_SERVICE_SFNT_H               <freetype/internal/services/svsfnt.h>
914 #define FT_SERVICE_TRUETYPE_ENGINE_H    <freetype/internal/services/svtteng.h>
915 #define FT_SERVICE_TT_CMAP_H            <freetype/internal/services/svttcmap.h>
916 #define FT_SERVICE_WINFNT_H             <freetype/internal/services/svwinfnt.h>
917 #define FT_SERVICE_FONT_FORMAT_H        <freetype/internal/services/svfntfmt.h>
918 #define FT_SERVICE_TRUETYPE_GLYF_H      <freetype/internal/services/svttglyf.h>
919 
920  /* */
921 
922 FT_END_HEADER
923 
924 #endif /* FTSERV_H_ */
925 
926 
927 /* END */
928