Home | History | Annotate | Download | only in internal
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftserv.h                                                               */
      4 /*                                                                         */
      5 /*    The FreeType services (specification only).                          */
      6 /*                                                                         */
      7 /*  Copyright 2003-2007, 2009, 2012 by                                     */
      8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
      9 /*                                                                         */
     10 /*  This file is part of the FreeType project, and may only be used,       */
     11 /*  modified, and distributed under the terms of the FreeType project      */
     12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
     13 /*  this file you indicate that you have read the license and              */
     14 /*  understand and accept it fully.                                        */
     15 /*                                                                         */
     16 /***************************************************************************/
     17 
     18   /*************************************************************************/
     19   /*                                                                       */
     20   /*  Each module can export one or more `services'.  Each service is      */
     21   /*  identified by a constant string and modeled by a pointer; the latter */
     22   /*  generally corresponds to a structure containing function pointers.   */
     23   /*                                                                       */
     24   /*  Note that a service's data cannot be a mere function pointer because */
     25   /*  in C it is possible that function pointers might be implemented      */
     26   /*  differently than data pointers (e.g. 48 bits instead of 32).         */
     27   /*                                                                       */
     28   /*************************************************************************/
     29 
     30 
     31 #ifndef __FTSERV_H__
     32 #define __FTSERV_H__
     33 
     34 
     35 FT_BEGIN_HEADER
     36 
     37 #if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
     38 
     39   /* we disable the warning `conditional expression is constant' here */
     40   /* in order to compile cleanly with the maximum level of warnings   */
     41 #pragma warning( disable : 4127 )
     42 
     43 #endif /* _MSC_VER */
     44 
     45   /*
     46    * @macro:
     47    *   FT_FACE_FIND_SERVICE
     48    *
     49    * @description:
     50    *   This macro is used to look up a service from a face's driver module.
     51    *
     52    * @input:
     53    *   face ::
     54    *     The source face handle.
     55    *
     56    *   id ::
     57    *     A string describing the service as defined in the service's
     58    *     header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
     59    *     `multi-masters').  It is automatically prefixed with
     60    *     `FT_SERVICE_ID_'.
     61    *
     62    * @output:
     63    *   ptr ::
     64    *     A variable that receives the service pointer.  Will be NULL
     65    *     if not found.
     66    */
     67 #ifdef __cplusplus
     68 
     69 #define FT_FACE_FIND_SERVICE( face, ptr, id )                               \
     70   FT_BEGIN_STMNT                                                            \
     71     FT_Module    module = FT_MODULE( FT_FACE( face )->driver );             \
     72     FT_Pointer   _tmp_  = NULL;                                             \
     73     FT_Pointer*  _pptr_ = (FT_Pointer*)&(ptr);                              \
     74                                                                             \
     75                                                                             \
     76     if ( module->clazz->get_interface )                                     \
     77       _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
     78     *_pptr_ = _tmp_;                                                        \
     79   FT_END_STMNT
     80 
     81 #else /* !C++ */
     82 
     83 #define FT_FACE_FIND_SERVICE( face, ptr, id )                               \
     84   FT_BEGIN_STMNT                                                            \
     85     FT_Module   module = FT_MODULE( FT_FACE( face )->driver );              \
     86     FT_Pointer  _tmp_  = NULL;                                              \
     87                                                                             \
     88     if ( module->clazz->get_interface )                                     \
     89       _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
     90     ptr = _tmp_;                                                            \
     91   FT_END_STMNT
     92 
     93 #endif /* !C++ */
     94 
     95   /*
     96    * @macro:
     97    *   FT_FACE_FIND_GLOBAL_SERVICE
     98    *
     99    * @description:
    100    *   This macro is used to look up a service from all modules.
    101    *
    102    * @input:
    103    *   face ::
    104    *     The source face handle.
    105    *
    106    *   id ::
    107    *     A string describing the service as defined in the service's
    108    *     header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
    109    *     `multi-masters').  It is automatically prefixed with
    110    *     `FT_SERVICE_ID_'.
    111    *
    112    * @output:
    113    *   ptr ::
    114    *     A variable that receives the service pointer.  Will be NULL
    115    *     if not found.
    116    */
    117 #ifdef __cplusplus
    118 
    119 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )               \
    120   FT_BEGIN_STMNT                                                   \
    121     FT_Module    module = FT_MODULE( FT_FACE( face )->driver );    \
    122     FT_Pointer   _tmp_;                                            \
    123     FT_Pointer*  _pptr_ = (FT_Pointer*)&(ptr);                     \
    124                                                                    \
    125                                                                    \
    126     _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \
    127     *_pptr_ = _tmp_;                                               \
    128   FT_END_STMNT
    129 
    130 #else /* !C++ */
    131 
    132 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )               \
    133   FT_BEGIN_STMNT                                                   \
    134     FT_Module   module = FT_MODULE( FT_FACE( face )->driver );     \
    135     FT_Pointer  _tmp_;                                             \
    136                                                                    \
    137                                                                    \
    138     _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \
    139     ptr   = _tmp_;                                                 \
    140   FT_END_STMNT
    141 
    142 #endif /* !C++ */
    143 
    144 
    145   /*************************************************************************/
    146   /*************************************************************************/
    147   /*****                                                               *****/
    148   /*****         S E R V I C E   D E S C R I P T O R S                 *****/
    149   /*****                                                               *****/
    150   /*************************************************************************/
    151   /*************************************************************************/
    152 
    153   /*
    154    *  The following structure is used to _describe_ a given service
    155    *  to the library.  This is useful to build simple static service lists.
    156    */
    157   typedef struct  FT_ServiceDescRec_
    158   {
    159     const char*  serv_id;     /* service name         */
    160     const void*  serv_data;   /* service pointer/data */
    161 
    162   } FT_ServiceDescRec;
    163 
    164   typedef const FT_ServiceDescRec*  FT_ServiceDesc;
    165 
    166 
    167   /*************************************************************************/
    168   /*                                                                       */
    169   /* <Macro>                                                               */
    170   /*    FT_DEFINE_SERVICEDESCREC1 .. FT_DEFINE_SERVICEDESCREC6             */
    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 #else /* FT_CONFIG_OPTION_PIC */
    268 
    269 #define FT_DEFINE_SERVICEDESCREC1( class_,                                  \
    270                                    serv_id_1, serv_data_1 )                 \
    271   void                                                                      \
    272   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
    273                                FT_ServiceDescRec*  clazz )                  \
    274   {                                                                         \
    275     FT_Memory  memory = library->memory;                                    \
    276                                                                             \
    277                                                                             \
    278     if ( clazz )                                                            \
    279       FT_FREE( clazz );                                                     \
    280   }                                                                         \
    281                                                                             \
    282   FT_Error                                                                  \
    283   FT_Create_Class_ ## class_( FT_Library           library,                 \
    284                               FT_ServiceDescRec**  output_class )           \
    285   {                                                                         \
    286     FT_ServiceDescRec*  clazz;                                              \
    287     FT_Error            error;                                              \
    288     FT_Memory           memory = library->memory;                           \
    289                                                                             \
    290                                                                             \
    291     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 2 ) )                         \
    292       return error;                                                         \
    293                                                                             \
    294     clazz[0].serv_id   = serv_id_1;                                         \
    295     clazz[0].serv_data = serv_data_1;                                       \
    296     clazz[1].serv_id   = NULL;                                              \
    297     clazz[1].serv_data = NULL;                                              \
    298                                                                             \
    299     *output_class = clazz;                                                  \
    300                                                                             \
    301     return FT_Err_Ok;                                                       \
    302   }
    303 
    304 #define FT_DEFINE_SERVICEDESCREC2( class_,                                  \
    305                                    serv_id_1, serv_data_1,                  \
    306                                    serv_id_2, serv_data_2 )                 \
    307   void                                                                      \
    308   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
    309                                FT_ServiceDescRec*  clazz )                  \
    310   {                                                                         \
    311     FT_Memory  memory = library->memory;                                    \
    312                                                                             \
    313                                                                             \
    314     if ( clazz )                                                            \
    315       FT_FREE( clazz );                                                     \
    316   }                                                                         \
    317                                                                             \
    318   FT_Error                                                                  \
    319   FT_Create_Class_ ## class_( FT_Library           library,                 \
    320                               FT_ServiceDescRec**  output_class )           \
    321   {                                                                         \
    322     FT_ServiceDescRec*  clazz;                                              \
    323     FT_Error            error;                                              \
    324     FT_Memory           memory = library->memory;                           \
    325                                                                             \
    326                                                                             \
    327     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 3 ) )                         \
    328       return error;                                                         \
    329                                                                             \
    330     clazz[0].serv_id   = serv_id_1;                                         \
    331     clazz[0].serv_data = serv_data_1;                                       \
    332     clazz[1].serv_id   = serv_id_2;                                         \
    333     clazz[1].serv_data = serv_data_2;                                       \
    334     clazz[2].serv_id   = NULL;                                              \
    335     clazz[2].serv_data = NULL;                                              \
    336                                                                             \
    337     *output_class = clazz;                                                  \
    338                                                                             \
    339     return FT_Err_Ok;                                                       \
    340   }
    341 
    342 #define FT_DEFINE_SERVICEDESCREC3( class_,                                  \
    343                                    serv_id_1, serv_data_1,                  \
    344                                    serv_id_2, serv_data_2,                  \
    345                                    serv_id_3, serv_data_3 )                 \
    346   void                                                                      \
    347   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
    348                                FT_ServiceDescRec*  clazz )                  \
    349   {                                                                         \
    350     FT_Memory  memory = library->memory;                                    \
    351                                                                             \
    352                                                                             \
    353     if ( clazz )                                                            \
    354       FT_FREE( clazz );                                                     \
    355   }                                                                         \
    356                                                                             \
    357   FT_Error                                                                  \
    358   FT_Create_Class_ ## class_( FT_Library           library,                 \
    359                               FT_ServiceDescRec**  output_class )           \
    360   {                                                                         \
    361     FT_ServiceDescRec*  clazz;                                              \
    362     FT_Error            error;                                              \
    363     FT_Memory           memory = library->memory;                           \
    364                                                                             \
    365                                                                             \
    366     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 4 ) )                         \
    367       return error;                                                         \
    368                                                                             \
    369     clazz[0].serv_id   = serv_id_1;                                         \
    370     clazz[0].serv_data = serv_data_1;                                       \
    371     clazz[1].serv_id   = serv_id_2;                                         \
    372     clazz[1].serv_data = serv_data_2;                                       \
    373     clazz[2].serv_id   = serv_id_3;                                         \
    374     clazz[2].serv_data = serv_data_3;                                       \
    375     clazz[3].serv_id   = NULL;                                              \
    376     clazz[3].serv_data = NULL;                                              \
    377                                                                             \
    378     *output_class = clazz;                                                  \
    379                                                                             \
    380     return FT_Err_Ok;                                                       \
    381   }
    382 
    383 #define FT_DEFINE_SERVICEDESCREC4( class_,                                  \
    384                                    serv_id_1, serv_data_1,                  \
    385                                    serv_id_2, serv_data_2,                  \
    386                                    serv_id_3, serv_data_3,                  \
    387                                    serv_id_4, serv_data_4 )                 \
    388   void                                                                      \
    389   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
    390                                FT_ServiceDescRec*  clazz )                  \
    391   {                                                                         \
    392     FT_Memory  memory = library->memory;                                    \
    393                                                                             \
    394                                                                             \
    395     if ( clazz )                                                            \
    396       FT_FREE( clazz );                                                     \
    397   }                                                                         \
    398                                                                             \
    399   FT_Error                                                                  \
    400   FT_Create_Class_ ## class_( FT_Library           library,                 \
    401                               FT_ServiceDescRec**  output_class )           \
    402   {                                                                         \
    403     FT_ServiceDescRec*  clazz;                                              \
    404     FT_Error            error;                                              \
    405     FT_Memory           memory = library->memory;                           \
    406                                                                             \
    407                                                                             \
    408     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 5 ) )                         \
    409       return error;                                                         \
    410                                                                             \
    411     clazz[0].serv_id   = serv_id_1;                                         \
    412     clazz[0].serv_data = serv_data_1;                                       \
    413     clazz[1].serv_id   = serv_id_2;                                         \
    414     clazz[1].serv_data = serv_data_2;                                       \
    415     clazz[2].serv_id   = serv_id_3;                                         \
    416     clazz[2].serv_data = serv_data_3;                                       \
    417     clazz[3].serv_id   = serv_id_4;                                         \
    418     clazz[3].serv_data = serv_data_4;                                       \
    419     clazz[4].serv_id   = NULL;                                              \
    420     clazz[4].serv_data = NULL;                                              \
    421                                                                             \
    422     *output_class = clazz;                                                  \
    423                                                                             \
    424     return FT_Err_Ok;                                                       \
    425   }
    426 
    427 #define FT_DEFINE_SERVICEDESCREC5( class_,                                  \
    428                                    serv_id_1, serv_data_1,                  \
    429                                    serv_id_2, serv_data_2,                  \
    430                                    serv_id_3, serv_data_3,                  \
    431                                    serv_id_4, serv_data_4,                  \
    432                                    serv_id_5, serv_data_5 )                 \
    433   void                                                                      \
    434   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
    435                                FT_ServiceDescRec*  clazz )                  \
    436   {                                                                         \
    437     FT_Memory  memory = library->memory;                                    \
    438                                                                             \
    439                                                                             \
    440     if ( clazz )                                                            \
    441       FT_FREE( clazz );                                                     \
    442   }                                                                         \
    443                                                                             \
    444   FT_Error                                                                  \
    445   FT_Create_Class_ ## class_( FT_Library           library,                 \
    446                               FT_ServiceDescRec**  output_class )           \
    447   {                                                                         \
    448     FT_ServiceDescRec*  clazz;                                              \
    449     FT_Error            error;                                              \
    450     FT_Memory           memory = library->memory;                           \
    451                                                                             \
    452                                                                             \
    453     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 6 ) )                         \
    454       return error;                                                         \
    455                                                                             \
    456     clazz[0].serv_id   = serv_id_1;                                         \
    457     clazz[0].serv_data = serv_data_1;                                       \
    458     clazz[1].serv_id   = serv_id_2;                                         \
    459     clazz[1].serv_data = serv_data_2;                                       \
    460     clazz[2].serv_id   = serv_id_3;                                         \
    461     clazz[2].serv_data = serv_data_3;                                       \
    462     clazz[3].serv_id   = serv_id_4;                                         \
    463     clazz[3].serv_data = serv_data_4;                                       \
    464     clazz[4].serv_id   = serv_id_5;                                         \
    465     clazz[4].serv_data = serv_data_5;                                       \
    466     clazz[5].serv_id   = NULL;                                              \
    467     clazz[5].serv_data = NULL;                                              \
    468                                                                             \
    469     *output_class = clazz;                                                  \
    470                                                                             \
    471     return FT_Err_Ok;                                                       \
    472   }
    473 
    474 #define FT_DEFINE_SERVICEDESCREC6( class_,                                  \
    475                                    serv_id_1, serv_data_1,                  \
    476                                    serv_id_2, serv_data_2,                  \
    477                                    serv_id_3, serv_data_3,                  \
    478                                    serv_id_4, serv_data_4,                  \
    479                                    serv_id_5, serv_data_5,                  \
    480                                    serv_id_6, serv_data_6 )                 \
    481   void                                                                      \
    482   FT_Destroy_Class_ ## class_( FT_Library          library,                 \
    483                                FT_ServiceDescRec*  clazz )                  \
    484   {                                                                         \
    485     FT_Memory  memory = library->memory;                                    \
    486                                                                             \
    487                                                                             \
    488     if ( clazz )                                                            \
    489       FT_FREE( clazz );                                                     \
    490   }                                                                         \
    491                                                                             \
    492   FT_Error                                                                  \
    493   FT_Create_Class_ ## class_( FT_Library           library,                 \
    494                               FT_ServiceDescRec**  output_class)            \
    495   {                                                                         \
    496     FT_ServiceDescRec*  clazz;                                              \
    497     FT_Error            error;                                              \
    498     FT_Memory           memory = library->memory;                           \
    499                                                                             \
    500                                                                             \
    501     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 7 ) )                         \
    502       return error;                                                         \
    503                                                                             \
    504     clazz[0].serv_id   = serv_id_1;                                         \
    505     clazz[0].serv_data = serv_data_1;                                       \
    506     clazz[1].serv_id   = serv_id_2;                                         \
    507     clazz[1].serv_data = serv_data_2;                                       \
    508     clazz[2].serv_id   = serv_id_3;                                         \
    509     clazz[2].serv_data = serv_data_3;                                       \
    510     clazz[3].serv_id   = serv_id_4;                                         \
    511     clazz[3].serv_data = serv_data_4;                                       \
    512     clazz[4].serv_id   = serv_id_5;                                         \
    513     clazz[4].serv_data = serv_data_5;                                       \
    514     clazz[5].serv_id   = serv_id_6;                                         \
    515     clazz[5].serv_data = serv_data_6;                                       \
    516     clazz[6].serv_id   = NULL;                                              \
    517     clazz[6].serv_data = NULL;                                              \
    518                                                                             \
    519     *output_class = clazz;                                                  \
    520                                                                             \
    521     return FT_Err_Ok;                                                       \
    522   }
    523 
    524 #endif /* FT_CONFIG_OPTION_PIC */
    525 
    526 
    527   /*
    528    *  Parse a list of FT_ServiceDescRec descriptors and look for
    529    *  a specific service by ID.  Note that the last element in the
    530    *  array must be { NULL, NULL }, and that the function should
    531    *  return NULL if the service isn't available.
    532    *
    533    *  This function can be used by modules to implement their
    534    *  `get_service' method.
    535    */
    536   FT_BASE( FT_Pointer )
    537   ft_service_list_lookup( FT_ServiceDesc  service_descriptors,
    538                           const char*     service_id );
    539 
    540 
    541   /*************************************************************************/
    542   /*************************************************************************/
    543   /*****                                                               *****/
    544   /*****             S E R V I C E S   C A C H E                       *****/
    545   /*****                                                               *****/
    546   /*************************************************************************/
    547   /*************************************************************************/
    548 
    549   /*
    550    *  This structure is used to store a cache for several frequently used
    551    *  services.  It is the type of `face->internal->services'.  You
    552    *  should only use FT_FACE_LOOKUP_SERVICE to access it.
    553    *
    554    *  All fields should have the type FT_Pointer to relax compilation
    555    *  dependencies.  We assume the developer isn't completely stupid.
    556    *
    557    *  Each field must be named `service_XXXX' where `XXX' corresponds to
    558    *  the correct FT_SERVICE_ID_XXXX macro.  See the definition of
    559    *  FT_FACE_LOOKUP_SERVICE below how this is implemented.
    560    *
    561    */
    562   typedef struct  FT_ServiceCacheRec_
    563   {
    564     FT_Pointer  service_POSTSCRIPT_FONT_NAME;
    565     FT_Pointer  service_MULTI_MASTERS;
    566     FT_Pointer  service_GLYPH_DICT;
    567     FT_Pointer  service_PFR_METRICS;
    568     FT_Pointer  service_WINFNT;
    569 
    570   } FT_ServiceCacheRec, *FT_ServiceCache;
    571 
    572 
    573   /*
    574    *  A magic number used within the services cache.
    575    */
    576 #define FT_SERVICE_UNAVAILABLE  ((FT_Pointer)-2)  /* magic number */
    577 
    578 
    579   /*
    580    * @macro:
    581    *   FT_FACE_LOOKUP_SERVICE
    582    *
    583    * @description:
    584    *   This macro is used to lookup a service from a face's driver module
    585    *   using its cache.
    586    *
    587    * @input:
    588    *   face::
    589    *     The source face handle containing the cache.
    590    *
    591    *   field ::
    592    *     The field name in the cache.
    593    *
    594    *   id ::
    595    *     The service ID.
    596    *
    597    * @output:
    598    *   ptr ::
    599    *     A variable receiving the service data.  NULL if not available.
    600    */
    601 #ifdef __cplusplus
    602 
    603 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
    604   FT_BEGIN_STMNT                                               \
    605     FT_Pointer   svc;                                          \
    606     FT_Pointer*  Pptr = (FT_Pointer*)&(ptr);                   \
    607                                                                \
    608                                                                \
    609     svc = FT_FACE( face )->internal->services. service_ ## id; \
    610     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
    611       svc = NULL;                                              \
    612     else if ( svc == NULL )                                    \
    613     {                                                          \
    614       FT_FACE_FIND_SERVICE( face, svc, id );                   \
    615                                                                \
    616       FT_FACE( face )->internal->services. service_ ## id =    \
    617         (FT_Pointer)( svc != NULL ? svc                        \
    618                                   : FT_SERVICE_UNAVAILABLE );  \
    619     }                                                          \
    620     *Pptr = svc;                                               \
    621   FT_END_STMNT
    622 
    623 #else /* !C++ */
    624 
    625 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
    626   FT_BEGIN_STMNT                                               \
    627     FT_Pointer  svc;                                           \
    628                                                                \
    629                                                                \
    630     svc = FT_FACE( face )->internal->services. service_ ## id; \
    631     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
    632       svc = NULL;                                              \
    633     else if ( svc == NULL )                                    \
    634     {                                                          \
    635       FT_FACE_FIND_SERVICE( face, svc, id );                   \
    636                                                                \
    637       FT_FACE( face )->internal->services. service_ ## id =    \
    638         (FT_Pointer)( svc != NULL ? svc                        \
    639                                   : FT_SERVICE_UNAVAILABLE );  \
    640     }                                                          \
    641     ptr = svc;                                                 \
    642   FT_END_STMNT
    643 
    644 #endif /* !C++ */
    645 
    646   /*
    647    *  A macro used to define new service structure types.
    648    */
    649 
    650 #define FT_DEFINE_SERVICE( name )            \
    651   typedef struct FT_Service_ ## name ## Rec_ \
    652     FT_Service_ ## name ## Rec ;             \
    653   typedef struct FT_Service_ ## name ## Rec_ \
    654     const * FT_Service_ ## name ;            \
    655   struct FT_Service_ ## name ## Rec_
    656 
    657   /* */
    658 
    659   /*
    660    *  The header files containing the services.
    661    */
    662 
    663 #define FT_SERVICE_BDF_H                <freetype/internal/services/svbdf.h>
    664 #define FT_SERVICE_CID_H                <freetype/internal/services/svcid.h>
    665 #define FT_SERVICE_GLYPH_DICT_H         <freetype/internal/services/svgldict.h>
    666 #define FT_SERVICE_GX_VALIDATE_H        <freetype/internal/services/svgxval.h>
    667 #define FT_SERVICE_KERNING_H            <freetype/internal/services/svkern.h>
    668 #define FT_SERVICE_MULTIPLE_MASTERS_H   <freetype/internal/services/svmm.h>
    669 #define FT_SERVICE_OPENTYPE_VALIDATE_H  <freetype/internal/services/svotval.h>
    670 #define FT_SERVICE_PFR_H                <freetype/internal/services/svpfr.h>
    671 #define FT_SERVICE_POSTSCRIPT_CMAPS_H   <freetype/internal/services/svpscmap.h>
    672 #define FT_SERVICE_POSTSCRIPT_INFO_H    <freetype/internal/services/svpsinfo.h>
    673 #define FT_SERVICE_POSTSCRIPT_NAME_H    <freetype/internal/services/svpostnm.h>
    674 #define FT_SERVICE_SFNT_H               <freetype/internal/services/svsfnt.h>
    675 #define FT_SERVICE_TRUETYPE_ENGINE_H    <freetype/internal/services/svtteng.h>
    676 #define FT_SERVICE_TT_CMAP_H            <freetype/internal/services/svttcmap.h>
    677 #define FT_SERVICE_WINFNT_H             <freetype/internal/services/svwinfnt.h>
    678 #define FT_SERVICE_XFREE86_NAME_H       <freetype/internal/services/svxf86nm.h>
    679 #define FT_SERVICE_TRUETYPE_GLYF_H      <freetype/internal/services/svttglyf.h>
    680 
    681  /* */
    682 
    683 FT_END_HEADER
    684 
    685 #endif /* __FTSERV_H__ */
    686 
    687 
    688 /* END */
    689