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