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