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