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