1 /***************************************************************************/ 2 /* */ 3 /* ftserv.h */ 4 /* */ 5 /* The FreeType services (specification only). */ 6 /* */ 7 /* Copyright 2003-2018 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 */ 25 /* in C it is possible that function pointers might be implemented */ 26 /* differently 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 * @macro: 39 * FT_FACE_FIND_SERVICE 40 * 41 * @description: 42 * This macro is used to look up a service from a face's driver module. 43 * 44 * @input: 45 * face :: 46 * The source face handle. 47 * 48 * id :: 49 * A string describing the service as defined in the service's 50 * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to 51 * `multi-masters'). It is automatically prefixed with 52 * `FT_SERVICE_ID_'. 53 * 54 * @output: 55 * ptr :: 56 * A variable that receives the service pointer. Will be NULL 57 * if not found. 58 */ 59 #ifdef __cplusplus 60 61 #define FT_FACE_FIND_SERVICE( face, ptr, id ) \ 62 FT_BEGIN_STMNT \ 63 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \ 64 FT_Pointer _tmp_ = NULL; \ 65 FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \ 66 \ 67 \ 68 if ( module->clazz->get_interface ) \ 69 _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \ 70 *_pptr_ = _tmp_; \ 71 FT_END_STMNT 72 73 #else /* !C++ */ 74 75 #define FT_FACE_FIND_SERVICE( face, ptr, id ) \ 76 FT_BEGIN_STMNT \ 77 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \ 78 FT_Pointer _tmp_ = NULL; \ 79 \ 80 if ( module->clazz->get_interface ) \ 81 _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \ 82 ptr = _tmp_; \ 83 FT_END_STMNT 84 85 #endif /* !C++ */ 86 87 88 /* 89 * @macro: 90 * FT_FACE_FIND_GLOBAL_SERVICE 91 * 92 * @description: 93 * This macro is used to look up a service from all modules. 94 * 95 * @input: 96 * face :: 97 * The source face handle. 98 * 99 * id :: 100 * A string describing the service as defined in the service's 101 * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to 102 * `multi-masters'). It is automatically prefixed with 103 * `FT_SERVICE_ID_'. 104 * 105 * @output: 106 * ptr :: 107 * A variable that receives the service pointer. Will be NULL 108 * if not found. 109 */ 110 #ifdef __cplusplus 111 112 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \ 113 FT_BEGIN_STMNT \ 114 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \ 115 FT_Pointer _tmp_; \ 116 FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \ 117 \ 118 \ 119 _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \ 120 *_pptr_ = _tmp_; \ 121 FT_END_STMNT 122 123 #else /* !C++ */ 124 125 #define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \ 126 FT_BEGIN_STMNT \ 127 FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \ 128 FT_Pointer _tmp_; \ 129 \ 130 \ 131 _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \ 132 ptr = _tmp_; \ 133 FT_END_STMNT 134 135 #endif /* !C++ */ 136 137 138 /*************************************************************************/ 139 /*************************************************************************/ 140 /***** *****/ 141 /***** S E R V I C E D E S C R I P T O R S *****/ 142 /***** *****/ 143 /*************************************************************************/ 144 /*************************************************************************/ 145 146 /* 147 * The following structure is used to _describe_ a given service 148 * to the library. This is useful to build simple static service lists. 149 */ 150 typedef struct FT_ServiceDescRec_ 151 { 152 const char* serv_id; /* service name */ 153 const void* serv_data; /* service pointer/data */ 154 155 } FT_ServiceDescRec; 156 157 typedef const FT_ServiceDescRec* FT_ServiceDesc; 158 159 160 /*************************************************************************/ 161 /* */ 162 /* <Macro> */ 163 /* FT_DEFINE_SERVICEDESCREC1 */ 164 /* FT_DEFINE_SERVICEDESCREC2 */ 165 /* FT_DEFINE_SERVICEDESCREC3 */ 166 /* FT_DEFINE_SERVICEDESCREC4 */ 167 /* FT_DEFINE_SERVICEDESCREC5 */ 168 /* FT_DEFINE_SERVICEDESCREC6 */ 169 /* FT_DEFINE_SERVICEDESCREC7 */ 170 /* FT_DEFINE_SERVICEDESCREC8 */ 171 /* */ 172 /* <Description> */ 173 /* Used to initialize an array of FT_ServiceDescRec structures. */ 174 /* */ 175 /* When FT_CONFIG_OPTION_PIC is defined a `create' function needs to */ 176 /* be called with a pointer to return an allocated array. As soon as */ 177 /* it is no longer needed, a `destroy' function needs to be called to */ 178 /* release that allocation. */ 179 /* */ 180 /* These functions should be manually called from the `pic_init' and */ 181 /* `pic_free' functions of your module (see FT_DEFINE_MODULE). */ 182 /* */ 183 /* When FT_CONFIG_OPTION_PIC is not defined the array will be */ 184 /* allocated in the global scope (or the scope where the macro is */ 185 /* used). */ 186 /* */ 187 #ifndef FT_CONFIG_OPTION_PIC 188 189 #define FT_DEFINE_SERVICEDESCREC1( class_, \ 190 serv_id_1, serv_data_1 ) \ 191 static const FT_ServiceDescRec class_[] = \ 192 { \ 193 { serv_id_1, serv_data_1 }, \ 194 { NULL, NULL } \ 195 }; 196 197 #define FT_DEFINE_SERVICEDESCREC2( class_, \ 198 serv_id_1, serv_data_1, \ 199 serv_id_2, serv_data_2 ) \ 200 static const FT_ServiceDescRec class_[] = \ 201 { \ 202 { serv_id_1, serv_data_1 }, \ 203 { serv_id_2, serv_data_2 }, \ 204 { NULL, NULL } \ 205 }; 206 207 #define FT_DEFINE_SERVICEDESCREC3( class_, \ 208 serv_id_1, serv_data_1, \ 209 serv_id_2, serv_data_2, \ 210 serv_id_3, serv_data_3 ) \ 211 static const FT_ServiceDescRec class_[] = \ 212 { \ 213 { serv_id_1, serv_data_1 }, \ 214 { serv_id_2, serv_data_2 }, \ 215 { serv_id_3, serv_data_3 }, \ 216 { NULL, NULL } \ 217 }; 218 219 #define FT_DEFINE_SERVICEDESCREC4( 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 ) \ 224 static const FT_ServiceDescRec class_[] = \ 225 { \ 226 { serv_id_1, serv_data_1 }, \ 227 { serv_id_2, serv_data_2 }, \ 228 { serv_id_3, serv_data_3 }, \ 229 { serv_id_4, serv_data_4 }, \ 230 { NULL, NULL } \ 231 }; 232 233 #define FT_DEFINE_SERVICEDESCREC5( class_, \ 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 static const FT_ServiceDescRec class_[] = \ 240 { \ 241 { serv_id_1, serv_data_1 }, \ 242 { serv_id_2, serv_data_2 }, \ 243 { serv_id_3, serv_data_3 }, \ 244 { serv_id_4, serv_data_4 }, \ 245 { serv_id_5, serv_data_5 }, \ 246 { NULL, NULL } \ 247 }; 248 249 #define FT_DEFINE_SERVICEDESCREC6( class_, \ 250 serv_id_1, serv_data_1, \ 251 serv_id_2, serv_data_2, \ 252 serv_id_3, serv_data_3, \ 253 serv_id_4, serv_data_4, \ 254 serv_id_5, serv_data_5, \ 255 serv_id_6, serv_data_6 ) \ 256 static const FT_ServiceDescRec class_[] = \ 257 { \ 258 { serv_id_1, serv_data_1 }, \ 259 { serv_id_2, serv_data_2 }, \ 260 { serv_id_3, serv_data_3 }, \ 261 { serv_id_4, serv_data_4 }, \ 262 { serv_id_5, serv_data_5 }, \ 263 { serv_id_6, serv_data_6 }, \ 264 { NULL, NULL } \ 265 }; 266 267 #define FT_DEFINE_SERVICEDESCREC7( class_, \ 268 serv_id_1, serv_data_1, \ 269 serv_id_2, serv_data_2, \ 270 serv_id_3, serv_data_3, \ 271 serv_id_4, serv_data_4, \ 272 serv_id_5, serv_data_5, \ 273 serv_id_6, serv_data_6, \ 274 serv_id_7, serv_data_7 ) \ 275 static const FT_ServiceDescRec class_[] = \ 276 { \ 277 { serv_id_1, serv_data_1 }, \ 278 { serv_id_2, serv_data_2 }, \ 279 { serv_id_3, serv_data_3 }, \ 280 { serv_id_4, serv_data_4 }, \ 281 { serv_id_5, serv_data_5 }, \ 282 { serv_id_6, serv_data_6 }, \ 283 { serv_id_7, serv_data_7 }, \ 284 { NULL, NULL } \ 285 }; 286 287 #define FT_DEFINE_SERVICEDESCREC8( class_, \ 288 serv_id_1, serv_data_1, \ 289 serv_id_2, serv_data_2, \ 290 serv_id_3, serv_data_3, \ 291 serv_id_4, serv_data_4, \ 292 serv_id_5, serv_data_5, \ 293 serv_id_6, serv_data_6, \ 294 serv_id_7, serv_data_7, \ 295 serv_id_8, serv_data_8 ) \ 296 static const FT_ServiceDescRec class_[] = \ 297 { \ 298 { serv_id_1, serv_data_1 }, \ 299 { serv_id_2, serv_data_2 }, \ 300 { serv_id_3, serv_data_3 }, \ 301 { serv_id_4, serv_data_4 }, \ 302 { serv_id_5, serv_data_5 }, \ 303 { serv_id_6, serv_data_6 }, \ 304 { serv_id_7, serv_data_7 }, \ 305 { serv_id_8, serv_data_8 }, \ 306 { NULL, NULL } \ 307 }; 308 309 #define FT_DEFINE_SERVICEDESCREC9( class_, \ 310 serv_id_1, serv_data_1, \ 311 serv_id_2, serv_data_2, \ 312 serv_id_3, serv_data_3, \ 313 serv_id_4, serv_data_4, \ 314 serv_id_5, serv_data_5, \ 315 serv_id_6, serv_data_6, \ 316 serv_id_7, serv_data_7, \ 317 serv_id_8, serv_data_8, \ 318 serv_id_9, serv_data_9 ) \ 319 static const FT_ServiceDescRec class_[] = \ 320 { \ 321 { serv_id_1, serv_data_1 }, \ 322 { serv_id_2, serv_data_2 }, \ 323 { serv_id_3, serv_data_3 }, \ 324 { serv_id_4, serv_data_4 }, \ 325 { serv_id_5, serv_data_5 }, \ 326 { serv_id_6, serv_data_6 }, \ 327 { serv_id_7, serv_data_7 }, \ 328 { serv_id_8, serv_data_8 }, \ 329 { serv_id_9, serv_data_9 }, \ 330 { NULL, NULL } \ 331 }; 332 333 #define FT_DEFINE_SERVICEDESCREC10( class_, \ 334 serv_id_1, serv_data_1, \ 335 serv_id_2, serv_data_2, \ 336 serv_id_3, serv_data_3, \ 337 serv_id_4, serv_data_4, \ 338 serv_id_5, serv_data_5, \ 339 serv_id_6, serv_data_6, \ 340 serv_id_7, serv_data_7, \ 341 serv_id_8, serv_data_8, \ 342 serv_id_9, serv_data_9, \ 343 serv_id_10, serv_data_10 ) \ 344 static const FT_ServiceDescRec class_[] = \ 345 { \ 346 { serv_id_1, serv_data_1 }, \ 347 { serv_id_2, serv_data_2 }, \ 348 { serv_id_3, serv_data_3 }, \ 349 { serv_id_4, serv_data_4 }, \ 350 { serv_id_5, serv_data_5 }, \ 351 { serv_id_6, serv_data_6 }, \ 352 { serv_id_7, serv_data_7 }, \ 353 { serv_id_8, serv_data_8 }, \ 354 { serv_id_9, serv_data_9 }, \ 355 { serv_id_10, serv_data_10 }, \ 356 { NULL, NULL } \ 357 }; 358 359 #else /* FT_CONFIG_OPTION_PIC */ 360 361 #define FT_DEFINE_SERVICEDESCREC1( class_, \ 362 serv_id_1, serv_data_1 ) \ 363 void \ 364 FT_Destroy_Class_ ## class_( FT_Library library, \ 365 FT_ServiceDescRec* clazz ) \ 366 { \ 367 FT_Memory memory = library->memory; \ 368 \ 369 \ 370 if ( clazz ) \ 371 FT_FREE( clazz ); \ 372 } \ 373 \ 374 FT_Error \ 375 FT_Create_Class_ ## class_( FT_Library library, \ 376 FT_ServiceDescRec** output_class ) \ 377 { \ 378 FT_ServiceDescRec* clazz = NULL; \ 379 FT_Error error; \ 380 FT_Memory memory = library->memory; \ 381 \ 382 \ 383 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 2 ) ) \ 384 return error; \ 385 \ 386 clazz[0].serv_id = serv_id_1; \ 387 clazz[0].serv_data = serv_data_1; \ 388 clazz[1].serv_id = NULL; \ 389 clazz[1].serv_data = NULL; \ 390 \ 391 *output_class = clazz; \ 392 \ 393 return FT_Err_Ok; \ 394 } 395 396 #define FT_DEFINE_SERVICEDESCREC2( class_, \ 397 serv_id_1, serv_data_1, \ 398 serv_id_2, serv_data_2 ) \ 399 void \ 400 FT_Destroy_Class_ ## class_( FT_Library library, \ 401 FT_ServiceDescRec* clazz ) \ 402 { \ 403 FT_Memory memory = library->memory; \ 404 \ 405 \ 406 if ( clazz ) \ 407 FT_FREE( clazz ); \ 408 } \ 409 \ 410 FT_Error \ 411 FT_Create_Class_ ## class_( FT_Library library, \ 412 FT_ServiceDescRec** output_class ) \ 413 { \ 414 FT_ServiceDescRec* clazz = NULL; \ 415 FT_Error error; \ 416 FT_Memory memory = library->memory; \ 417 \ 418 \ 419 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 3 ) ) \ 420 return error; \ 421 \ 422 clazz[0].serv_id = serv_id_1; \ 423 clazz[0].serv_data = serv_data_1; \ 424 clazz[1].serv_id = serv_id_2; \ 425 clazz[1].serv_data = serv_data_2; \ 426 clazz[2].serv_id = NULL; \ 427 clazz[2].serv_data = NULL; \ 428 \ 429 *output_class = clazz; \ 430 \ 431 return FT_Err_Ok; \ 432 } 433 434 #define FT_DEFINE_SERVICEDESCREC3( class_, \ 435 serv_id_1, serv_data_1, \ 436 serv_id_2, serv_data_2, \ 437 serv_id_3, serv_data_3 ) \ 438 void \ 439 FT_Destroy_Class_ ## class_( FT_Library library, \ 440 FT_ServiceDescRec* clazz ) \ 441 { \ 442 FT_Memory memory = library->memory; \ 443 \ 444 \ 445 if ( clazz ) \ 446 FT_FREE( clazz ); \ 447 } \ 448 \ 449 FT_Error \ 450 FT_Create_Class_ ## class_( FT_Library library, \ 451 FT_ServiceDescRec** output_class ) \ 452 { \ 453 FT_ServiceDescRec* clazz = NULL; \ 454 FT_Error error; \ 455 FT_Memory memory = library->memory; \ 456 \ 457 \ 458 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 4 ) ) \ 459 return error; \ 460 \ 461 clazz[0].serv_id = serv_id_1; \ 462 clazz[0].serv_data = serv_data_1; \ 463 clazz[1].serv_id = serv_id_2; \ 464 clazz[1].serv_data = serv_data_2; \ 465 clazz[2].serv_id = serv_id_3; \ 466 clazz[2].serv_data = serv_data_3; \ 467 clazz[3].serv_id = NULL; \ 468 clazz[3].serv_data = NULL; \ 469 \ 470 *output_class = clazz; \ 471 \ 472 return FT_Err_Ok; \ 473 } 474 475 #define FT_DEFINE_SERVICEDESCREC4( class_, \ 476 serv_id_1, serv_data_1, \ 477 serv_id_2, serv_data_2, \ 478 serv_id_3, serv_data_3, \ 479 serv_id_4, serv_data_4 ) \ 480 void \ 481 FT_Destroy_Class_ ## class_( FT_Library library, \ 482 FT_ServiceDescRec* clazz ) \ 483 { \ 484 FT_Memory memory = library->memory; \ 485 \ 486 \ 487 if ( clazz ) \ 488 FT_FREE( clazz ); \ 489 } \ 490 \ 491 FT_Error \ 492 FT_Create_Class_ ## class_( FT_Library library, \ 493 FT_ServiceDescRec** output_class ) \ 494 { \ 495 FT_ServiceDescRec* clazz = NULL; \ 496 FT_Error error; \ 497 FT_Memory memory = library->memory; \ 498 \ 499 \ 500 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 5 ) ) \ 501 return error; \ 502 \ 503 clazz[0].serv_id = serv_id_1; \ 504 clazz[0].serv_data = serv_data_1; \ 505 clazz[1].serv_id = serv_id_2; \ 506 clazz[1].serv_data = serv_data_2; \ 507 clazz[2].serv_id = serv_id_3; \ 508 clazz[2].serv_data = serv_data_3; \ 509 clazz[3].serv_id = serv_id_4; \ 510 clazz[3].serv_data = serv_data_4; \ 511 clazz[4].serv_id = NULL; \ 512 clazz[4].serv_data = NULL; \ 513 \ 514 *output_class = clazz; \ 515 \ 516 return FT_Err_Ok; \ 517 } 518 519 #define FT_DEFINE_SERVICEDESCREC5( class_, \ 520 serv_id_1, serv_data_1, \ 521 serv_id_2, serv_data_2, \ 522 serv_id_3, serv_data_3, \ 523 serv_id_4, serv_data_4, \ 524 serv_id_5, serv_data_5 ) \ 525 void \ 526 FT_Destroy_Class_ ## class_( FT_Library library, \ 527 FT_ServiceDescRec* clazz ) \ 528 { \ 529 FT_Memory memory = library->memory; \ 530 \ 531 \ 532 if ( clazz ) \ 533 FT_FREE( clazz ); \ 534 } \ 535 \ 536 FT_Error \ 537 FT_Create_Class_ ## class_( FT_Library library, \ 538 FT_ServiceDescRec** output_class ) \ 539 { \ 540 FT_ServiceDescRec* clazz = NULL; \ 541 FT_Error error; \ 542 FT_Memory memory = library->memory; \ 543 \ 544 \ 545 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 6 ) ) \ 546 return error; \ 547 \ 548 clazz[0].serv_id = serv_id_1; \ 549 clazz[0].serv_data = serv_data_1; \ 550 clazz[1].serv_id = serv_id_2; \ 551 clazz[1].serv_data = serv_data_2; \ 552 clazz[2].serv_id = serv_id_3; \ 553 clazz[2].serv_data = serv_data_3; \ 554 clazz[3].serv_id = serv_id_4; \ 555 clazz[3].serv_data = serv_data_4; \ 556 clazz[4].serv_id = serv_id_5; \ 557 clazz[4].serv_data = serv_data_5; \ 558 clazz[5].serv_id = NULL; \ 559 clazz[5].serv_data = NULL; \ 560 \ 561 *output_class = clazz; \ 562 \ 563 return FT_Err_Ok; \ 564 } 565 566 #define FT_DEFINE_SERVICEDESCREC6( class_, \ 567 serv_id_1, serv_data_1, \ 568 serv_id_2, serv_data_2, \ 569 serv_id_3, serv_data_3, \ 570 serv_id_4, serv_data_4, \ 571 serv_id_5, serv_data_5, \ 572 serv_id_6, serv_data_6 ) \ 573 void \ 574 FT_Destroy_Class_ ## class_( FT_Library library, \ 575 FT_ServiceDescRec* clazz ) \ 576 { \ 577 FT_Memory memory = library->memory; \ 578 \ 579 \ 580 if ( clazz ) \ 581 FT_FREE( clazz ); \ 582 } \ 583 \ 584 FT_Error \ 585 FT_Create_Class_ ## class_( FT_Library library, \ 586 FT_ServiceDescRec** output_class ) \ 587 { \ 588 FT_ServiceDescRec* clazz = NULL; \ 589 FT_Error error; \ 590 FT_Memory memory = library->memory; \ 591 \ 592 \ 593 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 7 ) ) \ 594 return error; \ 595 \ 596 clazz[0].serv_id = serv_id_1; \ 597 clazz[0].serv_data = serv_data_1; \ 598 clazz[1].serv_id = serv_id_2; \ 599 clazz[1].serv_data = serv_data_2; \ 600 clazz[2].serv_id = serv_id_3; \ 601 clazz[2].serv_data = serv_data_3; \ 602 clazz[3].serv_id = serv_id_4; \ 603 clazz[3].serv_data = serv_data_4; \ 604 clazz[4].serv_id = serv_id_5; \ 605 clazz[4].serv_data = serv_data_5; \ 606 clazz[5].serv_id = serv_id_6; \ 607 clazz[5].serv_data = serv_data_6; \ 608 clazz[6].serv_id = NULL; \ 609 clazz[6].serv_data = NULL; \ 610 \ 611 *output_class = clazz; \ 612 \ 613 return FT_Err_Ok; \ 614 } 615 616 #define FT_DEFINE_SERVICEDESCREC7( class_, \ 617 serv_id_1, serv_data_1, \ 618 serv_id_2, serv_data_2, \ 619 serv_id_3, serv_data_3, \ 620 serv_id_4, serv_data_4, \ 621 serv_id_5, serv_data_5, \ 622 serv_id_6, serv_data_6, \ 623 serv_id_7, serv_data_7 ) \ 624 void \ 625 FT_Destroy_Class_ ## class_( FT_Library library, \ 626 FT_ServiceDescRec* clazz ) \ 627 { \ 628 FT_Memory memory = library->memory; \ 629 \ 630 \ 631 if ( clazz ) \ 632 FT_FREE( clazz ); \ 633 } \ 634 \ 635 FT_Error \ 636 FT_Create_Class_ ## class_( FT_Library library, \ 637 FT_ServiceDescRec** output_class ) \ 638 { \ 639 FT_ServiceDescRec* clazz = NULL; \ 640 FT_Error error; \ 641 FT_Memory memory = library->memory; \ 642 \ 643 \ 644 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 8 ) ) \ 645 return error; \ 646 \ 647 clazz[0].serv_id = serv_id_1; \ 648 clazz[0].serv_data = serv_data_1; \ 649 clazz[1].serv_id = serv_id_2; \ 650 clazz[1].serv_data = serv_data_2; \ 651 clazz[2].serv_id = serv_id_3; \ 652 clazz[2].serv_data = serv_data_3; \ 653 clazz[3].serv_id = serv_id_4; \ 654 clazz[3].serv_data = serv_data_4; \ 655 clazz[4].serv_id = serv_id_5; \ 656 clazz[4].serv_data = serv_data_5; \ 657 clazz[5].serv_id = serv_id_6; \ 658 clazz[5].serv_data = serv_data_6; \ 659 clazz[6].serv_id = serv_id_7; \ 660 clazz[6].serv_data = serv_data_7; \ 661 clazz[7].serv_id = NULL; \ 662 clazz[7].serv_data = NULL; \ 663 \ 664 *output_class = clazz; \ 665 \ 666 return FT_Err_Ok; \ 667 } 668 669 #define FT_DEFINE_SERVICEDESCREC8( class_, \ 670 serv_id_1, serv_data_1, \ 671 serv_id_2, serv_data_2, \ 672 serv_id_3, serv_data_3, \ 673 serv_id_4, serv_data_4, \ 674 serv_id_5, serv_data_5, \ 675 serv_id_6, serv_data_6, \ 676 serv_id_7, serv_data_7, \ 677 serv_id_8, serv_data_8 ) \ 678 void \ 679 FT_Destroy_Class_ ## class_( FT_Library library, \ 680 FT_ServiceDescRec* clazz ) \ 681 { \ 682 FT_Memory memory = library->memory; \ 683 \ 684 \ 685 if ( clazz ) \ 686 FT_FREE( clazz ); \ 687 } \ 688 \ 689 FT_Error \ 690 FT_Create_Class_ ## class_( FT_Library library, \ 691 FT_ServiceDescRec** output_class ) \ 692 { \ 693 FT_ServiceDescRec* clazz = NULL; \ 694 FT_Error error; \ 695 FT_Memory memory = library->memory; \ 696 \ 697 \ 698 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 9 ) ) \ 699 return error; \ 700 \ 701 clazz[0].serv_id = serv_id_1; \ 702 clazz[0].serv_data = serv_data_1; \ 703 clazz[1].serv_id = serv_id_2; \ 704 clazz[1].serv_data = serv_data_2; \ 705 clazz[2].serv_id = serv_id_3; \ 706 clazz[2].serv_data = serv_data_3; \ 707 clazz[3].serv_id = serv_id_4; \ 708 clazz[3].serv_data = serv_data_4; \ 709 clazz[4].serv_id = serv_id_5; \ 710 clazz[4].serv_data = serv_data_5; \ 711 clazz[5].serv_id = serv_id_6; \ 712 clazz[5].serv_data = serv_data_6; \ 713 clazz[6].serv_id = serv_id_7; \ 714 clazz[6].serv_data = serv_data_7; \ 715 clazz[7].serv_id = serv_id_8; \ 716 clazz[7].serv_data = serv_data_8; \ 717 clazz[8].serv_id = NULL; \ 718 clazz[8].serv_data = NULL; \ 719 \ 720 *output_class = clazz; \ 721 \ 722 return FT_Err_Ok; \ 723 } 724 725 #define FT_DEFINE_SERVICEDESCREC9( class_, \ 726 serv_id_1, serv_data_1, \ 727 serv_id_2, serv_data_2, \ 728 serv_id_3, serv_data_3, \ 729 serv_id_4, serv_data_4, \ 730 serv_id_5, serv_data_5, \ 731 serv_id_6, serv_data_6, \ 732 serv_id_7, serv_data_7, \ 733 serv_id_8, serv_data_8, \ 734 serv_id_9, serv_data_9 ) \ 735 void \ 736 FT_Destroy_Class_ ## class_( FT_Library library, \ 737 FT_ServiceDescRec* clazz ) \ 738 { \ 739 FT_Memory memory = library->memory; \ 740 \ 741 \ 742 if ( clazz ) \ 743 FT_FREE( clazz ); \ 744 } \ 745 \ 746 FT_Error \ 747 FT_Create_Class_ ## class_( FT_Library library, \ 748 FT_ServiceDescRec** output_class ) \ 749 { \ 750 FT_ServiceDescRec* clazz = NULL; \ 751 FT_Error error; \ 752 FT_Memory memory = library->memory; \ 753 \ 754 \ 755 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 10 ) ) \ 756 return error; \ 757 \ 758 clazz[0].serv_id = serv_id_1; \ 759 clazz[0].serv_data = serv_data_1; \ 760 clazz[1].serv_id = serv_id_2; \ 761 clazz[1].serv_data = serv_data_2; \ 762 clazz[2].serv_id = serv_id_3; \ 763 clazz[2].serv_data = serv_data_3; \ 764 clazz[3].serv_id = serv_id_4; \ 765 clazz[3].serv_data = serv_data_4; \ 766 clazz[4].serv_id = serv_id_5; \ 767 clazz[4].serv_data = serv_data_5; \ 768 clazz[5].serv_id = serv_id_6; \ 769 clazz[5].serv_data = serv_data_6; \ 770 clazz[6].serv_id = serv_id_7; \ 771 clazz[6].serv_data = serv_data_7; \ 772 clazz[7].serv_id = serv_id_8; \ 773 clazz[7].serv_data = serv_data_8; \ 774 clazz[8].serv_id = serv_id_9; \ 775 clazz[8].serv_data = serv_data_9; \ 776 clazz[9].serv_id = NULL; \ 777 clazz[9].serv_data = NULL; \ 778 \ 779 *output_class = clazz; \ 780 \ 781 return FT_Err_Ok; \ 782 } 783 784 #define FT_DEFINE_SERVICEDESCREC10( class_, \ 785 serv_id_1, serv_data_1, \ 786 serv_id_2, serv_data_2, \ 787 serv_id_3, serv_data_3, \ 788 serv_id_4, serv_data_4, \ 789 serv_id_5, serv_data_5, \ 790 serv_id_6, serv_data_6, \ 791 serv_id_7, serv_data_7, \ 792 serv_id_8, serv_data_8, \ 793 serv_id_9, serv_data_9, \ 794 serv_id_10, serv_data_10 ) \ 795 void \ 796 FT_Destroy_Class_ ## class_( FT_Library library, \ 797 FT_ServiceDescRec* clazz ) \ 798 { \ 799 FT_Memory memory = library->memory; \ 800 \ 801 \ 802 if ( clazz ) \ 803 FT_FREE( clazz ); \ 804 } \ 805 \ 806 FT_Error \ 807 FT_Create_Class_ ## class_( FT_Library library, \ 808 FT_ServiceDescRec** output_class ) \ 809 { \ 810 FT_ServiceDescRec* clazz = NULL; \ 811 FT_Error error; \ 812 FT_Memory memory = library->memory; \ 813 \ 814 \ 815 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 11 ) ) \ 816 return error; \ 817 \ 818 clazz[ 0].serv_id = serv_id_1; \ 819 clazz[ 0].serv_data = serv_data_1; \ 820 clazz[ 1].serv_id = serv_id_2; \ 821 clazz[ 1].serv_data = serv_data_2; \ 822 clazz[ 2].serv_id = serv_id_3; \ 823 clazz[ 2].serv_data = serv_data_3; \ 824 clazz[ 3].serv_id = serv_id_4; \ 825 clazz[ 3].serv_data = serv_data_4; \ 826 clazz[ 4].serv_id = serv_id_5; \ 827 clazz[ 4].serv_data = serv_data_5; \ 828 clazz[ 5].serv_id = serv_id_6; \ 829 clazz[ 5].serv_data = serv_data_6; \ 830 clazz[ 6].serv_id = serv_id_7; \ 831 clazz[ 6].serv_data = serv_data_7; \ 832 clazz[ 7].serv_id = serv_id_8; \ 833 clazz[ 7].serv_data = serv_data_8; \ 834 clazz[ 8].serv_id = serv_id_9; \ 835 clazz[ 8].serv_data = serv_data_9; \ 836 clazz[ 9].serv_id = serv_id_10; \ 837 clazz[ 9].serv_data = serv_data_10; \ 838 clazz[10].serv_id = NULL; \ 839 clazz[10].serv_data = NULL; \ 840 \ 841 *output_class = clazz; \ 842 \ 843 return FT_Err_Ok; \ 844 } 845 846 #endif /* FT_CONFIG_OPTION_PIC */ 847 848 849 /* 850 * Parse a list of FT_ServiceDescRec descriptors and look for 851 * a specific service by ID. Note that the last element in the 852 * array must be { NULL, NULL }, and that the function should 853 * return NULL if the service isn't available. 854 * 855 * This function can be used by modules to implement their 856 * `get_service' method. 857 */ 858 FT_BASE( FT_Pointer ) 859 ft_service_list_lookup( FT_ServiceDesc service_descriptors, 860 const char* service_id ); 861 862 863 /*************************************************************************/ 864 /*************************************************************************/ 865 /***** *****/ 866 /***** S E R V I C E S C A C H E *****/ 867 /***** *****/ 868 /*************************************************************************/ 869 /*************************************************************************/ 870 871 /* 872 * This structure is used to store a cache for several frequently used 873 * services. It is the type of `face->internal->services'. You 874 * should only use FT_FACE_LOOKUP_SERVICE to access it. 875 * 876 * All fields should have the type FT_Pointer to relax compilation 877 * dependencies. We assume the developer isn't completely stupid. 878 * 879 * Each field must be named `service_XXXX' where `XXX' corresponds to 880 * the correct FT_SERVICE_ID_XXXX macro. See the definition of 881 * FT_FACE_LOOKUP_SERVICE below how this is implemented. 882 * 883 */ 884 typedef struct FT_ServiceCacheRec_ 885 { 886 FT_Pointer service_POSTSCRIPT_FONT_NAME; 887 FT_Pointer service_MULTI_MASTERS; 888 FT_Pointer service_METRICS_VARIATIONS; 889 FT_Pointer service_GLYPH_DICT; 890 FT_Pointer service_PFR_METRICS; 891 FT_Pointer service_WINFNT; 892 893 } FT_ServiceCacheRec, *FT_ServiceCache; 894 895 896 /* 897 * A magic number used within the services cache. 898 */ 899 900 /* ensure that value `1' has the same width as a pointer */ 901 #define FT_SERVICE_UNAVAILABLE ((FT_Pointer)~(FT_PtrDist)1) 902 903 904 /* 905 * @macro: 906 * FT_FACE_LOOKUP_SERVICE 907 * 908 * @description: 909 * This macro is used to look up a service from a face's driver module 910 * using its cache. 911 * 912 * @input: 913 * face:: 914 * The source face handle containing the cache. 915 * 916 * field :: 917 * The field name in the cache. 918 * 919 * id :: 920 * The service ID. 921 * 922 * @output: 923 * ptr :: 924 * A variable receiving the service data. NULL if not available. 925 */ 926 #ifdef __cplusplus 927 928 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \ 929 FT_BEGIN_STMNT \ 930 FT_Pointer svc; \ 931 FT_Pointer* Pptr = (FT_Pointer*)&(ptr); \ 932 \ 933 \ 934 svc = FT_FACE( face )->internal->services. service_ ## id; \ 935 if ( svc == FT_SERVICE_UNAVAILABLE ) \ 936 svc = NULL; \ 937 else if ( svc == NULL ) \ 938 { \ 939 FT_FACE_FIND_SERVICE( face, svc, id ); \ 940 \ 941 FT_FACE( face )->internal->services. service_ ## id = \ 942 (FT_Pointer)( svc != NULL ? svc \ 943 : FT_SERVICE_UNAVAILABLE ); \ 944 } \ 945 *Pptr = svc; \ 946 FT_END_STMNT 947 948 #else /* !C++ */ 949 950 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \ 951 FT_BEGIN_STMNT \ 952 FT_Pointer svc; \ 953 \ 954 \ 955 svc = FT_FACE( face )->internal->services. service_ ## id; \ 956 if ( svc == FT_SERVICE_UNAVAILABLE ) \ 957 svc = NULL; \ 958 else if ( svc == NULL ) \ 959 { \ 960 FT_FACE_FIND_SERVICE( face, svc, id ); \ 961 \ 962 FT_FACE( face )->internal->services. service_ ## id = \ 963 (FT_Pointer)( svc != NULL ? svc \ 964 : FT_SERVICE_UNAVAILABLE ); \ 965 } \ 966 ptr = svc; \ 967 FT_END_STMNT 968 969 #endif /* !C++ */ 970 971 /* 972 * A macro used to define new service structure types. 973 */ 974 975 #define FT_DEFINE_SERVICE( name ) \ 976 typedef struct FT_Service_ ## name ## Rec_ \ 977 FT_Service_ ## name ## Rec ; \ 978 typedef struct FT_Service_ ## name ## Rec_ \ 979 const * FT_Service_ ## name ; \ 980 struct FT_Service_ ## name ## Rec_ 981 982 /* */ 983 984 /* 985 * The header files containing the services. 986 */ 987 988 #define FT_SERVICE_BDF_H <freetype/internal/services/svbdf.h> 989 #define FT_SERVICE_CFF_TABLE_LOAD_H <freetype/internal/services/svcfftl.h> 990 #define FT_SERVICE_CID_H <freetype/internal/services/svcid.h> 991 #define FT_SERVICE_FONT_FORMAT_H <freetype/internal/services/svfntfmt.h> 992 #define FT_SERVICE_GLYPH_DICT_H <freetype/internal/services/svgldict.h> 993 #define FT_SERVICE_GX_VALIDATE_H <freetype/internal/services/svgxval.h> 994 #define FT_SERVICE_KERNING_H <freetype/internal/services/svkern.h> 995 #define FT_SERVICE_METRICS_VARIATIONS_H <freetype/internal/services/svmetric.h> 996 #define FT_SERVICE_MULTIPLE_MASTERS_H <freetype/internal/services/svmm.h> 997 #define FT_SERVICE_OPENTYPE_VALIDATE_H <freetype/internal/services/svotval.h> 998 #define FT_SERVICE_PFR_H <freetype/internal/services/svpfr.h> 999 #define FT_SERVICE_POSTSCRIPT_CMAPS_H <freetype/internal/services/svpscmap.h> 1000 #define FT_SERVICE_POSTSCRIPT_INFO_H <freetype/internal/services/svpsinfo.h> 1001 #define FT_SERVICE_POSTSCRIPT_NAME_H <freetype/internal/services/svpostnm.h> 1002 #define FT_SERVICE_PROPERTIES_H <freetype/internal/services/svprop.h> 1003 #define FT_SERVICE_SFNT_H <freetype/internal/services/svsfnt.h> 1004 #define FT_SERVICE_TRUETYPE_ENGINE_H <freetype/internal/services/svtteng.h> 1005 #define FT_SERVICE_TRUETYPE_GLYF_H <freetype/internal/services/svttglyf.h> 1006 #define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h> 1007 #define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h> 1008 1009 /* */ 1010 1011 FT_END_HEADER 1012 1013 #endif /* FTSERV_H_ */ 1014 1015 1016 /* END */ 1017