Home | History | Annotate | Line # | Download | only in internal
      1 /****************************************************************************
      2  *
      3  * ftserv.h
      4  *
      5  *   The FreeType services (specification only).
      6  *
      7  * Copyright (C) 2003-2020 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 in
     25    * C it is possible that function pointers might be implemented differently
     26    * than data pointers (e.g. 48 bits instead of 32).
     27    *
     28    */
     29 
     30 
     31 #ifndef FTSERV_H_
     32 #define FTSERV_H_
     33 
     34 #include "compiler-macros.h"
     35 
     36 FT_BEGIN_HEADER
     37 
     38   /**************************************************************************
     39    *
     40    * @macro:
     41    *   FT_FACE_FIND_SERVICE
     42    *
     43    * @description:
     44    *   This macro is used to look up a service from a face's driver module.
     45    *
     46    * @input:
     47    *   face ::
     48    *     The source face handle.
     49    *
     50    *   id ::
     51    *     A string describing the service as defined in the service's header
     52    *     files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
     53    *     'multi-masters').  It is automatically prefixed with
     54    *     `FT_SERVICE_ID_`.
     55    *
     56    * @output:
     57    *   ptr ::
     58    *     A variable that receives the service pointer.  Will be `NULL` if not
     59    *     found.
     60    */
     61 #ifdef __cplusplus
     62 
     63 #define FT_FACE_FIND_SERVICE( face, ptr, id )                               \
     64   FT_BEGIN_STMNT                                                            \
     65     FT_Module    module = FT_MODULE( FT_FACE( face )->driver );             \
     66     FT_Pointer   _tmp_  = NULL;                                             \
     67     FT_Pointer*  _pptr_ = (FT_Pointer*)&(ptr);                              \
     68                                                                             \
     69                                                                             \
     70     if ( module->clazz->get_interface )                                     \
     71       _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
     72     *_pptr_ = _tmp_;                                                        \
     73   FT_END_STMNT
     74 
     75 #else /* !C++ */
     76 
     77 #define FT_FACE_FIND_SERVICE( face, ptr, id )                               \
     78   FT_BEGIN_STMNT                                                            \
     79     FT_Module   module = FT_MODULE( FT_FACE( face )->driver );              \
     80     FT_Pointer  _tmp_  = NULL;                                              \
     81                                                                             \
     82     if ( module->clazz->get_interface )                                     \
     83       _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
     84     ptr = _tmp_;                                                            \
     85   FT_END_STMNT
     86 
     87 #endif /* !C++ */
     88 
     89 
     90   /**************************************************************************
     91    *
     92    * @macro:
     93    *   FT_FACE_FIND_GLOBAL_SERVICE
     94    *
     95    * @description:
     96    *   This macro is used to look up a service from all modules.
     97    *
     98    * @input:
     99    *   face ::
    100    *     The source face handle.
    101    *
    102    *   id ::
    103    *     A string describing the service as defined in the service's header
    104    *     files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
    105    *     'multi-masters').  It is automatically prefixed with
    106    *     `FT_SERVICE_ID_`.
    107    *
    108    * @output:
    109    *   ptr ::
    110    *     A variable that receives the service pointer.  Will be `NULL` if not
    111    *     found.
    112    */
    113 #ifdef __cplusplus
    114 
    115 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )                  \
    116   FT_BEGIN_STMNT                                                      \
    117     FT_Module    module = FT_MODULE( FT_FACE( face )->driver );       \
    118     FT_Pointer   _tmp_;                                               \
    119     FT_Pointer*  _pptr_ = (FT_Pointer*)&(ptr);                        \
    120                                                                       \
    121                                                                       \
    122     _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
    123     *_pptr_ = _tmp_;                                                  \
    124   FT_END_STMNT
    125 
    126 #else /* !C++ */
    127 
    128 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )                  \
    129   FT_BEGIN_STMNT                                                      \
    130     FT_Module   module = FT_MODULE( FT_FACE( face )->driver );        \
    131     FT_Pointer  _tmp_;                                                \
    132                                                                       \
    133                                                                       \
    134     _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
    135     ptr   = _tmp_;                                                    \
    136   FT_END_STMNT
    137 
    138 #endif /* !C++ */
    139 
    140 
    141   /*************************************************************************/
    142   /*************************************************************************/
    143   /*****                                                               *****/
    144   /*****         S E R V I C E   D E S C R I P T O R S                 *****/
    145   /*****                                                               *****/
    146   /*************************************************************************/
    147   /*************************************************************************/
    148 
    149   /*
    150    * The following structure is used to _describe_ a given service to the
    151    * library.  This is useful to build simple static service lists.
    152    */
    153   typedef struct  FT_ServiceDescRec_
    154   {
    155     const char*  serv_id;     /* service name         */
    156     const void*  serv_data;   /* service pointer/data */
    157 
    158   } FT_ServiceDescRec;
    159 
    160   typedef const FT_ServiceDescRec*  FT_ServiceDesc;
    161 
    162 
    163   /**************************************************************************
    164    *
    165    * @macro:
    166    *   FT_DEFINE_SERVICEDESCREC1
    167    *   FT_DEFINE_SERVICEDESCREC2
    168    *   FT_DEFINE_SERVICEDESCREC3
    169    *   FT_DEFINE_SERVICEDESCREC4
    170    *   FT_DEFINE_SERVICEDESCREC5
    171    *   FT_DEFINE_SERVICEDESCREC6
    172    *   FT_DEFINE_SERVICEDESCREC7
    173    *   FT_DEFINE_SERVICEDESCREC8
    174    *   FT_DEFINE_SERVICEDESCREC9
    175    *   FT_DEFINE_SERVICEDESCREC10
    176    *
    177    * @description:
    178    *   Used to initialize an array of FT_ServiceDescRec structures.
    179    *
    180    *   The array will be allocated in the global scope (or the scope where
    181    *   the macro is used).
    182    */
    183 #define FT_DEFINE_SERVICEDESCREC1( class_,                                  \
    184                                    serv_id_1, serv_data_1 )                 \
    185   static const FT_ServiceDescRec  class_[] =                                \
    186   {                                                                         \
    187     { serv_id_1, serv_data_1 },                                             \
    188     { NULL, NULL }                                                          \
    189   };
    190 
    191 #define FT_DEFINE_SERVICEDESCREC2( class_,                                  \
    192                                    serv_id_1, serv_data_1,                  \
    193                                    serv_id_2, serv_data_2 )                 \
    194   static const FT_ServiceDescRec  class_[] =                                \
    195   {                                                                         \
    196     { serv_id_1, serv_data_1 },                                             \
    197     { serv_id_2, serv_data_2 },                                             \
    198     { NULL, NULL }                                                          \
    199   };
    200 
    201 #define FT_DEFINE_SERVICEDESCREC3( class_,                                  \
    202                                    serv_id_1, serv_data_1,                  \
    203                                    serv_id_2, serv_data_2,                  \
    204                                    serv_id_3, serv_data_3 )                 \
    205   static const FT_ServiceDescRec  class_[] =                                \
    206   {                                                                         \
    207     { serv_id_1, serv_data_1 },                                             \
    208     { serv_id_2, serv_data_2 },                                             \
    209     { serv_id_3, serv_data_3 },                                             \
    210     { NULL, NULL }                                                          \
    211   };
    212 
    213 #define FT_DEFINE_SERVICEDESCREC4( class_,                                  \
    214                                    serv_id_1, serv_data_1,                  \
    215                                    serv_id_2, serv_data_2,                  \
    216                                    serv_id_3, serv_data_3,                  \
    217                                    serv_id_4, serv_data_4 )                 \
    218   static const FT_ServiceDescRec  class_[] =                                \
    219   {                                                                         \
    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     { NULL, NULL }                                                          \
    225   };
    226 
    227 #define FT_DEFINE_SERVICEDESCREC5( class_,                                  \
    228                                    serv_id_1, serv_data_1,                  \
    229                                    serv_id_2, serv_data_2,                  \
    230                                    serv_id_3, serv_data_3,                  \
    231                                    serv_id_4, serv_data_4,                  \
    232                                    serv_id_5, serv_data_5 )                 \
    233   static const FT_ServiceDescRec  class_[] =                                \
    234   {                                                                         \
    235     { serv_id_1, serv_data_1 },                                             \
    236     { serv_id_2, serv_data_2 },                                             \
    237     { serv_id_3, serv_data_3 },                                             \
    238     { serv_id_4, serv_data_4 },                                             \
    239     { serv_id_5, serv_data_5 },                                             \
    240     { NULL, NULL }                                                          \
    241   };
    242 
    243 #define FT_DEFINE_SERVICEDESCREC6( class_,                                  \
    244                                    serv_id_1, serv_data_1,                  \
    245                                    serv_id_2, serv_data_2,                  \
    246                                    serv_id_3, serv_data_3,                  \
    247                                    serv_id_4, serv_data_4,                  \
    248                                    serv_id_5, serv_data_5,                  \
    249                                    serv_id_6, serv_data_6 )                 \
    250   static const FT_ServiceDescRec  class_[] =                                \
    251   {                                                                         \
    252     { serv_id_1, serv_data_1 },                                             \
    253     { serv_id_2, serv_data_2 },                                             \
    254     { serv_id_3, serv_data_3 },                                             \
    255     { serv_id_4, serv_data_4 },                                             \
    256     { serv_id_5, serv_data_5 },                                             \
    257     { serv_id_6, serv_data_6 },                                             \
    258     { NULL, NULL }                                                          \
    259   };
    260 
    261 #define FT_DEFINE_SERVICEDESCREC7( class_,                                  \
    262                                    serv_id_1, serv_data_1,                  \
    263                                    serv_id_2, serv_data_2,                  \
    264                                    serv_id_3, serv_data_3,                  \
    265                                    serv_id_4, serv_data_4,                  \
    266                                    serv_id_5, serv_data_5,                  \
    267                                    serv_id_6, serv_data_6,                  \
    268                                    serv_id_7, serv_data_7 )                 \
    269   static const FT_ServiceDescRec  class_[] =                                \
    270   {                                                                         \
    271     { serv_id_1, serv_data_1 },                                             \
    272     { serv_id_2, serv_data_2 },                                             \
    273     { serv_id_3, serv_data_3 },                                             \
    274     { serv_id_4, serv_data_4 },                                             \
    275     { serv_id_5, serv_data_5 },                                             \
    276     { serv_id_6, serv_data_6 },                                             \
    277     { serv_id_7, serv_data_7 },                                             \
    278     { NULL, NULL }                                                          \
    279   };
    280 
    281 #define FT_DEFINE_SERVICEDESCREC8( class_,                                  \
    282                                    serv_id_1, serv_data_1,                  \
    283                                    serv_id_2, serv_data_2,                  \
    284                                    serv_id_3, serv_data_3,                  \
    285                                    serv_id_4, serv_data_4,                  \
    286                                    serv_id_5, serv_data_5,                  \
    287                                    serv_id_6, serv_data_6,                  \
    288                                    serv_id_7, serv_data_7,                  \
    289                                    serv_id_8, serv_data_8 )                 \
    290   static const FT_ServiceDescRec  class_[] =                                \
    291   {                                                                         \
    292     { serv_id_1, serv_data_1 },                                             \
    293     { serv_id_2, serv_data_2 },                                             \
    294     { serv_id_3, serv_data_3 },                                             \
    295     { serv_id_4, serv_data_4 },                                             \
    296     { serv_id_5, serv_data_5 },                                             \
    297     { serv_id_6, serv_data_6 },                                             \
    298     { serv_id_7, serv_data_7 },                                             \
    299     { serv_id_8, serv_data_8 },                                             \
    300     { NULL, NULL }                                                          \
    301   };
    302 
    303 #define FT_DEFINE_SERVICEDESCREC9( class_,                                  \
    304                                    serv_id_1, serv_data_1,                  \
    305                                    serv_id_2, serv_data_2,                  \
    306                                    serv_id_3, serv_data_3,                  \
    307                                    serv_id_4, serv_data_4,                  \
    308                                    serv_id_5, serv_data_5,                  \
    309                                    serv_id_6, serv_data_6,                  \
    310                                    serv_id_7, serv_data_7,                  \
    311                                    serv_id_8, serv_data_8,                  \
    312                                    serv_id_9, serv_data_9 )                 \
    313   static const FT_ServiceDescRec  class_[] =                                \
    314   {                                                                         \
    315     { serv_id_1, serv_data_1 },                                             \
    316     { serv_id_2, serv_data_2 },                                             \
    317     { serv_id_3, serv_data_3 },                                             \
    318     { serv_id_4, serv_data_4 },                                             \
    319     { serv_id_5, serv_data_5 },                                             \
    320     { serv_id_6, serv_data_6 },                                             \
    321     { serv_id_7, serv_data_7 },                                             \
    322     { serv_id_8, serv_data_8 },                                             \
    323     { serv_id_9, serv_data_9 },                                             \
    324     { NULL, NULL }                                                          \
    325   };
    326 
    327 #define FT_DEFINE_SERVICEDESCREC10( class_,                                 \
    328                                     serv_id_1, serv_data_1,                 \
    329                                     serv_id_2, serv_data_2,                 \
    330                                     serv_id_3, serv_data_3,                 \
    331                                     serv_id_4, serv_data_4,                 \
    332                                     serv_id_5, serv_data_5,                 \
    333                                     serv_id_6, serv_data_6,                 \
    334                                     serv_id_7, serv_data_7,                 \
    335                                     serv_id_8, serv_data_8,                 \
    336                                     serv_id_9, serv_data_9,                 \
    337                                     serv_id_10, serv_data_10 )              \
    338   static const FT_ServiceDescRec  class_[] =                                \
    339   {                                                                         \
    340     { serv_id_1, serv_data_1 },                                             \
    341     { serv_id_2, serv_data_2 },                                             \
    342     { serv_id_3, serv_data_3 },                                             \
    343     { serv_id_4, serv_data_4 },                                             \
    344     { serv_id_5, serv_data_5 },                                             \
    345     { serv_id_6, serv_data_6 },                                             \
    346     { serv_id_7, serv_data_7 },                                             \
    347     { serv_id_8, serv_data_8 },                                             \
    348     { serv_id_9, serv_data_9 },                                             \
    349     { serv_id_10, serv_data_10 },                                           \
    350     { NULL, NULL }                                                          \
    351   };
    352 
    353 
    354   /*
    355    * Parse a list of FT_ServiceDescRec descriptors and look for a specific
    356    * service by ID.  Note that the last element in the array must be { NULL,
    357    * NULL }, and that the function should return NULL if the service isn't
    358    * available.
    359    *
    360    * This function can be used by modules to implement their `get_service'
    361    * method.
    362    */
    363   FT_BASE( FT_Pointer )
    364   ft_service_list_lookup( FT_ServiceDesc  service_descriptors,
    365                           const char*     service_id );
    366 
    367 
    368   /*************************************************************************/
    369   /*************************************************************************/
    370   /*****                                                               *****/
    371   /*****             S E R V I C E S   C A C H E                       *****/
    372   /*****                                                               *****/
    373   /*************************************************************************/
    374   /*************************************************************************/
    375 
    376   /*
    377    * This structure is used to store a cache for several frequently used
    378    * services.  It is the type of `face->internal->services'.  You should
    379    * only use FT_FACE_LOOKUP_SERVICE to access it.
    380    *
    381    * All fields should have the type FT_Pointer to relax compilation
    382    * dependencies.  We assume the developer isn't completely stupid.
    383    *
    384    * Each field must be named `service_XXXX' where `XXX' corresponds to the
    385    * correct FT_SERVICE_ID_XXXX macro.  See the definition of
    386    * FT_FACE_LOOKUP_SERVICE below how this is implemented.
    387    *
    388    */
    389   typedef struct  FT_ServiceCacheRec_
    390   {
    391     FT_Pointer  service_POSTSCRIPT_FONT_NAME;
    392     FT_Pointer  service_MULTI_MASTERS;
    393     FT_Pointer  service_METRICS_VARIATIONS;
    394     FT_Pointer  service_GLYPH_DICT;
    395     FT_Pointer  service_PFR_METRICS;
    396     FT_Pointer  service_WINFNT;
    397 
    398   } FT_ServiceCacheRec, *FT_ServiceCache;
    399 
    400 
    401   /*
    402    * A magic number used within the services cache.
    403    */
    404 
    405   /* ensure that value `1' has the same width as a pointer */
    406 #define FT_SERVICE_UNAVAILABLE  ((FT_Pointer)~(FT_PtrDist)1)
    407 
    408 
    409   /**************************************************************************
    410    *
    411    * @macro:
    412    *   FT_FACE_LOOKUP_SERVICE
    413    *
    414    * @description:
    415    *   This macro is used to look up a service from a face's driver module
    416    *   using its cache.
    417    *
    418    * @input:
    419    *   face ::
    420    *     The source face handle containing the cache.
    421    *
    422    *   field ::
    423    *     The field name in the cache.
    424    *
    425    *   id ::
    426    *     The service ID.
    427    *
    428    * @output:
    429    *   ptr ::
    430    *     A variable receiving the service data.  `NULL` if not available.
    431    */
    432 #ifdef __cplusplus
    433 
    434 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
    435   FT_BEGIN_STMNT                                               \
    436     FT_Pointer   svc;                                          \
    437     FT_Pointer*  Pptr = (FT_Pointer*)&(ptr);                   \
    438                                                                \
    439                                                                \
    440     svc = FT_FACE( face )->internal->services. service_ ## id; \
    441     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
    442       svc = NULL;                                              \
    443     else if ( svc == NULL )                                    \
    444     {                                                          \
    445       FT_FACE_FIND_SERVICE( face, svc, id );                   \
    446                                                                \
    447       FT_FACE( face )->internal->services. service_ ## id =    \
    448         (FT_Pointer)( svc != NULL ? svc                        \
    449                                   : FT_SERVICE_UNAVAILABLE );  \
    450     }                                                          \
    451     *Pptr = svc;                                               \
    452   FT_END_STMNT
    453 
    454 #else /* !C++ */
    455 
    456 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
    457   FT_BEGIN_STMNT                                               \
    458     FT_Pointer  svc;                                           \
    459                                                                \
    460                                                                \
    461     svc = FT_FACE( face )->internal->services. service_ ## id; \
    462     if ( svc == FT_SERVICE_UNAVAILABLE )                       \
    463       svc = NULL;                                              \
    464     else if ( svc == NULL )                                    \
    465     {                                                          \
    466       FT_FACE_FIND_SERVICE( face, svc, id );                   \
    467                                                                \
    468       FT_FACE( face )->internal->services. service_ ## id =    \
    469         (FT_Pointer)( svc != NULL ? svc                        \
    470                                   : FT_SERVICE_UNAVAILABLE );  \
    471     }                                                          \
    472     ptr = svc;                                                 \
    473   FT_END_STMNT
    474 
    475 #endif /* !C++ */
    476 
    477   /*
    478    * A macro used to define new service structure types.
    479    */
    480 
    481 #define FT_DEFINE_SERVICE( name )            \
    482   typedef struct FT_Service_ ## name ## Rec_ \
    483     FT_Service_ ## name ## Rec ;             \
    484   typedef struct FT_Service_ ## name ## Rec_ \
    485     const * FT_Service_ ## name ;            \
    486   struct FT_Service_ ## name ## Rec_
    487 
    488   /* */
    489 
    490 FT_END_HEADER
    491 
    492 #endif /* FTSERV_H_ */
    493 
    494 
    495 /* END */
    496