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