1 /****************************************************************************
5 * The FreeType services (specification only).
7 * Copyright (C) 2003-2023 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
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.
18 /**************************************************************************
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.
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).
34 #include "compiler-macros.h"
38 /**************************************************************************
41 * FT_FACE_FIND_SERVICE
44 * This macro is used to look up a service from a face's driver module.
48 * The source face handle.
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
58 * A variable that receives the service pointer. Will be `NULL` if not
63 #define FT_FACE_FIND_SERVICE( face, ptr, id ) \
65 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
66 FT_Pointer _tmp_ = NULL; \
67 FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \
70 if ( module->clazz->get_interface ) \
71 _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
77 #define FT_FACE_FIND_SERVICE( face, ptr, id ) \
79 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
80 FT_Pointer _tmp_ = NULL; \
82 if ( module->clazz->get_interface ) \
83 _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
90 /**************************************************************************
93 * FT_FACE_FIND_GLOBAL_SERVICE
96 * This macro is used to look up a service from all modules.
100 * The source face handle.
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
110 * A variable that receives the service pointer. Will be `NULL` if not
115 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \
117 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
119 FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \
122 _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
128 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \
130 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
134 _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
141 /*************************************************************************/
142 /*************************************************************************/
144 /***** S E R V I C E D E S C R I P T O R S *****/
146 /*************************************************************************/
147 /*************************************************************************/
150 * The following structure is used to _describe_ a given service to the
151 * library. This is useful to build simple static service lists.
153 typedef struct FT_ServiceDescRec_
155 const char* serv_id; /* service name */
156 const void* serv_data; /* service pointer/data */
160 typedef const FT_ServiceDescRec* FT_ServiceDesc;
163 /**************************************************************************
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
178 * Used to initialize an array of FT_ServiceDescRec structures.
180 * The array will be allocated in the global scope (or the scope where
181 * the macro is used).
183 #define FT_DEFINE_SERVICEDESCREC1( class_, \
184 serv_id_1, serv_data_1 ) \
185 static const FT_ServiceDescRec class_[] = \
187 { serv_id_1, serv_data_1 }, \
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_[] = \
196 { serv_id_1, serv_data_1 }, \
197 { serv_id_2, serv_data_2 }, \
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_[] = \
207 { serv_id_1, serv_data_1 }, \
208 { serv_id_2, serv_data_2 }, \
209 { serv_id_3, serv_data_3 }, \
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_[] = \
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 }, \
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_[] = \
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 }, \
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_[] = \
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 }, \
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_[] = \
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 }, \
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_[] = \
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 }, \
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_[] = \
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 }, \
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_[] = \
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 }, \
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
360 * This function can be used by modules to implement their `get_service'
363 FT_BASE( FT_Pointer )
364 ft_service_list_lookup( FT_ServiceDesc service_descriptors,
365 const char* service_id );
368 /*************************************************************************/
369 /*************************************************************************/
371 /***** S E R V I C E S C A C H E *****/
373 /*************************************************************************/
374 /*************************************************************************/
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.
381 * All fields should have the type FT_Pointer to relax compilation
382 * dependencies. We assume the developer isn't completely stupid.
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.
389 typedef struct FT_ServiceCacheRec_
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;
398 } FT_ServiceCacheRec, *FT_ServiceCache;
402 * A magic number used within the services cache.
405 /* ensure that value `1' has the same width as a pointer */
406 #define FT_SERVICE_UNAVAILABLE ((FT_Pointer)~(FT_PtrDist)1)
409 /**************************************************************************
412 * FT_FACE_LOOKUP_SERVICE
415 * This macro is used to look up a service from a face's driver module
420 * The source face handle containing the cache.
423 * The field name in the cache.
430 * A variable receiving the service data. `NULL` if not available.
434 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \
437 FT_Pointer* Pptr = (FT_Pointer*)&(ptr); \
440 svc = FT_FACE( face )->internal->services. service_ ## id; \
441 if ( svc == FT_SERVICE_UNAVAILABLE ) \
443 else if ( svc == NULL ) \
445 FT_FACE_FIND_SERVICE( face, svc, id ); \
447 FT_FACE( face )->internal->services. service_ ## id = \
448 (FT_Pointer)( svc != NULL ? svc \
449 : FT_SERVICE_UNAVAILABLE ); \
456 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \
461 svc = FT_FACE( face )->internal->services. service_ ## id; \
462 if ( svc == FT_SERVICE_UNAVAILABLE ) \
464 else if ( svc == NULL ) \
466 FT_FACE_FIND_SERVICE( face, svc, id ); \
468 FT_FACE( face )->internal->services. service_ ## id = \
469 (FT_Pointer)( svc != NULL ? svc \
470 : FT_SERVICE_UNAVAILABLE ); \
478 * A macro used to define new service structure types.
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_
492 #endif /* FTSERV_H_ */