• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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