1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftserv.h                                                               */
4 /*                                                                         */
5 /*    The FreeType services (specification only).                          */
6 /*                                                                         */
7 /*  Copyright 2003-2007, 2009, 2012, 2013 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 ); \
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 ); \
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   /*                                                                       */
171   /* <Description>                                                         */
172   /*    Used to initialize an array of FT_ServiceDescRec structures.       */
173   /*                                                                       */
174   /*    When FT_CONFIG_OPTION_PIC is defined a `create' function needs to  */
175   /*    be called with a pointer to return an allocated array.  As soon as */
176   /*    it is no longer needed, a `destroy' function needs to be called to */
177   /*    release that allocation.                                           */
178   /*                                                                       */
179   /*    These functions should be manually called from the `pic_init' and  */
180   /*    `pic_free' functions of your module (see FT_DEFINE_MODULE).        */
181   /*                                                                       */
182   /*    When FT_CONFIG_OPTION_PIC is not defined the array will be         */
183   /*    allocated in the global scope (or the scope where the macro is     */
184   /*    used).                                                             */
185   /*                                                                       */
186 #ifndef FT_CONFIG_OPTION_PIC
187 
188 #define FT_DEFINE_SERVICEDESCREC1( class_,                                  \
189                                    serv_id_1, serv_data_1 )                 \
190   static const FT_ServiceDescRec  class_[] =                                \
191   {                                                                         \
192     { serv_id_1, serv_data_1 },                                             \
193     { NULL, NULL }                                                          \
194   };
195 
196 #define FT_DEFINE_SERVICEDESCREC2( class_,                                  \
197                                    serv_id_1, serv_data_1,                  \
198                                    serv_id_2, serv_data_2 )                 \
199   static const FT_ServiceDescRec  class_[] =                                \
200   {                                                                         \
201     { serv_id_1, serv_data_1 },                                             \
202     { serv_id_2, serv_data_2 },                                             \
203     { NULL, NULL }                                                          \
204   };
205 
206 #define FT_DEFINE_SERVICEDESCREC3( class_,                                  \
207                                    serv_id_1, serv_data_1,                  \
208                                    serv_id_2, serv_data_2,                  \
209                                    serv_id_3, serv_data_3 )                 \
210   static const FT_ServiceDescRec  class_[] =                                \
211   {                                                                         \
212     { serv_id_1, serv_data_1 },                                             \
213     { serv_id_2, serv_data_2 },                                             \
214     { serv_id_3, serv_data_3 },                                             \
215     { NULL, NULL }                                                          \
216   };
217 
218 #define FT_DEFINE_SERVICEDESCREC4( class_,                                  \
219                                    serv_id_1, serv_data_1,                  \
220                                    serv_id_2, serv_data_2,                  \
221                                    serv_id_3, serv_data_3,                  \
222                                    serv_id_4, serv_data_4 )                 \
223   static const FT_ServiceDescRec  class_[] =                                \
224   {                                                                         \
225     { serv_id_1, serv_data_1 },                                             \
226     { serv_id_2, serv_data_2 },                                             \
227     { serv_id_3, serv_data_3 },                                             \
228     { serv_id_4, serv_data_4 },                                             \
229     { NULL, NULL }                                                          \
230   };
231 
232 #define FT_DEFINE_SERVICEDESCREC5( class_,                                  \
233                                    serv_id_1, serv_data_1,                  \
234                                    serv_id_2, serv_data_2,                  \
235                                    serv_id_3, serv_data_3,                  \
236                                    serv_id_4, serv_data_4,                  \
237                                    serv_id_5, serv_data_5 )                 \
238   static const FT_ServiceDescRec  class_[] =                                \
239   {                                                                         \
240     { serv_id_1, serv_data_1 },                                             \
241     { serv_id_2, serv_data_2 },                                             \
242     { serv_id_3, serv_data_3 },                                             \
243     { serv_id_4, serv_data_4 },                                             \
244     { serv_id_5, serv_data_5 },                                             \
245     { NULL, NULL }                                                          \
246   };
247 
248 #define FT_DEFINE_SERVICEDESCREC6( class_,                                  \
249                                    serv_id_1, serv_data_1,                  \
250                                    serv_id_2, serv_data_2,                  \
251                                    serv_id_3, serv_data_3,                  \
252                                    serv_id_4, serv_data_4,                  \
253                                    serv_id_5, serv_data_5,                  \
254                                    serv_id_6, serv_data_6 )                 \
255   static const FT_ServiceDescRec  class_[] =                                \
256   {                                                                         \
257     { serv_id_1, serv_data_1 },                                             \
258     { serv_id_2, serv_data_2 },                                             \
259     { serv_id_3, serv_data_3 },                                             \
260     { serv_id_4, serv_data_4 },                                             \
261     { serv_id_5, serv_data_5 },                                             \
262     { serv_id_6, serv_data_6 },                                             \
263     { NULL, NULL }                                                          \
264   };
265 
266 #define FT_DEFINE_SERVICEDESCREC7( class_,                                  \
267                                    serv_id_1, serv_data_1,                  \
268                                    serv_id_2, serv_data_2,                  \
269                                    serv_id_3, serv_data_3,                  \
270                                    serv_id_4, serv_data_4,                  \
271                                    serv_id_5, serv_data_5,                  \
272                                    serv_id_6, serv_data_6,                  \
273                                    serv_id_7, serv_data_7 )                 \
274   static const FT_ServiceDescRec  class_[] =                                \
275   {                                                                         \
276     { serv_id_1, serv_data_1 },                                             \
277     { serv_id_2, serv_data_2 },                                             \
278     { serv_id_3, serv_data_3 },                                             \
279     { serv_id_4, serv_data_4 },                                             \
280     { serv_id_5, serv_data_5 },                                             \
281     { serv_id_6, serv_data_6 },                                             \
282     { serv_id_7, serv_data_7 },                                             \
283     { NULL, NULL }                                                          \
284   };
285 
286 #else /* FT_CONFIG_OPTION_PIC */
287 
288 #define FT_DEFINE_SERVICEDESCREC1( class_,                                  \
289                                    serv_id_1, serv_data_1 )                 \
290   void                                                                      \
291   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
292                                FT_ServiceDescRec*  clazz )                  \
293   {                                                                         \
294     FT_Memory  memory = library->memory;                                    \
295                                                                             \
296                                                                             \
297     if ( clazz )                                                            \
298       FT_FREE( clazz );                                                     \
299   }                                                                         \
300                                                                             \
301   FT_Error                                                                  \
302   FT_Create_Class_ ## class_( FT_Library           library,                 \
303                               FT_ServiceDescRec**  output_class )           \
304   {                                                                         \
305     FT_ServiceDescRec*  clazz  = NULL;                                      \
306     FT_Error            error;                                              \
307     FT_Memory           memory = library->memory;                           \
308                                                                             \
309                                                                             \
310     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 2 ) )                         \
311       return error;                                                         \
312                                                                             \
313     clazz[0].serv_id   = serv_id_1;                                         \
314     clazz[0].serv_data = serv_data_1;                                       \
315     clazz[1].serv_id   = NULL;                                              \
316     clazz[1].serv_data = NULL;                                              \
317                                                                             \
318     *output_class = clazz;                                                  \
319                                                                             \
320     return FT_Err_Ok;                                                       \
321   }
322 
323 #define FT_DEFINE_SERVICEDESCREC2( class_,                                  \
324                                    serv_id_1, serv_data_1,                  \
325                                    serv_id_2, serv_data_2 )                 \
326   void                                                                      \
327   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
328                                FT_ServiceDescRec*  clazz )                  \
329   {                                                                         \
330     FT_Memory  memory = library->memory;                                    \
331                                                                             \
332                                                                             \
333     if ( clazz )                                                            \
334       FT_FREE( clazz );                                                     \
335   }                                                                         \
336                                                                             \
337   FT_Error                                                                  \
338   FT_Create_Class_ ## class_( FT_Library           library,                 \
339                               FT_ServiceDescRec**  output_class )           \
340   {                                                                         \
341     FT_ServiceDescRec*  clazz  = NULL;                                      \
342     FT_Error            error;                                              \
343     FT_Memory           memory = library->memory;                           \
344                                                                             \
345                                                                             \
346     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 3 ) )                         \
347       return error;                                                         \
348                                                                             \
349     clazz[0].serv_id   = serv_id_1;                                         \
350     clazz[0].serv_data = serv_data_1;                                       \
351     clazz[1].serv_id   = serv_id_2;                                         \
352     clazz[1].serv_data = serv_data_2;                                       \
353     clazz[2].serv_id   = NULL;                                              \
354     clazz[2].serv_data = NULL;                                              \
355                                                                             \
356     *output_class = clazz;                                                  \
357                                                                             \
358     return FT_Err_Ok;                                                       \
359   }
360 
361 #define FT_DEFINE_SERVICEDESCREC3( class_,                                  \
362                                    serv_id_1, serv_data_1,                  \
363                                    serv_id_2, serv_data_2,                  \
364                                    serv_id_3, serv_data_3 )                 \
365   void                                                                      \
366   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
367                                FT_ServiceDescRec*  clazz )                  \
368   {                                                                         \
369     FT_Memory  memory = library->memory;                                    \
370                                                                             \
371                                                                             \
372     if ( clazz )                                                            \
373       FT_FREE( clazz );                                                     \
374   }                                                                         \
375                                                                             \
376   FT_Error                                                                  \
377   FT_Create_Class_ ## class_( FT_Library           library,                 \
378                               FT_ServiceDescRec**  output_class )           \
379   {                                                                         \
380     FT_ServiceDescRec*  clazz  = NULL;                                      \
381     FT_Error            error;                                              \
382     FT_Memory           memory = library->memory;                           \
383                                                                             \
384                                                                             \
385     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 4 ) )                         \
386       return error;                                                         \
387                                                                             \
388     clazz[0].serv_id   = serv_id_1;                                         \
389     clazz[0].serv_data = serv_data_1;                                       \
390     clazz[1].serv_id   = serv_id_2;                                         \
391     clazz[1].serv_data = serv_data_2;                                       \
392     clazz[2].serv_id   = serv_id_3;                                         \
393     clazz[2].serv_data = serv_data_3;                                       \
394     clazz[3].serv_id   = NULL;                                              \
395     clazz[3].serv_data = NULL;                                              \
396                                                                             \
397     *output_class = clazz;                                                  \
398                                                                             \
399     return FT_Err_Ok;                                                       \
400   }
401 
402 #define FT_DEFINE_SERVICEDESCREC4( class_,                                  \
403                                    serv_id_1, serv_data_1,                  \
404                                    serv_id_2, serv_data_2,                  \
405                                    serv_id_3, serv_data_3,                  \
406                                    serv_id_4, serv_data_4 )                 \
407   void                                                                      \
408   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
409                                FT_ServiceDescRec*  clazz )                  \
410   {                                                                         \
411     FT_Memory  memory = library->memory;                                    \
412                                                                             \
413                                                                             \
414     if ( clazz )                                                            \
415       FT_FREE( clazz );                                                     \
416   }                                                                         \
417                                                                             \
418   FT_Error                                                                  \
419   FT_Create_Class_ ## class_( FT_Library           library,                 \
420                               FT_ServiceDescRec**  output_class )           \
421   {                                                                         \
422     FT_ServiceDescRec*  clazz  = NULL;                                      \
423     FT_Error            error;                                              \
424     FT_Memory           memory = library->memory;                           \
425                                                                             \
426                                                                             \
427     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 5 ) )                         \
428       return error;                                                         \
429                                                                             \
430     clazz[0].serv_id   = serv_id_1;                                         \
431     clazz[0].serv_data = serv_data_1;                                       \
432     clazz[1].serv_id   = serv_id_2;                                         \
433     clazz[1].serv_data = serv_data_2;                                       \
434     clazz[2].serv_id   = serv_id_3;                                         \
435     clazz[2].serv_data = serv_data_3;                                       \
436     clazz[3].serv_id   = serv_id_4;                                         \
437     clazz[3].serv_data = serv_data_4;                                       \
438     clazz[4].serv_id   = NULL;                                              \
439     clazz[4].serv_data = NULL;                                              \
440                                                                             \
441     *output_class = clazz;                                                  \
442                                                                             \
443     return FT_Err_Ok;                                                       \
444   }
445 
446 #define FT_DEFINE_SERVICEDESCREC5( class_,                                  \
447                                    serv_id_1, serv_data_1,                  \
448                                    serv_id_2, serv_data_2,                  \
449                                    serv_id_3, serv_data_3,                  \
450                                    serv_id_4, serv_data_4,                  \
451                                    serv_id_5, serv_data_5 )                 \
452   void                                                                      \
453   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
454                                FT_ServiceDescRec*  clazz )                  \
455   {                                                                         \
456     FT_Memory  memory = library->memory;                                    \
457                                                                             \
458                                                                             \
459     if ( clazz )                                                            \
460       FT_FREE( clazz );                                                     \
461   }                                                                         \
462                                                                             \
463   FT_Error                                                                  \
464   FT_Create_Class_ ## class_( FT_Library           library,                 \
465                               FT_ServiceDescRec**  output_class )           \
466   {                                                                         \
467     FT_ServiceDescRec*  clazz  = NULL;                                      \
468     FT_Error            error;                                              \
469     FT_Memory           memory = library->memory;                           \
470                                                                             \
471                                                                             \
472     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 6 ) )                         \
473       return error;                                                         \
474                                                                             \
475     clazz[0].serv_id   = serv_id_1;                                         \
476     clazz[0].serv_data = serv_data_1;                                       \
477     clazz[1].serv_id   = serv_id_2;                                         \
478     clazz[1].serv_data = serv_data_2;                                       \
479     clazz[2].serv_id   = serv_id_3;                                         \
480     clazz[2].serv_data = serv_data_3;                                       \
481     clazz[3].serv_id   = serv_id_4;                                         \
482     clazz[3].serv_data = serv_data_4;                                       \
483     clazz[4].serv_id   = serv_id_5;                                         \
484     clazz[4].serv_data = serv_data_5;                                       \
485     clazz[5].serv_id   = NULL;                                              \
486     clazz[5].serv_data = NULL;                                              \
487                                                                             \
488     *output_class = clazz;                                                  \
489                                                                             \
490     return FT_Err_Ok;                                                       \
491   }
492 
493 #define FT_DEFINE_SERVICEDESCREC6( 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                                    serv_id_6, serv_data_6 )                 \
500   void                                                                      \
501   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
502                                FT_ServiceDescRec*  clazz )                  \
503   {                                                                         \
504     FT_Memory  memory = library->memory;                                    \
505                                                                             \
506                                                                             \
507     if ( clazz )                                                            \
508       FT_FREE( clazz );                                                     \
509   }                                                                         \
510                                                                             \
511   FT_Error                                                                  \
512   FT_Create_Class_ ## class_( FT_Library           library,                 \
513                               FT_ServiceDescRec**  output_class)            \
514   {                                                                         \
515     FT_ServiceDescRec*  clazz  = NULL;                                      \
516     FT_Error            error;                                              \
517     FT_Memory           memory = library->memory;                           \
518                                                                             \
519                                                                             \
520     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 7 ) )                         \
521       return error;                                                         \
522                                                                             \
523     clazz[0].serv_id   = serv_id_1;                                         \
524     clazz[0].serv_data = serv_data_1;                                       \
525     clazz[1].serv_id   = serv_id_2;                                         \
526     clazz[1].serv_data = serv_data_2;                                       \
527     clazz[2].serv_id   = serv_id_3;                                         \
528     clazz[2].serv_data = serv_data_3;                                       \
529     clazz[3].serv_id   = serv_id_4;                                         \
530     clazz[3].serv_data = serv_data_4;                                       \
531     clazz[4].serv_id   = serv_id_5;                                         \
532     clazz[4].serv_data = serv_data_5;                                       \
533     clazz[5].serv_id   = serv_id_6;                                         \
534     clazz[5].serv_data = serv_data_6;                                       \
535     clazz[6].serv_id   = NULL;                                              \
536     clazz[6].serv_data = NULL;                                              \
537                                                                             \
538     *output_class = clazz;                                                  \
539                                                                             \
540     return FT_Err_Ok;                                                       \
541   }
542 
543 #define FT_DEFINE_SERVICEDESCREC7( class_,                                  \
544                                    serv_id_1, serv_data_1,                  \
545                                    serv_id_2, serv_data_2,                  \
546                                    serv_id_3, serv_data_3,                  \
547                                    serv_id_4, serv_data_4,                  \
548                                    serv_id_5, serv_data_5,                  \
549                                    serv_id_6, serv_data_6,                  \
550                                    serv_id_7, serv_data_7 )                 \
551   void                                                                      \
552   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
553                                FT_ServiceDescRec*  clazz )                  \
554   {                                                                         \
555     FT_Memory  memory = library->memory;                                    \
556                                                                             \
557                                                                             \
558     if ( clazz )                                                            \
559       FT_FREE( clazz );                                                     \
560   }                                                                         \
561                                                                             \
562   FT_Error                                                                  \
563   FT_Create_Class_ ## class_( FT_Library           library,                 \
564                               FT_ServiceDescRec**  output_class)            \
565   {                                                                         \
566     FT_ServiceDescRec*  clazz  = NULL;                                      \
567     FT_Error            error;                                              \
568     FT_Memory           memory = library->memory;                           \
569                                                                             \
570                                                                             \
571     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 8 ) )                         \
572       return error;                                                         \
573                                                                             \
574     clazz[0].serv_id   = serv_id_1;                                         \
575     clazz[0].serv_data = serv_data_1;                                       \
576     clazz[1].serv_id   = serv_id_2;                                         \
577     clazz[1].serv_data = serv_data_2;                                       \
578     clazz[2].serv_id   = serv_id_3;                                         \
579     clazz[2].serv_data = serv_data_3;                                       \
580     clazz[3].serv_id   = serv_id_4;                                         \
581     clazz[3].serv_data = serv_data_4;                                       \
582     clazz[4].serv_id   = serv_id_5;                                         \
583     clazz[4].serv_data = serv_data_5;                                       \
584     clazz[5].serv_id   = serv_id_6;                                         \
585     clazz[5].serv_data = serv_data_6;                                       \
586     clazz[6].serv_id   = serv_id_7;                                         \
587     clazz[6].serv_data = serv_data_7;                                       \
588     clazz[7].serv_id   = NULL;                                              \
589     clazz[7].serv_data = NULL;                                              \
590                                                                             \
591     *output_class = clazz;                                                  \
592                                                                             \
593     return FT_Err_Ok;                                                       \
594   }
595 
596 #endif /* FT_CONFIG_OPTION_PIC */
597 
598 
599   /*
600    *  Parse a list of FT_ServiceDescRec descriptors and look for
601    *  a specific service by ID.  Note that the last element in the
602    *  array must be { NULL, NULL }, and that the function should
603    *  return NULL if the service isn't available.
604    *
605    *  This function can be used by modules to implement their
606    *  `get_service' method.
607    */
608   FT_BASE( FT_Pointer )
609   ft_service_list_lookup( FT_ServiceDesc  service_descriptors,
610                           const char*     service_id );
611 
612 
613   /*************************************************************************/
614   /*************************************************************************/
615   /*****                                                               *****/
616   /*****             S E R V I C E S   C A C H E                       *****/
617   /*****                                                               *****/
618   /*************************************************************************/
619   /*************************************************************************/
620 
621   /*
622    *  This structure is used to store a cache for several frequently used
623    *  services.  It is the type of `face->internal->services'.  You
624    *  should only use FT_FACE_LOOKUP_SERVICE to access it.
625    *
626    *  All fields should have the type FT_Pointer to relax compilation
627    *  dependencies.  We assume the developer isn't completely stupid.
628    *
629    *  Each field must be named `service_XXXX' where `XXX' corresponds to
630    *  the correct FT_SERVICE_ID_XXXX macro.  See the definition of
631    *  FT_FACE_LOOKUP_SERVICE below how this is implemented.
632    *
633    */
634   typedef struct  FT_ServiceCacheRec_
635   {
636     FT_Pointer  service_POSTSCRIPT_FONT_NAME;
637     FT_Pointer  service_MULTI_MASTERS;
638     FT_Pointer  service_GLYPH_DICT;
639     FT_Pointer  service_PFR_METRICS;
640     FT_Pointer  service_WINFNT;
641 
642   } FT_ServiceCacheRec, *FT_ServiceCache;
643 
644 
645   /*
646    *  A magic number used within the services cache.
647    */
648 
649   /* ensure that value `1' has the same width as a pointer */
650 #define FT_SERVICE_UNAVAILABLE  ((FT_Pointer)~(FT_PtrDist)1)
651 
652 
653   /*
654    * @macro:
655    *   FT_FACE_LOOKUP_SERVICE
656    *
657    * @description:
658    *   This macro is used to lookup a service from a face's driver module
659    *   using its cache.
660    *
661    * @input:
662    *   face::
663    *     The source face handle containing the cache.
664    *
665    *   field ::
666    *     The field name in the cache.
667    *
668    *   id ::
669    *     The service ID.
670    *
671    * @output:
672    *   ptr ::
673    *     A variable receiving the service data.  NULL if not available.
674    */
675 #ifdef __cplusplus
676 
677 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
678   FT_BEGIN_STMNT                                               \
679     FT_Pointer   svc;                                          \
680     FT_Pointer*  Pptr = (FT_Pointer*)&(ptr);                   \
681                                                                \
682                                                                \
683     svc = FT_FACE( face )->internal->services. service_ ## id; \
684     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
685       svc = NULL;                                              \
686     else if ( svc == NULL )                                    \
687     {                                                          \
688       FT_FACE_FIND_SERVICE( face, svc, id );                   \
689                                                                \
690       FT_FACE( face )->internal->services. service_ ## id =    \
691         (FT_Pointer)( svc != NULL ? svc                        \
692                                   : FT_SERVICE_UNAVAILABLE );  \
693     }                                                          \
694     *Pptr = svc;                                               \
695   FT_END_STMNT
696 
697 #else /* !C++ */
698 
699 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
700   FT_BEGIN_STMNT                                               \
701     FT_Pointer  svc;                                           \
702                                                                \
703                                                                \
704     svc = FT_FACE( face )->internal->services. service_ ## id; \
705     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
706       svc = NULL;                                              \
707     else if ( svc == NULL )                                    \
708     {                                                          \
709       FT_FACE_FIND_SERVICE( face, svc, id );                   \
710                                                                \
711       FT_FACE( face )->internal->services. service_ ## id =    \
712         (FT_Pointer)( svc != NULL ? svc                        \
713                                   : FT_SERVICE_UNAVAILABLE );  \
714     }                                                          \
715     ptr = svc;                                                 \
716   FT_END_STMNT
717 
718 #endif /* !C++ */
719 
720   /*
721    *  A macro used to define new service structure types.
722    */
723 
724 #define FT_DEFINE_SERVICE( name )            \
725   typedef struct FT_Service_ ## name ## Rec_ \
726     FT_Service_ ## name ## Rec ;             \
727   typedef struct FT_Service_ ## name ## Rec_ \
728     const * FT_Service_ ## name ;            \
729   struct FT_Service_ ## name ## Rec_
730 
731   /* */
732 
733   /*
734    *  The header files containing the services.
735    */
736 
737 #define FT_SERVICE_BDF_H                <internal/services/svbdf.h>
738 #define FT_SERVICE_CID_H                <internal/services/svcid.h>
739 #define FT_SERVICE_GLYPH_DICT_H         <internal/services/svgldict.h>
740 #define FT_SERVICE_GX_VALIDATE_H        <internal/services/svgxval.h>
741 #define FT_SERVICE_KERNING_H            <internal/services/svkern.h>
742 #define FT_SERVICE_MULTIPLE_MASTERS_H   <internal/services/svmm.h>
743 #define FT_SERVICE_OPENTYPE_VALIDATE_H  <internal/services/svotval.h>
744 #define FT_SERVICE_PFR_H                <internal/services/svpfr.h>
745 #define FT_SERVICE_POSTSCRIPT_CMAPS_H   <internal/services/svpscmap.h>
746 #define FT_SERVICE_POSTSCRIPT_INFO_H    <internal/services/svpsinfo.h>
747 #define FT_SERVICE_POSTSCRIPT_NAME_H    <internal/services/svpostnm.h>
748 #define FT_SERVICE_PROPERTIES_H         <internal/services/svprop.h>
749 #define FT_SERVICE_SFNT_H               <internal/services/svsfnt.h>
750 #define FT_SERVICE_TRUETYPE_ENGINE_H    <internal/services/svtteng.h>
751 #define FT_SERVICE_TT_CMAP_H            <internal/services/svttcmap.h>
752 #define FT_SERVICE_WINFNT_H             <internal/services/svwinfnt.h>
753 #define FT_SERVICE_XFREE86_NAME_H       <internal/services/svxf86nm.h>
754 #define FT_SERVICE_TRUETYPE_GLYF_H      <internal/services/svttglyf.h>
755 
756  /* */
757 
758 FT_END_HEADER
759 
760 #endif /* __FTSERV_H__ */
761 
762 
763 /* END */
764