1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftserv.h                                                               */
4 /*                                                                         */
5 /*    The FreeType services (specification only).                          */
6 /*                                                                         */
7 /*  Copyright 2003-2018 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 #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_[] =                                \
345   {                                                                         \
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 },                                           \
356     { NULL, NULL }                                                          \
357   };
358 
359 #else /* FT_CONFIG_OPTION_PIC */
360 
361 #define FT_DEFINE_SERVICEDESCREC1( class_,                                  \
362                                    serv_id_1, serv_data_1 )                 \
363   void                                                                      \
364   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
365                                FT_ServiceDescRec*  clazz )                  \
366   {                                                                         \
367     FT_Memory  memory = library->memory;                                    \
368                                                                             \
369                                                                             \
370     if ( clazz )                                                            \
371       FT_FREE( clazz );                                                     \
372   }                                                                         \
373                                                                             \
374   FT_Error                                                                  \
375   FT_Create_Class_ ## class_( FT_Library           library,                 \
376                               FT_ServiceDescRec**  output_class )           \
377   {                                                                         \
378     FT_ServiceDescRec*  clazz  = NULL;                                      \
379     FT_Error            error;                                              \
380     FT_Memory           memory = library->memory;                           \
381                                                                             \
382                                                                             \
383     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 2 ) )                         \
384       return error;                                                         \
385                                                                             \
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;                                              \
390                                                                             \
391     *output_class = clazz;                                                  \
392                                                                             \
393     return FT_Err_Ok;                                                       \
394   }
395 
396 #define FT_DEFINE_SERVICEDESCREC2( class_,                                  \
397                                    serv_id_1, serv_data_1,                  \
398                                    serv_id_2, serv_data_2 )                 \
399   void                                                                      \
400   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
401                                FT_ServiceDescRec*  clazz )                  \
402   {                                                                         \
403     FT_Memory  memory = library->memory;                                    \
404                                                                             \
405                                                                             \
406     if ( clazz )                                                            \
407       FT_FREE( clazz );                                                     \
408   }                                                                         \
409                                                                             \
410   FT_Error                                                                  \
411   FT_Create_Class_ ## class_( FT_Library           library,                 \
412                               FT_ServiceDescRec**  output_class )           \
413   {                                                                         \
414     FT_ServiceDescRec*  clazz  = NULL;                                      \
415     FT_Error            error;                                              \
416     FT_Memory           memory = library->memory;                           \
417                                                                             \
418                                                                             \
419     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 3 ) )                         \
420       return error;                                                         \
421                                                                             \
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;                                              \
428                                                                             \
429     *output_class = clazz;                                                  \
430                                                                             \
431     return FT_Err_Ok;                                                       \
432   }
433 
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 )                 \
438   void                                                                      \
439   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
440                                FT_ServiceDescRec*  clazz )                  \
441   {                                                                         \
442     FT_Memory  memory = library->memory;                                    \
443                                                                             \
444                                                                             \
445     if ( clazz )                                                            \
446       FT_FREE( clazz );                                                     \
447   }                                                                         \
448                                                                             \
449   FT_Error                                                                  \
450   FT_Create_Class_ ## class_( FT_Library           library,                 \
451                               FT_ServiceDescRec**  output_class )           \
452   {                                                                         \
453     FT_ServiceDescRec*  clazz  = NULL;                                      \
454     FT_Error            error;                                              \
455     FT_Memory           memory = library->memory;                           \
456                                                                             \
457                                                                             \
458     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 4 ) )                         \
459       return error;                                                         \
460                                                                             \
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;                                              \
469                                                                             \
470     *output_class = clazz;                                                  \
471                                                                             \
472     return FT_Err_Ok;                                                       \
473   }
474 
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 )                 \
480   void                                                                      \
481   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
482                                FT_ServiceDescRec*  clazz )                  \
483   {                                                                         \
484     FT_Memory  memory = library->memory;                                    \
485                                                                             \
486                                                                             \
487     if ( clazz )                                                            \
488       FT_FREE( clazz );                                                     \
489   }                                                                         \
490                                                                             \
491   FT_Error                                                                  \
492   FT_Create_Class_ ## class_( FT_Library           library,                 \
493                               FT_ServiceDescRec**  output_class )           \
494   {                                                                         \
495     FT_ServiceDescRec*  clazz  = NULL;                                      \
496     FT_Error            error;                                              \
497     FT_Memory           memory = library->memory;                           \
498                                                                             \
499                                                                             \
500     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 5 ) )                         \
501       return error;                                                         \
502                                                                             \
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;                                              \
513                                                                             \
514     *output_class = clazz;                                                  \
515                                                                             \
516     return FT_Err_Ok;                                                       \
517   }
518 
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 )                 \
525   void                                                                      \
526   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
527                                FT_ServiceDescRec*  clazz )                  \
528   {                                                                         \
529     FT_Memory  memory = library->memory;                                    \
530                                                                             \
531                                                                             \
532     if ( clazz )                                                            \
533       FT_FREE( clazz );                                                     \
534   }                                                                         \
535                                                                             \
536   FT_Error                                                                  \
537   FT_Create_Class_ ## class_( FT_Library           library,                 \
538                               FT_ServiceDescRec**  output_class )           \
539   {                                                                         \
540     FT_ServiceDescRec*  clazz  = NULL;                                      \
541     FT_Error            error;                                              \
542     FT_Memory           memory = library->memory;                           \
543                                                                             \
544                                                                             \
545     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 6 ) )                         \
546       return error;                                                         \
547                                                                             \
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;                                              \
560                                                                             \
561     *output_class = clazz;                                                  \
562                                                                             \
563     return FT_Err_Ok;                                                       \
564   }
565 
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 )                 \
573   void                                                                      \
574   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
575                                FT_ServiceDescRec*  clazz )                  \
576   {                                                                         \
577     FT_Memory  memory = library->memory;                                    \
578                                                                             \
579                                                                             \
580     if ( clazz )                                                            \
581       FT_FREE( clazz );                                                     \
582   }                                                                         \
583                                                                             \
584   FT_Error                                                                  \
585   FT_Create_Class_ ## class_( FT_Library           library,                 \
586                               FT_ServiceDescRec**  output_class )           \
587   {                                                                         \
588     FT_ServiceDescRec*  clazz  = NULL;                                      \
589     FT_Error            error;                                              \
590     FT_Memory           memory = library->memory;                           \
591                                                                             \
592                                                                             \
593     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 7 ) )                         \
594       return error;                                                         \
595                                                                             \
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;                                              \
610                                                                             \
611     *output_class = clazz;                                                  \
612                                                                             \
613     return FT_Err_Ok;                                                       \
614   }
615 
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 )                 \
624   void                                                                      \
625   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
626                                FT_ServiceDescRec*  clazz )                  \
627   {                                                                         \
628     FT_Memory  memory = library->memory;                                    \
629                                                                             \
630                                                                             \
631     if ( clazz )                                                            \
632       FT_FREE( clazz );                                                     \
633   }                                                                         \
634                                                                             \
635   FT_Error                                                                  \
636   FT_Create_Class_ ## class_( FT_Library           library,                 \
637                               FT_ServiceDescRec**  output_class )           \
638   {                                                                         \
639     FT_ServiceDescRec*  clazz  = NULL;                                      \
640     FT_Error            error;                                              \
641     FT_Memory           memory = library->memory;                           \
642                                                                             \
643                                                                             \
644     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 8 ) )                         \
645       return error;                                                         \
646                                                                             \
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;                                              \
663                                                                             \
664     *output_class = clazz;                                                  \
665                                                                             \
666     return FT_Err_Ok;                                                       \
667   }
668 
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 )                 \
678   void                                                                      \
679   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
680                                FT_ServiceDescRec*  clazz )                  \
681   {                                                                         \
682     FT_Memory  memory = library->memory;                                    \
683                                                                             \
684                                                                             \
685     if ( clazz )                                                            \
686       FT_FREE( clazz );                                                     \
687   }                                                                         \
688                                                                             \
689   FT_Error                                                                  \
690   FT_Create_Class_ ## class_( FT_Library           library,                 \
691                               FT_ServiceDescRec**  output_class )           \
692   {                                                                         \
693     FT_ServiceDescRec*  clazz  = NULL;                                      \
694     FT_Error            error;                                              \
695     FT_Memory           memory = library->memory;                           \
696                                                                             \
697                                                                             \
698     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 9 ) )                         \
699       return error;                                                         \
700                                                                             \
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;                                              \
719                                                                             \
720     *output_class = clazz;                                                  \
721                                                                             \
722     return FT_Err_Ok;                                                       \
723   }
724 
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 )                 \
735   void                                                                      \
736   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
737                                FT_ServiceDescRec*  clazz )                  \
738   {                                                                         \
739     FT_Memory  memory = library->memory;                                    \
740                                                                             \
741                                                                             \
742     if ( clazz )                                                            \
743       FT_FREE( clazz );                                                     \
744   }                                                                         \
745                                                                             \
746   FT_Error                                                                  \
747   FT_Create_Class_ ## class_( FT_Library           library,                 \
748                               FT_ServiceDescRec**  output_class )           \
749   {                                                                         \
750     FT_ServiceDescRec*  clazz  = NULL;                                      \
751     FT_Error            error;                                              \
752     FT_Memory           memory = library->memory;                           \
753                                                                             \
754                                                                             \
755     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 10 ) )                        \
756       return error;                                                         \
757                                                                             \
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;                                              \
778                                                                             \
779     *output_class = clazz;                                                  \
780                                                                             \
781     return FT_Err_Ok;                                                       \
782   }
783 
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 )              \
795   void                                                                      \
796   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
797                                FT_ServiceDescRec*  clazz )                  \
798   {                                                                         \
799     FT_Memory  memory = library->memory;                                    \
800                                                                             \
801                                                                             \
802     if ( clazz )                                                            \
803       FT_FREE( clazz );                                                     \
804   }                                                                         \
805                                                                             \
806   FT_Error                                                                  \
807   FT_Create_Class_ ## class_( FT_Library           library,                 \
808                               FT_ServiceDescRec**  output_class )           \
809   {                                                                         \
810     FT_ServiceDescRec*  clazz  = NULL;                                      \
811     FT_Error            error;                                              \
812     FT_Memory           memory = library->memory;                           \
813                                                                             \
814                                                                             \
815     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 11 ) )                        \
816       return error;                                                         \
817                                                                             \
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;                                             \
840                                                                             \
841     *output_class = clazz;                                                  \
842                                                                             \
843     return FT_Err_Ok;                                                       \
844   }
845 
846 #endif /* FT_CONFIG_OPTION_PIC */
847 
848 
849   /*
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.
854    *
855    *  This function can be used by modules to implement their
856    *  `get_service' method.
857    */
858   FT_BASE( FT_Pointer )
859   ft_service_list_lookup( FT_ServiceDesc  service_descriptors,
860                           const char*     service_id );
861 
862 
863   /*************************************************************************/
864   /*************************************************************************/
865   /*****                                                               *****/
866   /*****             S E R V I C E S   C A C H E                       *****/
867   /*****                                                               *****/
868   /*************************************************************************/
869   /*************************************************************************/
870 
871   /*
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.
875    *
876    *  All fields should have the type FT_Pointer to relax compilation
877    *  dependencies.  We assume the developer isn't completely stupid.
878    *
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.
882    *
883    */
884   typedef struct  FT_ServiceCacheRec_
885   {
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;
892 
893   } FT_ServiceCacheRec, *FT_ServiceCache;
894 
895 
896   /*
897    *  A magic number used within the services cache.
898    */
899 
900   /* ensure that value `1' has the same width as a pointer */
901 #define FT_SERVICE_UNAVAILABLE  ((FT_Pointer)~(FT_PtrDist)1)
902 
903 
904   /*
905    * @macro:
906    *   FT_FACE_LOOKUP_SERVICE
907    *
908    * @description:
909    *   This macro is used to look up a service from a face's driver module
910    *   using its cache.
911    *
912    * @input:
913    *   face::
914    *     The source face handle containing the cache.
915    *
916    *   field ::
917    *     The field name in the cache.
918    *
919    *   id ::
920    *     The service ID.
921    *
922    * @output:
923    *   ptr ::
924    *     A variable receiving the service data.  NULL if not available.
925    */
926 #ifdef __cplusplus
927 
928 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
929   FT_BEGIN_STMNT                                               \
930     FT_Pointer   svc;                                          \
931     FT_Pointer*  Pptr = (FT_Pointer*)&(ptr);                   \
932                                                                \
933                                                                \
934     svc = FT_FACE( face )->internal->services. service_ ## id; \
935     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
936       svc = NULL;                                              \
937     else if ( svc == NULL )                                    \
938     {                                                          \
939       FT_FACE_FIND_SERVICE( face, svc, id );                   \
940                                                                \
941       FT_FACE( face )->internal->services. service_ ## id =    \
942         (FT_Pointer)( svc != NULL ? svc                        \
943                                   : FT_SERVICE_UNAVAILABLE );  \
944     }                                                          \
945     *Pptr = svc;                                               \
946   FT_END_STMNT
947 
948 #else /* !C++ */
949 
950 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
951   FT_BEGIN_STMNT                                               \
952     FT_Pointer  svc;                                           \
953                                                                \
954                                                                \
955     svc = FT_FACE( face )->internal->services. service_ ## id; \
956     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
957       svc = NULL;                                              \
958     else if ( svc == NULL )                                    \
959     {                                                          \
960       FT_FACE_FIND_SERVICE( face, svc, id );                   \
961                                                                \
962       FT_FACE( face )->internal->services. service_ ## id =    \
963         (FT_Pointer)( svc != NULL ? svc                        \
964                                   : FT_SERVICE_UNAVAILABLE );  \
965     }                                                          \
966     ptr = svc;                                                 \
967   FT_END_STMNT
968 
969 #endif /* !C++ */
970 
971   /*
972    *  A macro used to define new service structure types.
973    */
974 
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_
981 
982   /* */
983 
984   /*
985    *  The header files containing the services.
986    */
987 
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>
1008 
1009  /* */
1010 
1011 FT_END_HEADER
1012 
1013 #endif /* FTSERV_H_ */
1014 
1015 
1016 /* END */
1017