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
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 ); \
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                <freetype/internal/services/svbdf.h>
738#define FT_SERVICE_CID_H                <freetype/internal/services/svcid.h>
739#define FT_SERVICE_GLYPH_DICT_H         <freetype/internal/services/svgldict.h>
740#define FT_SERVICE_GX_VALIDATE_H        <freetype/internal/services/svgxval.h>
741#define FT_SERVICE_KERNING_H            <freetype/internal/services/svkern.h>
742#define FT_SERVICE_MULTIPLE_MASTERS_H   <freetype/internal/services/svmm.h>
743#define FT_SERVICE_OPENTYPE_VALIDATE_H  <freetype/internal/services/svotval.h>
744#define FT_SERVICE_PFR_H                <freetype/internal/services/svpfr.h>
745#define FT_SERVICE_POSTSCRIPT_CMAPS_H   <freetype/internal/services/svpscmap.h>
746#define FT_SERVICE_POSTSCRIPT_INFO_H    <freetype/internal/services/svpsinfo.h>
747#define FT_SERVICE_POSTSCRIPT_NAME_H    <freetype/internal/services/svpostnm.h>
748#define FT_SERVICE_PROPERTIES_H         <freetype/internal/services/svprop.h>
749#define FT_SERVICE_SFNT_H               <freetype/internal/services/svsfnt.h>
750#define FT_SERVICE_TRUETYPE_ENGINE_H    <freetype/internal/services/svtteng.h>
751#define FT_SERVICE_TT_CMAP_H            <freetype/internal/services/svttcmap.h>
752#define FT_SERVICE_WINFNT_H             <freetype/internal/services/svwinfnt.h>
753#define FT_SERVICE_XFREE86_NAME_H       <freetype/internal/services/svxf86nm.h>
754#define FT_SERVICE_TRUETYPE_GLYF_H      <freetype/internal/services/svttglyf.h>
755
756 /* */
757
758FT_END_HEADER
759
760#endif /* __FTSERV_H__ */
761
762
763/* END */
764