Home | History | Annotate | Download | only in internal
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftserv.h                                                               */
      4 /*                                                                         */
      5 /*    The FreeType services (specification only).                          */
      6 /*                                                                         */
      7 /*  Copyright 2003, 2004, 2005, 2006, 2007 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   /* <Macro>                                                               */
    169   /*    FT_DEFINE_SERVICEDESCREC1 .. FT_DEFINE_SERVICEDESCREC6             */
    170   /*                                                                       */
    171   /* <Description>                                                         */
    172   /*    Used to initialize an array of FT_ServiceDescRec structs.          */
    173   /*                                                                       */
    174   /*    When FT_CONFIG_OPTION_PIC is defined a Create funtion will need    */
    175   /*    to called with a pointer where the allocated array is returned.    */
    176   /*    And when it is no longer needed a Destroy function needs           */
    177   /*    to be called to release that allocation.                           */
    178   /*                                                                       */
    179   /*    These functions should be manyally 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        */
    184   /*    is used).                                                          */
    185   /*                                                                       */
    186 #ifndef FT_CONFIG_OPTION_PIC
    187 
    188 #define FT_DEFINE_SERVICEDESCREC1(class_, serv_id_1, serv_data_1)            \
    189   static const FT_ServiceDescRec class_[] =                                  \
    190   {                                                                          \
    191   {serv_id_1, serv_data_1},                                                  \
    192   {NULL, NULL}                                                               \
    193   };
    194 #define FT_DEFINE_SERVICEDESCREC2(class_, serv_id_1, serv_data_1,            \
    195         serv_id_2, serv_data_2)                                              \
    196   static const FT_ServiceDescRec class_[] =                                  \
    197   {                                                                          \
    198   {serv_id_1, serv_data_1},                                                  \
    199   {serv_id_2, serv_data_2},                                                  \
    200   {NULL, NULL}                                                               \
    201   };
    202 #define FT_DEFINE_SERVICEDESCREC3(class_, serv_id_1, serv_data_1,            \
    203         serv_id_2, serv_data_2, serv_id_3, serv_data_3)                      \
    204   static const FT_ServiceDescRec class_[] =                                  \
    205   {                                                                          \
    206   {serv_id_1, serv_data_1},                                                  \
    207   {serv_id_2, serv_data_2},                                                  \
    208   {serv_id_3, serv_data_3},                                                  \
    209   {NULL, NULL}                                                               \
    210   };
    211 #define FT_DEFINE_SERVICEDESCREC4(class_, serv_id_1, serv_data_1,            \
    212         serv_id_2, serv_data_2, serv_id_3, serv_data_3,                      \
    213         serv_id_4, serv_data_4)                                              \
    214   static const FT_ServiceDescRec class_[] =                                  \
    215   {                                                                          \
    216   {serv_id_1, serv_data_1},                                                  \
    217   {serv_id_2, serv_data_2},                                                  \
    218   {serv_id_3, serv_data_3},                                                  \
    219   {serv_id_4, serv_data_4},                                                  \
    220   {NULL, NULL}                                                               \
    221   };
    222 #define FT_DEFINE_SERVICEDESCREC5(class_, serv_id_1, serv_data_1,            \
    223         serv_id_2, serv_data_2, serv_id_3, serv_data_3,                      \
    224         serv_id_4, serv_data_4, serv_id_5, serv_data_5)                      \
    225   static const FT_ServiceDescRec class_[] =                                  \
    226   {                                                                          \
    227   {serv_id_1, serv_data_1},                                                  \
    228   {serv_id_2, serv_data_2},                                                  \
    229   {serv_id_3, serv_data_3},                                                  \
    230   {serv_id_4, serv_data_4},                                                  \
    231   {serv_id_5, serv_data_5},                                                  \
    232   {NULL, NULL}                                                               \
    233   };
    234 #define FT_DEFINE_SERVICEDESCREC6(class_, serv_id_1, serv_data_1,            \
    235         serv_id_2, serv_data_2, serv_id_3, serv_data_3,                      \
    236         serv_id_4, serv_data_4, serv_id_5, serv_data_5,                      \
    237         serv_id_6, serv_data_6)                                              \
    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   {serv_id_6, serv_data_6},                                                  \
    246   {NULL, NULL}                                                               \
    247   };
    248 
    249 #else /* FT_CONFIG_OPTION_PIC */
    250 
    251 #define FT_DEFINE_SERVICEDESCREC1(class_, serv_id_1, serv_data_1)            \
    252   void                                                                       \
    253   FT_Destroy_Class_##class_( FT_Library library,                             \
    254                              FT_ServiceDescRec* clazz )                      \
    255   {                                                                          \
    256     FT_Memory memory = library->memory;                                      \
    257     if ( clazz )                                                             \
    258       FT_FREE( clazz );                                                      \
    259   }                                                                          \
    260                                                                              \
    261   FT_Error                                                                   \
    262   FT_Create_Class_##class_( FT_Library library,                              \
    263                             FT_ServiceDescRec** output_class)                \
    264   {                                                                          \
    265     FT_ServiceDescRec*  clazz;                                               \
    266     FT_Error          error;                                                 \
    267     FT_Memory memory = library->memory;                                      \
    268                                                                              \
    269     if ( FT_ALLOC( clazz, sizeof(*clazz)*2 ) )                               \
    270       return error;                                                          \
    271     clazz[0].serv_id = serv_id_1;                                            \
    272     clazz[0].serv_data = serv_data_1;                                        \
    273     clazz[1].serv_id = NULL;                                                 \
    274     clazz[1].serv_data = NULL;                                               \
    275     *output_class = clazz;                                                   \
    276     return FT_Err_Ok;                                                        \
    277   }
    278 
    279 #define FT_DEFINE_SERVICEDESCREC2(class_, serv_id_1, serv_data_1,            \
    280         serv_id_2, serv_data_2)                                              \
    281   void                                                                       \
    282   FT_Destroy_Class_##class_( FT_Library library,                             \
    283                              FT_ServiceDescRec* clazz )                      \
    284   {                                                                          \
    285     FT_Memory memory = library->memory;                                      \
    286     if ( clazz )                                                             \
    287       FT_FREE( clazz );                                                      \
    288   }                                                                          \
    289                                                                              \
    290   FT_Error                                                                   \
    291   FT_Create_Class_##class_( FT_Library library,                              \
    292                             FT_ServiceDescRec** output_class)                \
    293   {                                                                          \
    294     FT_ServiceDescRec*  clazz;                                               \
    295     FT_Error          error;                                                 \
    296     FT_Memory memory = library->memory;                                      \
    297                                                                              \
    298     if ( FT_ALLOC( clazz, sizeof(*clazz)*3 ) )                               \
    299       return error;                                                          \
    300     clazz[0].serv_id = serv_id_1;                                            \
    301     clazz[0].serv_data = serv_data_1;                                        \
    302     clazz[1].serv_id = serv_id_2;                                            \
    303     clazz[1].serv_data = serv_data_2;                                        \
    304     clazz[2].serv_id = NULL;                                                 \
    305     clazz[2].serv_data = NULL;                                               \
    306     *output_class = clazz;                                                   \
    307     return FT_Err_Ok;                                                        \
    308   }
    309 
    310 #define FT_DEFINE_SERVICEDESCREC3(class_, serv_id_1, serv_data_1,            \
    311         serv_id_2, serv_data_2, serv_id_3, serv_data_3)                      \
    312   void                                                                       \
    313   FT_Destroy_Class_##class_( FT_Library library,                             \
    314                              FT_ServiceDescRec* clazz )                      \
    315   {                                                                          \
    316     FT_Memory memory = library->memory;                                      \
    317     if ( clazz )                                                             \
    318       FT_FREE( clazz );                                                      \
    319   }                                                                          \
    320                                                                              \
    321   FT_Error                                                                   \
    322   FT_Create_Class_##class_( FT_Library library,                              \
    323                             FT_ServiceDescRec** output_class)                \
    324   {                                                                          \
    325     FT_ServiceDescRec*  clazz;                                               \
    326     FT_Error          error;                                                 \
    327     FT_Memory memory = library->memory;                                      \
    328                                                                              \
    329     if ( FT_ALLOC( clazz, sizeof(*clazz)*4 ) )                               \
    330       return error;                                                          \
    331     clazz[0].serv_id = serv_id_1;                                            \
    332     clazz[0].serv_data = serv_data_1;                                        \
    333     clazz[1].serv_id = serv_id_2;                                            \
    334     clazz[1].serv_data = serv_data_2;                                        \
    335     clazz[2].serv_id = serv_id_3;                                            \
    336     clazz[2].serv_data = serv_data_3;                                        \
    337     clazz[3].serv_id = NULL;                                                 \
    338     clazz[3].serv_data = NULL;                                               \
    339     *output_class = clazz;                                                   \
    340     return FT_Err_Ok;                                                        \
    341   }
    342 
    343 #define FT_DEFINE_SERVICEDESCREC4(class_, serv_id_1, serv_data_1,            \
    344         serv_id_2, serv_data_2, serv_id_3, serv_data_3,                      \
    345         serv_id_4, serv_data_4)                                              \
    346   void                                                                       \
    347   FT_Destroy_Class_##class_( FT_Library library,                             \
    348                              FT_ServiceDescRec* clazz )                      \
    349   {                                                                          \
    350     FT_Memory memory = library->memory;                                      \
    351     if ( clazz )                                                             \
    352       FT_FREE( clazz );                                                      \
    353   }                                                                          \
    354                                                                              \
    355   FT_Error                                                                   \
    356   FT_Create_Class_##class_( FT_Library library,                              \
    357                             FT_ServiceDescRec** output_class)                \
    358   {                                                                          \
    359     FT_ServiceDescRec*  clazz;                                               \
    360     FT_Error          error;                                                 \
    361     FT_Memory memory = library->memory;                                      \
    362                                                                              \
    363     if ( FT_ALLOC( clazz, sizeof(*clazz)*5 ) )                               \
    364       return error;                                                          \
    365     clazz[0].serv_id = serv_id_1;                                            \
    366     clazz[0].serv_data = serv_data_1;                                        \
    367     clazz[1].serv_id = serv_id_2;                                            \
    368     clazz[1].serv_data = serv_data_2;                                        \
    369     clazz[2].serv_id = serv_id_3;                                            \
    370     clazz[2].serv_data = serv_data_3;                                        \
    371     clazz[3].serv_id = serv_id_4;                                            \
    372     clazz[3].serv_data = serv_data_4;                                        \
    373     clazz[4].serv_id = NULL;                                                 \
    374     clazz[4].serv_data = NULL;                                               \
    375     *output_class = clazz;                                                   \
    376     return FT_Err_Ok;                                                        \
    377   }
    378 
    379 #define FT_DEFINE_SERVICEDESCREC5(class_, serv_id_1, serv_data_1,            \
    380         serv_id_2, serv_data_2, serv_id_3, serv_data_3, serv_id_4,           \
    381         serv_data_4, serv_id_5, serv_data_5)                                 \
    382   void                                                                       \
    383   FT_Destroy_Class_##class_( FT_Library library,                             \
    384                              FT_ServiceDescRec* clazz )                      \
    385   {                                                                          \
    386     FT_Memory memory = library->memory;                                      \
    387     if ( clazz )                                                             \
    388       FT_FREE( clazz );                                                      \
    389   }                                                                          \
    390                                                                              \
    391   FT_Error                                                                   \
    392   FT_Create_Class_##class_( FT_Library library,                              \
    393                             FT_ServiceDescRec** output_class)                \
    394   {                                                                          \
    395     FT_ServiceDescRec*  clazz;                                               \
    396     FT_Error          error;                                                 \
    397     FT_Memory memory = library->memory;                                      \
    398                                                                              \
    399     if ( FT_ALLOC( clazz, sizeof(*clazz)*6 ) )                               \
    400       return error;                                                          \
    401     clazz[0].serv_id = serv_id_1;                                            \
    402     clazz[0].serv_data = serv_data_1;                                        \
    403     clazz[1].serv_id = serv_id_2;                                            \
    404     clazz[1].serv_data = serv_data_2;                                        \
    405     clazz[2].serv_id = serv_id_3;                                            \
    406     clazz[2].serv_data = serv_data_3;                                        \
    407     clazz[3].serv_id = serv_id_4;                                            \
    408     clazz[3].serv_data = serv_data_4;                                        \
    409     clazz[4].serv_id = serv_id_5;                                            \
    410     clazz[4].serv_data = serv_data_5;                                        \
    411     clazz[5].serv_id = NULL;                                                 \
    412     clazz[5].serv_data = NULL;                                               \
    413     *output_class = clazz;                                                   \
    414     return FT_Err_Ok;                                                        \
    415   }
    416 
    417 #define FT_DEFINE_SERVICEDESCREC6(class_, serv_id_1, serv_data_1,            \
    418         serv_id_2, serv_data_2, serv_id_3, serv_data_3,                      \
    419         serv_id_4, serv_data_4, serv_id_5, serv_data_5,                      \
    420         serv_id_6, serv_data_6)                                              \
    421   void                                                                       \
    422   FT_Destroy_Class_##class_( FT_Library library,                             \
    423                              FT_ServiceDescRec* clazz )                      \
    424   {                                                                          \
    425     FT_Memory memory = library->memory;                                      \
    426     if ( clazz )                                                             \
    427       FT_FREE( clazz );                                                      \
    428   }                                                                          \
    429                                                                              \
    430   FT_Error                                                                   \
    431   FT_Create_Class_##class_( FT_Library library,                              \
    432                             FT_ServiceDescRec** output_class)                \
    433   {                                                                          \
    434     FT_ServiceDescRec*  clazz;                                               \
    435     FT_Error          error;                                                 \
    436     FT_Memory memory = library->memory;                                      \
    437                                                                              \
    438     if ( FT_ALLOC( clazz, sizeof(*clazz)*7 ) )                               \
    439       return error;                                                          \
    440     clazz[0].serv_id = serv_id_1;                                            \
    441     clazz[0].serv_data = serv_data_1;                                        \
    442     clazz[1].serv_id = serv_id_2;                                            \
    443     clazz[1].serv_data = serv_data_2;                                        \
    444     clazz[2].serv_id = serv_id_3;                                            \
    445     clazz[2].serv_data = serv_data_3;                                        \
    446     clazz[3].serv_id = serv_id_4;                                            \
    447     clazz[3].serv_data = serv_data_4;                                        \
    448     clazz[4].serv_id = serv_id_5;                                            \
    449     clazz[4].serv_data = serv_data_5;                                        \
    450     clazz[5].serv_id = serv_id_6;                                            \
    451     clazz[5].serv_data = serv_data_6;                                        \
    452     clazz[6].serv_id = NULL;                                                 \
    453     clazz[6].serv_data = NULL;                                               \
    454     *output_class = clazz;                                                   \
    455     return FT_Err_Ok;                                                        \
    456   }
    457 #endif /* FT_CONFIG_OPTION_PIC */
    458 
    459   /*
    460    *  Parse a list of FT_ServiceDescRec descriptors and look for
    461    *  a specific service by ID.  Note that the last element in the
    462    *  array must be { NULL, NULL }, and that the function should
    463    *  return NULL if the service isn't available.
    464    *
    465    *  This function can be used by modules to implement their
    466    *  `get_service' method.
    467    */
    468   FT_BASE( FT_Pointer )
    469   ft_service_list_lookup( FT_ServiceDesc  service_descriptors,
    470                           const char*     service_id );
    471 
    472 
    473   /*************************************************************************/
    474   /*************************************************************************/
    475   /*****                                                               *****/
    476   /*****             S E R V I C E S   C A C H E                       *****/
    477   /*****                                                               *****/
    478   /*************************************************************************/
    479   /*************************************************************************/
    480 
    481   /*
    482    *  This structure is used to store a cache for several frequently used
    483    *  services.  It is the type of `face->internal->services'.  You
    484    *  should only use FT_FACE_LOOKUP_SERVICE to access it.
    485    *
    486    *  All fields should have the type FT_Pointer to relax compilation
    487    *  dependencies.  We assume the developer isn't completely stupid.
    488    *
    489    *  Each field must be named `service_XXXX' where `XXX' corresponds to
    490    *  the correct FT_SERVICE_ID_XXXX macro.  See the definition of
    491    *  FT_FACE_LOOKUP_SERVICE below how this is implemented.
    492    *
    493    */
    494   typedef struct  FT_ServiceCacheRec_
    495   {
    496     FT_Pointer  service_POSTSCRIPT_FONT_NAME;
    497     FT_Pointer  service_MULTI_MASTERS;
    498     FT_Pointer  service_GLYPH_DICT;
    499     FT_Pointer  service_PFR_METRICS;
    500     FT_Pointer  service_WINFNT;
    501 
    502   } FT_ServiceCacheRec, *FT_ServiceCache;
    503 
    504 
    505   /*
    506    *  A magic number used within the services cache.
    507    */
    508 #define FT_SERVICE_UNAVAILABLE  ((FT_Pointer)-2)  /* magic number */
    509 
    510 
    511   /*
    512    * @macro:
    513    *   FT_FACE_LOOKUP_SERVICE
    514    *
    515    * @description:
    516    *   This macro is used to lookup a service from a face's driver module
    517    *   using its cache.
    518    *
    519    * @input:
    520    *   face::
    521    *     The source face handle containing the cache.
    522    *
    523    *   field ::
    524    *     The field name in the cache.
    525    *
    526    *   id ::
    527    *     The service ID.
    528    *
    529    * @output:
    530    *   ptr ::
    531    *     A variable receiving the service data.  NULL if not available.
    532    */
    533 #ifdef __cplusplus
    534 
    535 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
    536   FT_BEGIN_STMNT                                               \
    537     FT_Pointer   svc;                                          \
    538     FT_Pointer*  Pptr = (FT_Pointer*)&(ptr);                   \
    539                                                                \
    540                                                                \
    541     svc = FT_FACE( face )->internal->services. service_ ## id; \
    542     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
    543       svc = NULL;                                              \
    544     else if ( svc == NULL )                                    \
    545     {                                                          \
    546       FT_FACE_FIND_SERVICE( face, svc, id );                   \
    547                                                                \
    548       FT_FACE( face )->internal->services. service_ ## id =    \
    549         (FT_Pointer)( svc != NULL ? svc                        \
    550                                   : FT_SERVICE_UNAVAILABLE );  \
    551     }                                                          \
    552     *Pptr = svc;                                               \
    553   FT_END_STMNT
    554 
    555 #else /* !C++ */
    556 
    557 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
    558   FT_BEGIN_STMNT                                               \
    559     FT_Pointer  svc;                                           \
    560                                                                \
    561                                                                \
    562     svc = FT_FACE( face )->internal->services. service_ ## id; \
    563     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
    564       svc = NULL;                                              \
    565     else if ( svc == NULL )                                    \
    566     {                                                          \
    567       FT_FACE_FIND_SERVICE( face, svc, id );                   \
    568                                                                \
    569       FT_FACE( face )->internal->services. service_ ## id =    \
    570         (FT_Pointer)( svc != NULL ? svc                        \
    571                                   : FT_SERVICE_UNAVAILABLE );  \
    572     }                                                          \
    573     ptr = svc;                                                 \
    574   FT_END_STMNT
    575 
    576 #endif /* !C++ */
    577 
    578   /*
    579    *  A macro used to define new service structure types.
    580    */
    581 
    582 #define FT_DEFINE_SERVICE( name )            \
    583   typedef struct FT_Service_ ## name ## Rec_ \
    584     FT_Service_ ## name ## Rec ;             \
    585   typedef struct FT_Service_ ## name ## Rec_ \
    586     const * FT_Service_ ## name ;            \
    587   struct FT_Service_ ## name ## Rec_
    588 
    589   /* */
    590 
    591   /*
    592    *  The header files containing the services.
    593    */
    594 
    595 #define FT_SERVICE_BDF_H                <freetype/internal/services/svbdf.h>
    596 #define FT_SERVICE_CID_H                <freetype/internal/services/svcid.h>
    597 #define FT_SERVICE_GLYPH_DICT_H         <freetype/internal/services/svgldict.h>
    598 #define FT_SERVICE_GX_VALIDATE_H        <freetype/internal/services/svgxval.h>
    599 #define FT_SERVICE_KERNING_H            <freetype/internal/services/svkern.h>
    600 #define FT_SERVICE_MULTIPLE_MASTERS_H   <freetype/internal/services/svmm.h>
    601 #define FT_SERVICE_OPENTYPE_VALIDATE_H  <freetype/internal/services/svotval.h>
    602 #define FT_SERVICE_PFR_H                <freetype/internal/services/svpfr.h>
    603 #define FT_SERVICE_POSTSCRIPT_CMAPS_H   <freetype/internal/services/svpscmap.h>
    604 #define FT_SERVICE_POSTSCRIPT_INFO_H    <freetype/internal/services/svpsinfo.h>
    605 #define FT_SERVICE_POSTSCRIPT_NAME_H    <freetype/internal/services/svpostnm.h>
    606 #define FT_SERVICE_SFNT_H               <freetype/internal/services/svsfnt.h>
    607 #define FT_SERVICE_TRUETYPE_ENGINE_H    <freetype/internal/services/svtteng.h>
    608 #define FT_SERVICE_TT_CMAP_H            <freetype/internal/services/svttcmap.h>
    609 #define FT_SERVICE_WINFNT_H             <freetype/internal/services/svwinfnt.h>
    610 #define FT_SERVICE_XFREE86_NAME_H       <freetype/internal/services/svxf86nm.h>
    611 #define FT_SERVICE_TRUETYPE_GLYF_H      <freetype/internal/services/svttglyf.h>
    612 
    613  /* */
    614 
    615 FT_END_HEADER
    616 
    617 #endif /* __FTSERV_H__ */
    618 
    619 
    620 /* END */
    621