1 /***************************************************************************/ 2 /* */ 3 /* ftserv.h */ 4 /* */ 5 /* The FreeType services (specification only). */ 6 /* */ 7 /* Copyright 2003-2017 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 #else /* FT_CONFIG_OPTION_PIC */ 334 335 #define FT_DEFINE_SERVICEDESCREC1( class_, \ 336 serv_id_1, serv_data_1 ) \ 337 void \ 338 FT_Destroy_Class_ ## class_( FT_Library library, \ 339 FT_ServiceDescRec* clazz ) \ 340 { \ 341 FT_Memory memory = library->memory; \ 342 \ 343 \ 344 if ( clazz ) \ 345 FT_FREE( clazz ); \ 346 } \ 347 \ 348 FT_Error \ 349 FT_Create_Class_ ## class_( FT_Library library, \ 350 FT_ServiceDescRec** output_class ) \ 351 { \ 352 FT_ServiceDescRec* clazz = NULL; \ 353 FT_Error error; \ 354 FT_Memory memory = library->memory; \ 355 \ 356 \ 357 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 2 ) ) \ 358 return error; \ 359 \ 360 clazz[0].serv_id = serv_id_1; \ 361 clazz[0].serv_data = serv_data_1; \ 362 clazz[1].serv_id = NULL; \ 363 clazz[1].serv_data = NULL; \ 364 \ 365 *output_class = clazz; \ 366 \ 367 return FT_Err_Ok; \ 368 } 369 370 #define FT_DEFINE_SERVICEDESCREC2( class_, \ 371 serv_id_1, serv_data_1, \ 372 serv_id_2, serv_data_2 ) \ 373 void \ 374 FT_Destroy_Class_ ## class_( FT_Library library, \ 375 FT_ServiceDescRec* clazz ) \ 376 { \ 377 FT_Memory memory = library->memory; \ 378 \ 379 \ 380 if ( clazz ) \ 381 FT_FREE( clazz ); \ 382 } \ 383 \ 384 FT_Error \ 385 FT_Create_Class_ ## class_( FT_Library library, \ 386 FT_ServiceDescRec** output_class ) \ 387 { \ 388 FT_ServiceDescRec* clazz = NULL; \ 389 FT_Error error; \ 390 FT_Memory memory = library->memory; \ 391 \ 392 \ 393 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 3 ) ) \ 394 return error; \ 395 \ 396 clazz[0].serv_id = serv_id_1; \ 397 clazz[0].serv_data = serv_data_1; \ 398 clazz[1].serv_id = serv_id_2; \ 399 clazz[1].serv_data = serv_data_2; \ 400 clazz[2].serv_id = NULL; \ 401 clazz[2].serv_data = NULL; \ 402 \ 403 *output_class = clazz; \ 404 \ 405 return FT_Err_Ok; \ 406 } 407 408 #define FT_DEFINE_SERVICEDESCREC3( class_, \ 409 serv_id_1, serv_data_1, \ 410 serv_id_2, serv_data_2, \ 411 serv_id_3, serv_data_3 ) \ 412 void \ 413 FT_Destroy_Class_ ## class_( FT_Library library, \ 414 FT_ServiceDescRec* clazz ) \ 415 { \ 416 FT_Memory memory = library->memory; \ 417 \ 418 \ 419 if ( clazz ) \ 420 FT_FREE( clazz ); \ 421 } \ 422 \ 423 FT_Error \ 424 FT_Create_Class_ ## class_( FT_Library library, \ 425 FT_ServiceDescRec** output_class ) \ 426 { \ 427 FT_ServiceDescRec* clazz = NULL; \ 428 FT_Error error; \ 429 FT_Memory memory = library->memory; \ 430 \ 431 \ 432 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 4 ) ) \ 433 return error; \ 434 \ 435 clazz[0].serv_id = serv_id_1; \ 436 clazz[0].serv_data = serv_data_1; \ 437 clazz[1].serv_id = serv_id_2; \ 438 clazz[1].serv_data = serv_data_2; \ 439 clazz[2].serv_id = serv_id_3; \ 440 clazz[2].serv_data = serv_data_3; \ 441 clazz[3].serv_id = NULL; \ 442 clazz[3].serv_data = NULL; \ 443 \ 444 *output_class = clazz; \ 445 \ 446 return FT_Err_Ok; \ 447 } 448 449 #define FT_DEFINE_SERVICEDESCREC4( class_, \ 450 serv_id_1, serv_data_1, \ 451 serv_id_2, serv_data_2, \ 452 serv_id_3, serv_data_3, \ 453 serv_id_4, serv_data_4 ) \ 454 void \ 455 FT_Destroy_Class_ ## class_( FT_Library library, \ 456 FT_ServiceDescRec* clazz ) \ 457 { \ 458 FT_Memory memory = library->memory; \ 459 \ 460 \ 461 if ( clazz ) \ 462 FT_FREE( clazz ); \ 463 } \ 464 \ 465 FT_Error \ 466 FT_Create_Class_ ## class_( FT_Library library, \ 467 FT_ServiceDescRec** output_class ) \ 468 { \ 469 FT_ServiceDescRec* clazz = NULL; \ 470 FT_Error error; \ 471 FT_Memory memory = library->memory; \ 472 \ 473 \ 474 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 5 ) ) \ 475 return error; \ 476 \ 477 clazz[0].serv_id = serv_id_1; \ 478 clazz[0].serv_data = serv_data_1; \ 479 clazz[1].serv_id = serv_id_2; \ 480 clazz[1].serv_data = serv_data_2; \ 481 clazz[2].serv_id = serv_id_3; \ 482 clazz[2].serv_data = serv_data_3; \ 483 clazz[3].serv_id = serv_id_4; \ 484 clazz[3].serv_data = serv_data_4; \ 485 clazz[4].serv_id = NULL; \ 486 clazz[4].serv_data = NULL; \ 487 \ 488 *output_class = clazz; \ 489 \ 490 return FT_Err_Ok; \ 491 } 492 493 #define FT_DEFINE_SERVICEDESCREC5( class_, \ 494 serv_id_1, serv_data_1, \ 495 serv_id_2, serv_data_2, \ 496 serv_id_3, serv_data_3, \ 497 serv_id_4, serv_data_4, \ 498 serv_id_5, serv_data_5 ) \ 499 void \ 500 FT_Destroy_Class_ ## class_( FT_Library library, \ 501 FT_ServiceDescRec* clazz ) \ 502 { \ 503 FT_Memory memory = library->memory; \ 504 \ 505 \ 506 if ( clazz ) \ 507 FT_FREE( clazz ); \ 508 } \ 509 \ 510 FT_Error \ 511 FT_Create_Class_ ## class_( FT_Library library, \ 512 FT_ServiceDescRec** output_class ) \ 513 { \ 514 FT_ServiceDescRec* clazz = NULL; \ 515 FT_Error error; \ 516 FT_Memory memory = library->memory; \ 517 \ 518 \ 519 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 6 ) ) \ 520 return error; \ 521 \ 522 clazz[0].serv_id = serv_id_1; \ 523 clazz[0].serv_data = serv_data_1; \ 524 clazz[1].serv_id = serv_id_2; \ 525 clazz[1].serv_data = serv_data_2; \ 526 clazz[2].serv_id = serv_id_3; \ 527 clazz[2].serv_data = serv_data_3; \ 528 clazz[3].serv_id = serv_id_4; \ 529 clazz[3].serv_data = serv_data_4; \ 530 clazz[4].serv_id = serv_id_5; \ 531 clazz[4].serv_data = serv_data_5; \ 532 clazz[5].serv_id = NULL; \ 533 clazz[5].serv_data = NULL; \ 534 \ 535 *output_class = clazz; \ 536 \ 537 return FT_Err_Ok; \ 538 } 539 540 #define FT_DEFINE_SERVICEDESCREC6( class_, \ 541 serv_id_1, serv_data_1, \ 542 serv_id_2, serv_data_2, \ 543 serv_id_3, serv_data_3, \ 544 serv_id_4, serv_data_4, \ 545 serv_id_5, serv_data_5, \ 546 serv_id_6, serv_data_6 ) \ 547 void \ 548 FT_Destroy_Class_ ## class_( FT_Library library, \ 549 FT_ServiceDescRec* clazz ) \ 550 { \ 551 FT_Memory memory = library->memory; \ 552 \ 553 \ 554 if ( clazz ) \ 555 FT_FREE( clazz ); \ 556 } \ 557 \ 558 FT_Error \ 559 FT_Create_Class_ ## class_( FT_Library library, \ 560 FT_ServiceDescRec** output_class) \ 561 { \ 562 FT_ServiceDescRec* clazz = NULL; \ 563 FT_Error error; \ 564 FT_Memory memory = library->memory; \ 565 \ 566 \ 567 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 7 ) ) \ 568 return error; \ 569 \ 570 clazz[0].serv_id = serv_id_1; \ 571 clazz[0].serv_data = serv_data_1; \ 572 clazz[1].serv_id = serv_id_2; \ 573 clazz[1].serv_data = serv_data_2; \ 574 clazz[2].serv_id = serv_id_3; \ 575 clazz[2].serv_data = serv_data_3; \ 576 clazz[3].serv_id = serv_id_4; \ 577 clazz[3].serv_data = serv_data_4; \ 578 clazz[4].serv_id = serv_id_5; \ 579 clazz[4].serv_data = serv_data_5; \ 580 clazz[5].serv_id = serv_id_6; \ 581 clazz[5].serv_data = serv_data_6; \ 582 clazz[6].serv_id = NULL; \ 583 clazz[6].serv_data = NULL; \ 584 \ 585 *output_class = clazz; \ 586 \ 587 return FT_Err_Ok; \ 588 } 589 590 #define FT_DEFINE_SERVICEDESCREC7( class_, \ 591 serv_id_1, serv_data_1, \ 592 serv_id_2, serv_data_2, \ 593 serv_id_3, serv_data_3, \ 594 serv_id_4, serv_data_4, \ 595 serv_id_5, serv_data_5, \ 596 serv_id_6, serv_data_6, \ 597 serv_id_7, serv_data_7 ) \ 598 void \ 599 FT_Destroy_Class_ ## class_( FT_Library library, \ 600 FT_ServiceDescRec* clazz ) \ 601 { \ 602 FT_Memory memory = library->memory; \ 603 \ 604 \ 605 if ( clazz ) \ 606 FT_FREE( clazz ); \ 607 } \ 608 \ 609 FT_Error \ 610 FT_Create_Class_ ## class_( FT_Library library, \ 611 FT_ServiceDescRec** output_class) \ 612 { \ 613 FT_ServiceDescRec* clazz = NULL; \ 614 FT_Error error; \ 615 FT_Memory memory = library->memory; \ 616 \ 617 \ 618 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 8 ) ) \ 619 return error; \ 620 \ 621 clazz[0].serv_id = serv_id_1; \ 622 clazz[0].serv_data = serv_data_1; \ 623 clazz[1].serv_id = serv_id_2; \ 624 clazz[1].serv_data = serv_data_2; \ 625 clazz[2].serv_id = serv_id_3; \ 626 clazz[2].serv_data = serv_data_3; \ 627 clazz[3].serv_id = serv_id_4; \ 628 clazz[3].serv_data = serv_data_4; \ 629 clazz[4].serv_id = serv_id_5; \ 630 clazz[4].serv_data = serv_data_5; \ 631 clazz[5].serv_id = serv_id_6; \ 632 clazz[5].serv_data = serv_data_6; \ 633 clazz[6].serv_id = serv_id_7; \ 634 clazz[6].serv_data = serv_data_7; \ 635 clazz[7].serv_id = NULL; \ 636 clazz[7].serv_data = NULL; \ 637 \ 638 *output_class = clazz; \ 639 \ 640 return FT_Err_Ok; \ 641 } 642 643 #define FT_DEFINE_SERVICEDESCREC8( class_, \ 644 serv_id_1, serv_data_1, \ 645 serv_id_2, serv_data_2, \ 646 serv_id_3, serv_data_3, \ 647 serv_id_4, serv_data_4, \ 648 serv_id_5, serv_data_5, \ 649 serv_id_6, serv_data_6, \ 650 serv_id_7, serv_data_7, \ 651 serv_id_8, serv_data_8 ) \ 652 void \ 653 FT_Destroy_Class_ ## class_( FT_Library library, \ 654 FT_ServiceDescRec* clazz ) \ 655 { \ 656 FT_Memory memory = library->memory; \ 657 \ 658 \ 659 if ( clazz ) \ 660 FT_FREE( clazz ); \ 661 } \ 662 \ 663 FT_Error \ 664 FT_Create_Class_ ## class_( FT_Library library, \ 665 FT_ServiceDescRec** output_class) \ 666 { \ 667 FT_ServiceDescRec* clazz = NULL; \ 668 FT_Error error; \ 669 FT_Memory memory = library->memory; \ 670 \ 671 \ 672 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 9 ) ) \ 673 return error; \ 674 \ 675 clazz[0].serv_id = serv_id_1; \ 676 clazz[0].serv_data = serv_data_1; \ 677 clazz[1].serv_id = serv_id_2; \ 678 clazz[1].serv_data = serv_data_2; \ 679 clazz[2].serv_id = serv_id_3; \ 680 clazz[2].serv_data = serv_data_3; \ 681 clazz[3].serv_id = serv_id_4; \ 682 clazz[3].serv_data = serv_data_4; \ 683 clazz[4].serv_id = serv_id_5; \ 684 clazz[4].serv_data = serv_data_5; \ 685 clazz[5].serv_id = serv_id_6; \ 686 clazz[5].serv_data = serv_data_6; \ 687 clazz[6].serv_id = serv_id_7; \ 688 clazz[6].serv_data = serv_data_7; \ 689 clazz[7].serv_id = serv_id_8; \ 690 clazz[7].serv_data = serv_data_8; \ 691 clazz[8].serv_id = NULL; \ 692 clazz[8].serv_data = NULL; \ 693 \ 694 *output_class = clazz; \ 695 \ 696 return FT_Err_Ok; \ 697 } 698 699 #define FT_DEFINE_SERVICEDESCREC9( class_, \ 700 serv_id_1, serv_data_1, \ 701 serv_id_2, serv_data_2, \ 702 serv_id_3, serv_data_3, \ 703 serv_id_4, serv_data_4, \ 704 serv_id_5, serv_data_5, \ 705 serv_id_6, serv_data_6, \ 706 serv_id_7, serv_data_7, \ 707 serv_id_8, serv_data_8, \ 708 serv_id_9, serv_data_9 ) \ 709 void \ 710 FT_Destroy_Class_ ## class_( FT_Library library, \ 711 FT_ServiceDescRec* clazz ) \ 712 { \ 713 FT_Memory memory = library->memory; \ 714 \ 715 \ 716 if ( clazz ) \ 717 FT_FREE( clazz ); \ 718 } \ 719 \ 720 FT_Error \ 721 FT_Create_Class_ ## class_( FT_Library library, \ 722 FT_ServiceDescRec** output_class) \ 723 { \ 724 FT_ServiceDescRec* clazz = NULL; \ 725 FT_Error error; \ 726 FT_Memory memory = library->memory; \ 727 \ 728 \ 729 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 10 ) ) \ 730 return error; \ 731 \ 732 clazz[0].serv_id = serv_id_1; \ 733 clazz[0].serv_data = serv_data_1; \ 734 clazz[1].serv_id = serv_id_2; \ 735 clazz[1].serv_data = serv_data_2; \ 736 clazz[2].serv_id = serv_id_3; \ 737 clazz[2].serv_data = serv_data_3; \ 738 clazz[3].serv_id = serv_id_4; \ 739 clazz[3].serv_data = serv_data_4; \ 740 clazz[4].serv_id = serv_id_5; \ 741 clazz[4].serv_data = serv_data_5; \ 742 clazz[5].serv_id = serv_id_6; \ 743 clazz[5].serv_data = serv_data_6; \ 744 clazz[6].serv_id = serv_id_7; \ 745 clazz[6].serv_data = serv_data_7; \ 746 clazz[7].serv_id = serv_id_8; \ 747 clazz[7].serv_data = serv_data_8; \ 748 clazz[8].serv_id = serv_id_9; \ 749 clazz[8].serv_data = serv_data_9; \ 750 clazz[9].serv_id = NULL; \ 751 clazz[9].serv_data = NULL; \ 752 \ 753 *output_class = clazz; \ 754 \ 755 return FT_Err_Ok; \ 756 } 757 758 #endif /* FT_CONFIG_OPTION_PIC */ 759 760 761 /* 762 * Parse a list of FT_ServiceDescRec descriptors and look for 763 * a specific service by ID. Note that the last element in the 764 * array must be { NULL, NULL }, and that the function should 765 * return NULL if the service isn't available. 766 * 767 * This function can be used by modules to implement their 768 * `get_service' method. 769 */ 770 FT_BASE( FT_Pointer ) 771 ft_service_list_lookup( FT_ServiceDesc service_descriptors, 772 const char* service_id ); 773 774 775 /*************************************************************************/ 776 /*************************************************************************/ 777 /***** *****/ 778 /***** S E R V I C E S C A C H E *****/ 779 /***** *****/ 780 /*************************************************************************/ 781 /*************************************************************************/ 782 783 /* 784 * This structure is used to store a cache for several frequently used 785 * services. It is the type of `face->internal->services'. You 786 * should only use FT_FACE_LOOKUP_SERVICE to access it. 787 * 788 * All fields should have the type FT_Pointer to relax compilation 789 * dependencies. We assume the developer isn't completely stupid. 790 * 791 * Each field must be named `service_XXXX' where `XXX' corresponds to 792 * the correct FT_SERVICE_ID_XXXX macro. See the definition of 793 * FT_FACE_LOOKUP_SERVICE below how this is implemented. 794 * 795 */ 796 typedef struct FT_ServiceCacheRec_ 797 { 798 FT_Pointer service_POSTSCRIPT_FONT_NAME; 799 FT_Pointer service_MULTI_MASTERS; 800 FT_Pointer service_METRICS_VARIATIONS; 801 FT_Pointer service_GLYPH_DICT; 802 FT_Pointer service_PFR_METRICS; 803 FT_Pointer service_WINFNT; 804 805 } FT_ServiceCacheRec, *FT_ServiceCache; 806 807 808 /* 809 * A magic number used within the services cache. 810 */ 811 812 /* ensure that value `1' has the same width as a pointer */ 813 #define FT_SERVICE_UNAVAILABLE ((FT_Pointer)~(FT_PtrDist)1) 814 815 816 /* 817 * @macro: 818 * FT_FACE_LOOKUP_SERVICE 819 * 820 * @description: 821 * This macro is used to look up a service from a face's driver module 822 * using its cache. 823 * 824 * @input: 825 * face:: 826 * The source face handle containing the cache. 827 * 828 * field :: 829 * The field name in the cache. 830 * 831 * id :: 832 * The service ID. 833 * 834 * @output: 835 * ptr :: 836 * A variable receiving the service data. NULL if not available. 837 */ 838 #ifdef __cplusplus 839 840 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \ 841 FT_BEGIN_STMNT \ 842 FT_Pointer svc; \ 843 FT_Pointer* Pptr = (FT_Pointer*)&(ptr); \ 844 \ 845 \ 846 svc = FT_FACE( face )->internal->services. service_ ## id; \ 847 if ( svc == FT_SERVICE_UNAVAILABLE ) \ 848 svc = NULL; \ 849 else if ( svc == NULL ) \ 850 { \ 851 FT_FACE_FIND_SERVICE( face, svc, id ); \ 852 \ 853 FT_FACE( face )->internal->services. service_ ## id = \ 854 (FT_Pointer)( svc != NULL ? svc \ 855 : FT_SERVICE_UNAVAILABLE ); \ 856 } \ 857 *Pptr = svc; \ 858 FT_END_STMNT 859 860 #else /* !C++ */ 861 862 #define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \ 863 FT_BEGIN_STMNT \ 864 FT_Pointer svc; \ 865 \ 866 \ 867 svc = FT_FACE( face )->internal->services. service_ ## id; \ 868 if ( svc == FT_SERVICE_UNAVAILABLE ) \ 869 svc = NULL; \ 870 else if ( svc == NULL ) \ 871 { \ 872 FT_FACE_FIND_SERVICE( face, svc, id ); \ 873 \ 874 FT_FACE( face )->internal->services. service_ ## id = \ 875 (FT_Pointer)( svc != NULL ? svc \ 876 : FT_SERVICE_UNAVAILABLE ); \ 877 } \ 878 ptr = svc; \ 879 FT_END_STMNT 880 881 #endif /* !C++ */ 882 883 /* 884 * A macro used to define new service structure types. 885 */ 886 887 #define FT_DEFINE_SERVICE( name ) \ 888 typedef struct FT_Service_ ## name ## Rec_ \ 889 FT_Service_ ## name ## Rec ; \ 890 typedef struct FT_Service_ ## name ## Rec_ \ 891 const * FT_Service_ ## name ; \ 892 struct FT_Service_ ## name ## Rec_ 893 894 /* */ 895 896 /* 897 * The header files containing the services. 898 */ 899 900 #define FT_SERVICE_BDF_H <freetype/internal/services/svbdf.h> 901 #define FT_SERVICE_CID_H <freetype/internal/services/svcid.h> 902 #define FT_SERVICE_GLYPH_DICT_H <freetype/internal/services/svgldict.h> 903 #define FT_SERVICE_GX_VALIDATE_H <freetype/internal/services/svgxval.h> 904 #define FT_SERVICE_KERNING_H <freetype/internal/services/svkern.h> 905 #define FT_SERVICE_METRICS_VARIATIONS_H <freetype/internal/services/svmetric.h> 906 #define FT_SERVICE_MULTIPLE_MASTERS_H <freetype/internal/services/svmm.h> 907 #define FT_SERVICE_OPENTYPE_VALIDATE_H <freetype/internal/services/svotval.h> 908 #define FT_SERVICE_PFR_H <freetype/internal/services/svpfr.h> 909 #define FT_SERVICE_POSTSCRIPT_CMAPS_H <freetype/internal/services/svpscmap.h> 910 #define FT_SERVICE_POSTSCRIPT_INFO_H <freetype/internal/services/svpsinfo.h> 911 #define FT_SERVICE_POSTSCRIPT_NAME_H <freetype/internal/services/svpostnm.h> 912 #define FT_SERVICE_PROPERTIES_H <freetype/internal/services/svprop.h> 913 #define FT_SERVICE_SFNT_H <freetype/internal/services/svsfnt.h> 914 #define FT_SERVICE_TRUETYPE_ENGINE_H <freetype/internal/services/svtteng.h> 915 #define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h> 916 #define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h> 917 #define FT_SERVICE_FONT_FORMAT_H <freetype/internal/services/svfntfmt.h> 918 #define FT_SERVICE_TRUETYPE_GLYF_H <freetype/internal/services/svttglyf.h> 919 920 /* */ 921 922 FT_END_HEADER 923 924 #endif /* FTSERV_H_ */ 925 926 927 /* END */ 928