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, \ 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 } \ | 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, \ 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 } \ |