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 */ 522