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