1 /***************************************************************************/ 2 /* */ 3 /* ftobjs.c */ 4 /* */ 5 /* The FreeType private base classes (body). */ 6 /* */ 7 /* Copyright 1996-2001, 2002 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 #include <ft2build.h> 20 #include FT_LIST_H 21 #include FT_OUTLINE_H 22 #include FT_INTERNAL_OBJECTS_H 23 #include FT_INTERNAL_DEBUG_H 24 #include FT_INTERNAL_STREAM_H 25 #include FT_TRUETYPE_TABLES_H 26 #include FT_OUTLINE_H 27 28 29 FT_BASE_DEF( void ) 30 ft_validator_init( FT_Validator valid, 31 const FT_Byte* base, 32 const FT_Byte* limit, 33 FT_ValidationLevel level ) 34 { 35 valid->base = base; 36 valid->limit = limit; 37 valid->level = level; 38 valid->error = 0; 39 } 40 41 42 FT_BASE_DEF( FT_Int ) 43 ft_validator_run( FT_Validator valid ) 44 { 45 int result; 46 47 48 result = ft_setjmp( valid->jump_buffer ); 49 return result; 50 } 51 52 53 FT_BASE_DEF( void ) 54 ft_validator_error( FT_Validator valid, 55 FT_Error error ) 56 { 57 valid->error = error; 58 ft_longjmp( valid->jump_buffer, 1 ); 59 } 60 61 62 /*************************************************************************/ 63 /*************************************************************************/ 64 /*************************************************************************/ 65 /**** ****/ 66 /**** ****/ 67 /**** S T R E A M ****/ 68 /**** ****/ 69 /**** ****/ 70 /*************************************************************************/ 71 /*************************************************************************/ 72 /*************************************************************************/ 73 74 75 /* create a new input stream from a FT_Open_Args structure */ 76 /* */ 77 static FT_Error 78 ft_input_stream_new( FT_Library library, 79 const FT_Open_Args* args, 80 FT_Stream* astream ) 81 { 82 FT_Error error; 83 FT_Memory memory; 84 FT_Stream stream; 85 86 87 if ( !library ) 88 return FT_Err_Invalid_Library_Handle; 89 90 if ( !args ) 91 return FT_Err_Invalid_Argument; 92 93 *astream = 0; 94 memory = library->memory; 95 96 if ( FT_NEW( stream ) ) 97 goto Exit; 98 99 stream->memory = memory; 100 101 if ( args->flags & FT_OPEN_MEMORY ) 102 { 103 /* create a memory-based stream */ 104 FT_Stream_OpenMemory( stream, 105 (const FT_Byte*)args->memory_base, 106 args->memory_size ); 107 } 108 else if ( args->flags & FT_OPEN_PATHNAME ) 109 { 110 /* create a normal system stream */ 111 error = FT_Stream_Open( stream, args->pathname ); 112 stream->pathname.pointer = args->pathname; 113 } 114 else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream ) 115 { 116 /* use an existing, user-provided stream */ 117 118 /* in this case, we do not need to allocate a new stream object */ 119 /* since the caller is responsible for closing it himself */ 120 FT_FREE( stream ); 121 stream = args->stream; 122 } 123 else 124 error = FT_Err_Invalid_Argument; 125 126 if ( error ) 127 FT_FREE( stream ); 128 else 129 stream->memory = memory; /* just to be certain */ 130 131 *astream = stream; 132 133 Exit: 134 return error; 135 } 136 137 138 static void 139 ft_input_stream_free( FT_Stream stream, 140 FT_Int external ) 141 { 142 if ( stream ) 143 { 144 FT_Memory memory = stream->memory; 145 146 147 FT_Stream_Close( stream ); 148 149 if ( !external ) 150 FT_FREE( stream ); 151 } 152 } 153 154 155 #undef FT_COMPONENT 156 #define FT_COMPONENT trace_objs 157 158 159 /*************************************************************************/ 160 /*************************************************************************/ 161 /*************************************************************************/ 162 /**** ****/ 163 /**** ****/ 164 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/ 165 /**** ****/ 166 /**** ****/ 167 /*************************************************************************/ 168 /*************************************************************************/ 169 /*************************************************************************/ 170 171 172 static FT_Error 173 ft_glyphslot_init( FT_GlyphSlot slot ) 174 { 175 FT_Driver driver = slot->face->driver; 176 FT_Driver_Class clazz = driver->clazz; 177 FT_Memory memory = driver->root.memory; 178 FT_Error error = FT_Err_Ok; 179 FT_Slot_Internal internal; 180 181 182 slot->library = driver->root.library; 183 184 if ( FT_NEW( internal ) ) 185 goto Exit; 186 187 slot->internal = internal; 188 189 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 190 error = FT_GlyphLoader_New( memory, &internal->loader ); 191 192 if ( !error && clazz->init_slot ) 193 error = clazz->init_slot( slot ); 194 195 Exit: 196 return error; 197 } 198 199 200 static void 201 ft_glyphslot_clear( FT_GlyphSlot slot ) 202 { 203 /* free bitmap if needed */ 204 if ( slot->flags & FT_GLYPH_OWN_BITMAP ) 205 { 206 FT_Memory memory = FT_FACE_MEMORY( slot->face ); 207 208 209 FT_FREE( slot->bitmap.buffer ); 210 slot->flags &= ~FT_GLYPH_OWN_BITMAP; 211 } 212 213 /* clear all public fields in the glyph slot */ 214 FT_ZERO( &slot->metrics ); 215 FT_ZERO( &slot->outline ); 216 217 slot->bitmap.width = 0; 218 slot->bitmap.rows = 0; 219 slot->bitmap.pitch = 0; 220 slot->bitmap.pixel_mode = 0; 221 /* don't touch 'slot->bitmap.buffer' !! */ 222 223 slot->bitmap_left = 0; 224 slot->bitmap_top = 0; 225 slot->num_subglyphs = 0; 226 slot->subglyphs = 0; 227 slot->control_data = 0; 228 slot->control_len = 0; 229 slot->other = 0; 230 slot->format = FT_GLYPH_FORMAT_NONE; 231 232 slot->linearHoriAdvance = 0; 233 slot->linearVertAdvance = 0; 234 } 235 236 237 static void 238 ft_glyphslot_done( FT_GlyphSlot slot ) 239 { 240 FT_Driver driver = slot->face->driver; 241 FT_Driver_Class clazz = driver->clazz; 242 FT_Memory memory = driver->root.memory; 243 244 245 if ( clazz->done_slot ) 246 clazz->done_slot( slot ); 247 248 /* free bitmap buffer if needed */ 249 if ( slot->flags & FT_GLYPH_OWN_BITMAP ) 250 FT_FREE( slot->bitmap.buffer ); 251 252 /* free glyph loader */ 253 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 254 { 255 FT_GlyphLoader_Done( slot->internal->loader ); 256 slot->internal->loader = 0; 257 } 258 259 FT_FREE( slot->internal ); 260 } 261 262 263 /* documentation is in ftobjs.h */ 264 265 FT_BASE_DEF( FT_Error ) 266 FT_New_GlyphSlot( FT_Face face, 267 FT_GlyphSlot *aslot ) 268 { 269 FT_Error error; 270 FT_Driver driver; 271 FT_Driver_Class clazz; 272 FT_Memory memory; 273 FT_GlyphSlot slot; 274 275 276 if ( !face || !aslot || !face->driver ) 277 return FT_Err_Invalid_Argument; 278 279 *aslot = 0; 280 281 driver = face->driver; 282 clazz = driver->clazz; 283 memory = driver->root.memory; 284 285 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" )); 286 if ( !FT_ALLOC( slot, clazz->slot_object_size ) ) 287 { 288 slot->face = face; 289 290 error = ft_glyphslot_init( slot ); 291 if ( error ) 292 { 293 ft_glyphslot_done( slot ); 294 FT_FREE( slot ); 295 goto Exit; 296 } 297 298 *aslot = slot; 299 } 300 301 Exit: 302 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error )); 303 return error; 304 } 305 306 307 /* documentation is in ftobjs.h */ 308 309 FT_BASE_DEF( void ) 310 FT_Done_GlyphSlot( FT_GlyphSlot slot ) 311 { 312 if ( slot ) 313 { 314 FT_Driver driver = slot->face->driver; 315 FT_Memory memory = driver->root.memory; 316 FT_GlyphSlot* parent; 317 FT_GlyphSlot cur; 318 319 320 /* Remove slot from its parent face's list */ 321 parent = &slot->face->glyph; 322 cur = *parent; 323 324 while ( cur ) 325 { 326 if ( cur == slot ) 327 { 328 *parent = cur->next; 329 ft_glyphslot_done( slot ); 330 FT_FREE( slot ); 331 break; 332 } 333 cur = cur->next; 334 } 335 } 336 } 337 338 339 /* documentation is in freetype.h */ 340 341 FT_EXPORT_DEF( void ) 342 FT_Set_Transform( FT_Face face, 343 FT_Matrix* matrix, 344 FT_Vector* delta ) 345 { 346 FT_Face_Internal internal; 347 348 349 if ( !face ) 350 return; 351 352 internal = face->internal; 353 354 internal->transform_flags = 0; 355 356 if ( !matrix ) 357 { 358 internal->transform_matrix.xx = 0x10000L; 359 internal->transform_matrix.xy = 0; 360 internal->transform_matrix.yx = 0; 361 internal->transform_matrix.yy = 0x10000L; 362 matrix = &internal->transform_matrix; 363 } 364 else 365 internal->transform_matrix = *matrix; 366 367 /* set transform_flags bit flag 0 if `matrix' isn't the identity */ 368 if ( ( matrix->xy | matrix->yx ) || 369 matrix->xx != 0x10000L || 370 matrix->yy != 0x10000L ) 371 internal->transform_flags |= 1; 372 373 if ( !delta ) 374 { 375 internal->transform_delta.x = 0; 376 internal->transform_delta.y = 0; 377 delta = &internal->transform_delta; 378 } 379 else 380 internal->transform_delta = *delta; 381 382 /* set transform_flags bit flag 1 if `delta' isn't the null vector */ 383 if ( delta->x | delta->y ) 384 internal->transform_flags |= 2; 385 } 386 387 388 /* documentation is in freetype.h */ 389 390 FT_EXPORT_DEF( void ) 391 FT_Set_Hint_Flags( FT_Face face, 392 FT_ULong flags ) 393 { 394 FT_Face_Internal internal; 395 396 if ( !face ) 397 return; 398 399 internal = face->internal; 400 401 internal->hint_flags = (FT_UInt)flags; 402 } 403 404 405 static FT_Renderer 406 ft_lookup_glyph_renderer( FT_GlyphSlot slot ); 407 408 409 /* documentation is in freetype.h */ 410 411 FT_EXPORT_DEF( FT_Error ) 412 FT_Load_Glyph( FT_Face face, 413 FT_UInt glyph_index, 414 FT_Int32 load_flags ) 415 { 416 FT_Error error; 417 FT_Driver driver; 418 FT_GlyphSlot slot; 419 FT_Library library; 420 FT_Bool autohint; 421 FT_Module hinter; 422 423 424 if ( !face || !face->size || !face->glyph ) 425 return FT_Err_Invalid_Face_Handle; 426 427 if ( glyph_index > (FT_UInt)face->num_glyphs ) 428 return FT_Err_Invalid_Argument; 429 430 slot = face->glyph; 431 ft_glyphslot_clear( slot ); 432 433 driver = face->driver; 434 435 /* if the flag NO_RECURSE is set, we disable hinting and scaling */ 436 if ( load_flags & FT_LOAD_NO_RECURSE ) 437 { 438 /* disable scaling, hinting, and transformation */ 439 load_flags |= FT_LOAD_NO_SCALE | 440 FT_LOAD_NO_HINTING | 441 FT_LOAD_NO_BITMAP | 442 FT_LOAD_IGNORE_TRANSFORM; 443 444 /* disable bitmap rendering */ 445 load_flags &= ~FT_LOAD_RENDER; 446 } 447 448 /* do we need to load the glyph through the auto-hinter? */ 449 library = driver->root.library; 450 hinter = library->auto_hinter; 451 autohint = 452 FT_BOOL( hinter && 453 !( load_flags & ( FT_LOAD_NO_SCALE | 454 FT_LOAD_NO_HINTING | 455 FT_LOAD_NO_AUTOHINT ) ) && 456 FT_DRIVER_IS_SCALABLE( driver ) && 457 FT_DRIVER_USES_OUTLINES( driver ) ); 458 if ( autohint ) 459 { 460 if ( FT_DRIVER_HAS_HINTER( driver ) && 461 !( load_flags & FT_LOAD_FORCE_AUTOHINT ) ) 462 autohint = 0; 463 } 464 465 if ( autohint ) 466 { 467 FT_AutoHinter_Service hinting; 468 469 470 /* try to load embedded bitmaps first if available */ 471 /* */ 472 /* XXX: This is really a temporary hack that should disappear */ 473 /* promptly with FreeType 2.1! */ 474 /* */ 475 if ( FT_HAS_FIXED_SIZES( face ) && 476 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) 477 { 478 error = driver->clazz->load_glyph( slot, face->size, 479 glyph_index, 480 load_flags | FT_LOAD_SBITS_ONLY ); 481 482 if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP ) 483 goto Load_Ok; 484 } 485 486 /* load auto-hinted outline */ 487 hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface; 488 489 error = hinting->load_glyph( (FT_AutoHinter)hinter, 490 slot, face->size, 491 glyph_index, load_flags ); 492 } 493 else 494 { 495 error = driver->clazz->load_glyph( slot, 496 face->size, 497 glyph_index, 498 load_flags ); 499 if ( error ) 500 goto Exit; 501 502 /* check that the loaded outline is correct */ 503 error = FT_Outline_Check( &slot->outline ); 504 if ( error ) 505 goto Exit; 506 } 507 508 Load_Ok: 509 /* compute the advance */ 510 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 511 { 512 slot->advance.x = 0; 513 slot->advance.y = slot->metrics.vertAdvance; 514 } 515 else 516 { 517 slot->advance.x = slot->metrics.horiAdvance; 518 slot->advance.y = 0; 519 } 520 521 /* compute the linear advance in 16.16 pixels */ 522 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 ) 523 { 524 FT_UInt EM = face->units_per_EM; 525 FT_Size_Metrics* metrics = &face->size->metrics; 526 527 528 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance, 529 (FT_Long)metrics->x_ppem << 16, EM ); 530 531 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance, 532 (FT_Long)metrics->y_ppem << 16, EM ); 533 } 534 535 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 ) 536 { 537 FT_Face_Internal internal = face->internal; 538 539 540 /* now, transform the glyph image if needed */ 541 if ( internal->transform_flags ) 542 { 543 /* get renderer */ 544 FT_Renderer renderer = ft_lookup_glyph_renderer( slot ); 545 546 547 if ( renderer ) 548 error = renderer->clazz->transform_glyph( 549 renderer, slot, 550 &internal->transform_matrix, 551 &internal->transform_delta ); 552 /* transform advance */ 553 FT_Vector_Transform( &slot->advance, &internal->transform_matrix ); 554 } 555 } 556 557 /* do we need to render the image now? */ 558 if ( !error && 559 slot->format != FT_GLYPH_FORMAT_BITMAP && 560 slot->format != FT_GLYPH_FORMAT_COMPOSITE && 561 load_flags & FT_LOAD_RENDER ) 562 { 563 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); 564 565 566 if ( mode == FT_RENDER_MODE_NORMAL && 567 (load_flags & FT_LOAD_MONOCHROME ) ) 568 mode = FT_RENDER_MODE_MONO; 569 570 error = FT_Render_Glyph( slot, mode ); 571 } 572 573 Exit: 574 return error; 575 } 576 577 578 /* documentation is in freetype.h */ 579 580 FT_EXPORT_DEF( FT_Error ) 581 FT_Load_Char( FT_Face face, 582 FT_ULong char_code, 583 FT_Int32 load_flags ) 584 { 585 FT_UInt glyph_index; 586 587 588 if ( !face ) 589 return FT_Err_Invalid_Face_Handle; 590 591 glyph_index = (FT_UInt)char_code; 592 if ( face->charmap ) 593 glyph_index = FT_Get_Char_Index( face, char_code ); 594 595 return FT_Load_Glyph( face, glyph_index, load_flags ); 596 } 597 598 599 /* destructor for sizes list */ 600 static void 601 destroy_size( FT_Memory memory, 602 FT_Size size, 603 FT_Driver driver ) 604 { 605 /* finalize client-specific data */ 606 if ( size->generic.finalizer ) 607 size->generic.finalizer( size ); 608 609 /* finalize format-specific stuff */ 610 if ( driver->clazz->done_size ) 611 driver->clazz->done_size( size ); 612 613 FT_FREE( size->internal ); 614 FT_FREE( size ); 615 } 616 617 618 /* destructor for faces list */ 619 static void 620 destroy_face( FT_Memory memory, 621 FT_Face face, 622 FT_Driver driver ) 623 { 624 FT_Driver_Class clazz = driver->clazz; 625 626 627 /* discard auto-hinting data */ 628 if ( face->autohint.finalizer ) 629 face->autohint.finalizer( face->autohint.data ); 630 631 /* Discard glyph slots for this face. */ 632 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */ 633 while ( face->glyph ) 634 FT_Done_GlyphSlot( face->glyph ); 635 636 /* discard all sizes for this face */ 637 FT_List_Finalize( &face->sizes_list, 638 (FT_List_Destructor)destroy_size, 639 memory, 640 driver ); 641 face->size = 0; 642 643 /* now discard client data */ 644 if ( face->generic.finalizer ) 645 face->generic.finalizer( face ); 646 647 /* discard charmaps */ 648 { 649 FT_Int n; 650 651 652 for ( n = 0; n < face->num_charmaps; n++ ) 653 { 654 FT_CMap cmap = FT_CMAP( face->charmaps[n] ); 655 656 657 FT_CMap_Done( cmap ); 658 659 face->charmaps[n] = NULL; 660 } 661 662 FT_FREE( face->charmaps ); 663 face->num_charmaps = 0; 664 } 665 666 667 /* finalize format-specific stuff */ 668 if ( clazz->done_face ) 669 clazz->done_face( face ); 670 671 /* close the stream for this face if needed */ 672 ft_input_stream_free( 673 face->stream, 674 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 ); 675 676 face->stream = 0; 677 678 /* get rid of it */ 679 if ( face->internal ) 680 { 681 FT_FREE( face->internal->postscript_name ); 682 FT_FREE( face->internal ); 683 } 684 FT_FREE( face ); 685 } 686 687 688 static void 689 Destroy_Driver( FT_Driver driver ) 690 { 691 FT_List_Finalize( &driver->faces_list, 692 (FT_List_Destructor)destroy_face, 693 driver->root.memory, 694 driver ); 695 696 /* check whether we need to drop the driver's glyph loader */ 697 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 698 FT_GlyphLoader_Done( driver->glyph_loader ); 699 } 700 701 702 /*************************************************************************/ 703 /* */ 704 /* <Function> */ 705 /* open_face */ 706 /* */ 707 /* <Description> */ 708 /* This function does some work for FT_Open_Face(). */ 709 /* */ 710 static FT_Error 711 open_face( FT_Driver driver, 712 FT_Stream stream, 713 FT_Long face_index, 714 FT_Int num_params, 715 FT_Parameter* params, 716 FT_Face* aface ) 717 { 718 FT_Memory memory; 719 FT_Driver_Class clazz; 720 FT_Face face = 0; 721 FT_Error error; 722 FT_Face_Internal internal; 723 724 725 clazz = driver->clazz; 726 memory = driver->root.memory; 727 728 /* allocate the face object and perform basic initialization */ 729 if ( FT_ALLOC( face, clazz->face_object_size ) ) 730 goto Fail; 731 732 if ( FT_NEW( internal ) ) 733 goto Fail; 734 735 face->internal = internal; 736 737 face->driver = driver; 738 face->memory = memory; 739 face->stream = stream; 740 741 #ifdef FT_CONFIG_OPTION_INCREMENTAL 742 { 743 int i; 744 745 746 face->internal->incremental_interface = 0; 747 for ( i = 0; i < num_params && !face->internal->incremental_interface; 748 i++ ) 749 if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL ) 750 face->internal->incremental_interface = params[i].data; 751 } 752 #endif 753 754 error = clazz->init_face( stream, 755 face, 756 (FT_Int)face_index, 757 num_params, 758 params ); 759 if ( error ) 760 goto Fail; 761 762 /* select Unicode charmap by default */ 763 { 764 FT_Int nn; 765 FT_CharMap unicmap = NULL, cmap; 766 767 768 for ( nn = 0; nn < face->num_charmaps; nn++ ) 769 { 770 cmap = face->charmaps[nn]; 771 772 if ( cmap->encoding == FT_ENCODING_UNICODE ) 773 { 774 unicmap = cmap; 775 break; 776 } 777 } 778 779 if ( unicmap != NULL ) 780 face->charmap = unicmap; 781 } 782 783 *aface = face; 784 785 Fail: 786 if ( error ) 787 { 788 clazz->done_face( face ); 789 FT_FREE( face->internal ); 790 FT_FREE( face ); 791 *aface = 0; 792 } 793 794 return error; 795 } 796 797 798 /* there's a Mac-specific extended implementation of FT_New_Face() */ 799 /* in src/base/ftmac.c */ 800 801 #ifndef FT_MACINTOSH 802 803 /* documentation is in freetype.h */ 804 805 FT_EXPORT_DEF( FT_Error ) 806 FT_New_Face( FT_Library library, 807 const char* pathname, 808 FT_Long face_index, 809 FT_Face *aface ) 810 { 811 FT_Open_Args args; 812 813 814 /* test for valid `library' and `aface' delayed to FT_Open_Face() */ 815 if ( !pathname ) 816 return FT_Err_Invalid_Argument; 817 818 args.flags = FT_OPEN_PATHNAME; 819 args.pathname = (char*)pathname; 820 821 return FT_Open_Face( library, &args, face_index, aface ); 822 } 823 824 #endif /* !FT_MACINTOSH */ 825 826 827 /* documentation is in freetype.h */ 828 829 FT_EXPORT_DEF( FT_Error ) 830 FT_New_Memory_Face( FT_Library library, 831 const FT_Byte* file_base, 832 FT_Long file_size, 833 FT_Long face_index, 834 FT_Face *aface ) 835 { 836 FT_Open_Args args; 837 838 839 /* test for valid `library' and `face' delayed to FT_Open_Face() */ 840 if ( !file_base ) 841 return FT_Err_Invalid_Argument; 842 843 args.flags = FT_OPEN_MEMORY; 844 args.memory_base = file_base; 845 args.memory_size = file_size; 846 847 return FT_Open_Face( library, &args, face_index, aface ); 848 } 849 850 851 /* documentation is in freetype.h */ 852 853 FT_EXPORT_DEF( FT_Error ) 854 FT_Open_Face( FT_Library library, 855 const FT_Open_Args* args, 856 FT_Long face_index, 857 FT_Face *aface ) 858 { 859 FT_Error error; 860 FT_Driver driver; 861 FT_Memory memory; 862 FT_Stream stream; 863 FT_Face face = 0; 864 FT_ListNode node = 0; 865 FT_Bool external_stream; 866 867 868 /* test for valid `library' delayed to */ 869 /* ft_input_stream_new() */ 870 871 if ( !aface || !args ) 872 return FT_Err_Invalid_Argument; 873 874 *aface = 0; 875 876 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) && 877 args->stream ); 878 879 /* create input stream */ 880 error = ft_input_stream_new( library, args, &stream ); 881 if ( error ) 882 goto Exit; 883 884 memory = library->memory; 885 886 /* If the font driver is specified in the `args' structure, use */ 887 /* it. Otherwise, we scan the list of registered drivers. */ 888 if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver ) 889 { 890 driver = FT_DRIVER( args->driver ); 891 892 /* not all modules are drivers, so check... */ 893 if ( FT_MODULE_IS_DRIVER( driver ) ) 894 { 895 FT_Int num_params = 0; 896 FT_Parameter* params = 0; 897 898 899 if ( args->flags & FT_OPEN_PARAMS ) 900 { 901 num_params = args->num_params; 902 params = args->params; 903 } 904 905 error = open_face( driver, stream, face_index, 906 num_params, params, &face ); 907 if ( !error ) 908 goto Success; 909 } 910 else 911 error = FT_Err_Invalid_Handle; 912 913 ft_input_stream_free( stream, external_stream ); 914 goto Fail; 915 } 916 else 917 { 918 /* check each font driver for an appropriate format */ 919 FT_Module* cur = library->modules; 920 FT_Module* limit = cur + library->num_modules; 921 922 923 for ( ; cur < limit; cur++ ) 924 { 925 /* not all modules are font drivers, so check... */ 926 if ( FT_MODULE_IS_DRIVER( cur[0] ) ) 927 { 928 FT_Int num_params = 0; 929 FT_Parameter* params = 0; 930 931 932 driver = FT_DRIVER( cur[0] ); 933 934 if ( args->flags & FT_OPEN_PARAMS ) 935 { 936 num_params = args->num_params; 937 params = args->params; 938 } 939 940 error = open_face( driver, stream, face_index, 941 num_params, params, &face ); 942 if ( !error ) 943 goto Success; 944 945 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format ) 946 goto Fail2; 947 } 948 } 949 950 /* no driver is able to handle this format */ 951 error = FT_Err_Unknown_File_Format; 952 953 Fail2: 954 ft_input_stream_free( stream, external_stream ); 955 goto Fail; 956 } 957 958 Success: 959 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" )); 960 961 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */ 962 if ( external_stream ) 963 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM; 964 965 /* add the face object to its driver's list */ 966 if ( FT_NEW( node ) ) 967 goto Fail; 968 969 node->data = face; 970 /* don't assume driver is the same as face->driver, so use */ 971 /* face->driver instead. */ 972 FT_List_Add( &face->driver->faces_list, node ); 973 974 /* now allocate a glyph slot object for the face */ 975 { 976 FT_GlyphSlot slot; 977 978 979 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" )); 980 981 error = FT_New_GlyphSlot( face, &slot ); 982 if ( error ) 983 goto Fail; 984 985 face->glyph = slot; 986 } 987 988 /* finally, allocate a size object for the face */ 989 { 990 FT_Size size; 991 992 993 FT_TRACE4(( "FT_Open_Face: Creating size object\n" )); 994 995 error = FT_New_Size( face, &size ); 996 if ( error ) 997 goto Fail; 998 999 face->size = size; 1000 } 1001 1002 /* initialize internal face data */ 1003 { 1004 FT_Face_Internal internal = face->internal; 1005 1006 1007 internal->transform_matrix.xx = 0x10000L; 1008 internal->transform_matrix.xy = 0; 1009 internal->transform_matrix.yx = 0; 1010 internal->transform_matrix.yy = 0x10000L; 1011 1012 internal->transform_delta.x = 0; 1013 internal->transform_delta.y = 0; 1014 } 1015 1016 *aface = face; 1017 goto Exit; 1018 1019 Fail: 1020 FT_Done_Face( face ); 1021 1022 Exit: 1023 FT_TRACE4(( "FT_Open_Face: Return %d\n", error )); 1024 1025 return error; 1026 } 1027 1028 1029 /* documentation is in freetype.h */ 1030 1031 FT_EXPORT_DEF( FT_Error ) 1032 FT_Attach_File( FT_Face face, 1033 const char* filepathname ) 1034 { 1035 FT_Open_Args open; 1036 1037 1038 /* test for valid `face' delayed to FT_Attach_Stream() */ 1039 1040 if ( !filepathname ) 1041 return FT_Err_Invalid_Argument; 1042 1043 open.flags = FT_OPEN_PATHNAME; 1044 open.pathname = (char*)filepathname; 1045 1046 return FT_Attach_Stream( face, &open ); 1047 } 1048 1049 1050 /* documentation is in freetype.h */ 1051 1052 FT_EXPORT_DEF( FT_Error ) 1053 FT_Attach_Stream( FT_Face face, 1054 FT_Open_Args* parameters ) 1055 { 1056 FT_Stream stream; 1057 FT_Error error; 1058 FT_Driver driver; 1059 1060 FT_Driver_Class clazz; 1061 1062 1063 /* test for valid `parameters' delayed to ft_input_stream_new() */ 1064 1065 if ( !face ) 1066 return FT_Err_Invalid_Face_Handle; 1067 1068 driver = face->driver; 1069 if ( !driver ) 1070 return FT_Err_Invalid_Driver_Handle; 1071 1072 error = ft_input_stream_new( driver->root.library, parameters, &stream ); 1073 if ( error ) 1074 goto Exit; 1075 1076 /* we implement FT_Attach_Stream in each driver through the */ 1077 /* `attach_file' interface */ 1078 1079 error = FT_Err_Unimplemented_Feature; 1080 clazz = driver->clazz; 1081 if ( clazz->attach_file ) 1082 error = clazz->attach_file( face, stream ); 1083 1084 /* close the attached stream */ 1085 ft_input_stream_free( stream, 1086 (FT_Bool)( parameters->stream && 1087 ( parameters->flags & FT_OPEN_STREAM ) ) ); 1088 1089 Exit: 1090 return error; 1091 } 1092 1093 1094 /* documentation is in freetype.h */ 1095 1096 FT_EXPORT_DEF( FT_Error ) 1097 FT_Done_Face( FT_Face face ) 1098 { 1099 FT_Error error; 1100 FT_Driver driver; 1101 FT_Memory memory; 1102 FT_ListNode node; 1103 1104 1105 error = FT_Err_Invalid_Face_Handle; 1106 if ( face && face->driver ) 1107 { 1108 driver = face->driver; 1109 memory = driver->root.memory; 1110 1111 /* find face in driver's list */ 1112 node = FT_List_Find( &driver->faces_list, face ); 1113 if ( node ) 1114 { 1115 /* remove face object from the driver's list */ 1116 FT_List_Remove( &driver->faces_list, node ); 1117 FT_FREE( node ); 1118 1119 /* now destroy the object proper */ 1120 destroy_face( memory, face, driver ); 1121 error = FT_Err_Ok; 1122 } 1123 } 1124 return error; 1125 } 1126 1127 1128 /* documentation is in ftobjs.h */ 1129 1130 FT_EXPORT_DEF( FT_Error ) 1131 FT_New_Size( FT_Face face, 1132 FT_Size *asize ) 1133 { 1134 FT_Error error; 1135 FT_Memory memory; 1136 FT_Driver driver; 1137 FT_Driver_Class clazz; 1138 1139 FT_Size size = 0; 1140 FT_ListNode node = 0; 1141 1142 1143 if ( !face ) 1144 return FT_Err_Invalid_Face_Handle; 1145 1146 if ( !asize ) 1147 return FT_Err_Invalid_Size_Handle; 1148 1149 if ( !face->driver ) 1150 return FT_Err_Invalid_Driver_Handle; 1151 1152 *asize = 0; 1153 1154 driver = face->driver; 1155 clazz = driver->clazz; 1156 memory = face->memory; 1157 1158 /* Allocate new size object and perform basic initialisation */ 1159 if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) ) 1160 goto Exit; 1161 1162 size->face = face; 1163 1164 /* for now, do not use any internal fields in size objects */ 1165 size->internal = 0; 1166 1167 if ( clazz->init_size ) 1168 error = clazz->init_size( size ); 1169 1170 /* in case of success, add to the face's list */ 1171 if ( !error ) 1172 { 1173 *asize = size; 1174 node->data = size; 1175 FT_List_Add( &face->sizes_list, node ); 1176 } 1177 1178 Exit: 1179 if ( error ) 1180 { 1181 FT_FREE( node ); 1182 FT_FREE( size ); 1183 } 1184 1185 return error; 1186 } 1187 1188 1189 /* documentation is in ftobjs.h */ 1190 1191 FT_EXPORT_DEF( FT_Error ) 1192 FT_Done_Size( FT_Size size ) 1193 { 1194 FT_Error error; 1195 FT_Driver driver; 1196 FT_Memory memory; 1197 FT_Face face; 1198 FT_ListNode node; 1199 1200 1201 if ( !size ) 1202 return FT_Err_Invalid_Size_Handle; 1203 1204 face = size->face; 1205 if ( !face ) 1206 return FT_Err_Invalid_Face_Handle; 1207 1208 driver = face->driver; 1209 if ( !driver ) 1210 return FT_Err_Invalid_Driver_Handle; 1211 1212 memory = driver->root.memory; 1213 1214 error = FT_Err_Ok; 1215 node = FT_List_Find( &face->sizes_list, size ); 1216 if ( node ) 1217 { 1218 FT_List_Remove( &face->sizes_list, node ); 1219 FT_FREE( node ); 1220 1221 if ( face->size == size ) 1222 { 1223 face->size = 0; 1224 if ( face->sizes_list.head ) 1225 face->size = (FT_Size)(face->sizes_list.head->data); 1226 } 1227 1228 destroy_size( memory, size, driver ); 1229 } 1230 else 1231 error = FT_Err_Invalid_Size_Handle; 1232 1233 return error; 1234 } 1235 1236 1237 static void 1238 ft_recompute_scaled_metrics( FT_Face face, 1239 FT_Size_Metrics* metrics ) 1240 { 1241 /* Compute root ascender, descender, test height, and max_advance */ 1242 1243 metrics->ascender = ( FT_MulFix( face->ascender, 1244 metrics->y_scale ) + 32 ) & -64; 1245 1246 metrics->descender = ( FT_MulFix( face->descender, 1247 metrics->y_scale ) + 32 ) & -64; 1248 1249 metrics->height = ( FT_MulFix( face->height, 1250 metrics->y_scale ) + 32 ) & -64; 1251 1252 metrics->max_advance = ( FT_MulFix( face->max_advance_width, 1253 metrics->x_scale ) + 32 ) & -64; 1254 } 1255 1256 1257 /* documentation is in freetype.h */ 1258 1259 FT_EXPORT_DEF( FT_Error ) 1260 FT_Set_Char_Size( FT_Face face, 1261 FT_F26Dot6 char_width, 1262 FT_F26Dot6 char_height, 1263 FT_UInt horz_resolution, 1264 FT_UInt vert_resolution ) 1265 { 1266 FT_Error error = FT_Err_Ok; 1267 FT_Driver driver; 1268 FT_Driver_Class clazz; 1269 FT_Size_Metrics* metrics; 1270 FT_Long dim_x, dim_y; 1271 1272 1273 if ( !face || !face->size || !face->driver ) 1274 return FT_Err_Invalid_Face_Handle; 1275 1276 driver = face->driver; 1277 metrics = &face->size->metrics; 1278 1279 if ( !char_width ) 1280 char_width = char_height; 1281 1282 else if ( !char_height ) 1283 char_height = char_width; 1284 1285 if ( !horz_resolution ) 1286 horz_resolution = 72; 1287 1288 if ( !vert_resolution ) 1289 vert_resolution = 72; 1290 1291 driver = face->driver; 1292 clazz = driver->clazz; 1293 1294 /* default processing -- this can be overridden by the driver */ 1295 if ( char_width < 1 * 64 ) 1296 char_width = 1 * 64; 1297 if ( char_height < 1 * 64 ) 1298 char_height = 1 * 64; 1299 1300 /* Compute pixel sizes in 26.6 units */ 1301 dim_x = ( ( ( char_width * horz_resolution ) / 72 ) + 32 ) & -64; 1302 dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64; 1303 1304 metrics->x_ppem = (FT_UShort)( dim_x >> 6 ); 1305 metrics->y_ppem = (FT_UShort)( dim_y >> 6 ); 1306 1307 metrics->x_scale = 0x10000L; 1308 metrics->y_scale = 0x10000L; 1309 1310 if ( face->face_flags & FT_FACE_FLAG_SCALABLE ) 1311 { 1312 metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM ); 1313 metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM ); 1314 1315 ft_recompute_scaled_metrics( face, metrics ); 1316 } 1317 1318 if ( clazz->set_char_sizes ) 1319 error = clazz->set_char_sizes( face->size, 1320 char_width, 1321 char_height, 1322 horz_resolution, 1323 vert_resolution ); 1324 return error; 1325 } 1326 1327 1328 /* documentation is in freetype.h */ 1329 1330 FT_EXPORT_DEF( FT_Error ) 1331 FT_Set_Pixel_Sizes( FT_Face face, 1332 FT_UInt pixel_width, 1333 FT_UInt pixel_height ) 1334 { 1335 FT_Error error = FT_Err_Ok; 1336 FT_Driver driver; 1337 FT_Driver_Class clazz; 1338 FT_Size_Metrics* metrics = &face->size->metrics; 1339 1340 1341 if ( !face || !face->size || !face->driver ) 1342 return FT_Err_Invalid_Face_Handle; 1343 1344 driver = face->driver; 1345 clazz = driver->clazz; 1346 1347 /* default processing -- this can be overridden by the driver */ 1348 if ( pixel_width == 0 ) 1349 pixel_width = pixel_height; 1350 1351 else if ( pixel_height == 0 ) 1352 pixel_height = pixel_width; 1353 1354 if ( pixel_width < 1 ) 1355 pixel_width = 1; 1356 if ( pixel_height < 1 ) 1357 pixel_height = 1; 1358 1359 metrics->x_ppem = (FT_UShort)pixel_width; 1360 metrics->y_ppem = (FT_UShort)pixel_height; 1361 1362 if ( face->face_flags & FT_FACE_FLAG_SCALABLE ) 1363 { 1364 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, 1365 face->units_per_EM ); 1366 1367 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, 1368 face->units_per_EM ); 1369 1370 ft_recompute_scaled_metrics( face, metrics ); 1371 } 1372 1373 if ( clazz->set_pixel_sizes ) 1374 error = clazz->set_pixel_sizes( face->size, 1375 pixel_width, 1376 pixel_height ); 1377 return error; 1378 } 1379 1380 1381 /* documentation is in freetype.h */ 1382 1383 FT_EXPORT_DEF( FT_Error ) 1384 FT_Get_Kerning( FT_Face face, 1385 FT_UInt left_glyph, 1386 FT_UInt right_glyph, 1387 FT_UInt kern_mode, 1388 FT_Vector *akerning ) 1389 { 1390 FT_Error error = FT_Err_Ok; 1391 FT_Driver driver; 1392 1393 1394 if ( !face ) 1395 return FT_Err_Invalid_Face_Handle; 1396 1397 if ( !akerning ) 1398 return FT_Err_Invalid_Argument; 1399 1400 driver = face->driver; 1401 1402 akerning->x = 0; 1403 akerning->y = 0; 1404 1405 if ( driver->clazz->get_kerning ) 1406 { 1407 error = driver->clazz->get_kerning( face, 1408 left_glyph, 1409 right_glyph, 1410 akerning ); 1411 if ( !error ) 1412 { 1413 if ( kern_mode != FT_KERNING_UNSCALED ) 1414 { 1415 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale ); 1416 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale ); 1417 1418 if ( kern_mode != FT_KERNING_UNFITTED ) 1419 { 1420 akerning->x = ( akerning->x + 32 ) & -64; 1421 akerning->y = ( akerning->y + 32 ) & -64; 1422 } 1423 } 1424 } 1425 } 1426 1427 return error; 1428 } 1429 1430 1431 /* documentation is in freetype.h */ 1432 1433 FT_EXPORT_DEF( FT_Error ) 1434 FT_Select_Charmap( FT_Face face, 1435 FT_Encoding encoding ) 1436 { 1437 FT_CharMap* cur; 1438 FT_CharMap* limit; 1439 1440 1441 if ( !face ) 1442 return FT_Err_Invalid_Face_Handle; 1443 1444 cur = face->charmaps; 1445 if ( !cur ) 1446 return FT_Err_Invalid_CharMap_Handle; 1447 1448 limit = cur + face->num_charmaps; 1449 1450 for ( ; cur < limit; cur++ ) 1451 { 1452 if ( cur[0]->encoding == encoding ) 1453 { 1454 face->charmap = cur[0]; 1455 return 0; 1456 } 1457 } 1458 1459 return FT_Err_Invalid_Argument; 1460 } 1461 1462 1463 /* documentation is in freetype.h */ 1464 1465 FT_EXPORT_DEF( FT_Error ) 1466 FT_Set_Charmap( FT_Face face, 1467 FT_CharMap charmap ) 1468 { 1469 FT_CharMap* cur; 1470 FT_CharMap* limit; 1471 1472 1473 if ( !face ) 1474 return FT_Err_Invalid_Face_Handle; 1475 1476 cur = face->charmaps; 1477 if ( !cur ) 1478 return FT_Err_Invalid_CharMap_Handle; 1479 1480 limit = cur + face->num_charmaps; 1481 1482 for ( ; cur < limit; cur++ ) 1483 { 1484 if ( cur[0] == charmap ) 1485 { 1486 face->charmap = cur[0]; 1487 return 0; 1488 } 1489 } 1490 return FT_Err_Invalid_Argument; 1491 } 1492 1493 1494 FT_BASE_DEF( void ) 1495 FT_CMap_Done( FT_CMap cmap ) 1496 { 1497 if ( cmap ) 1498 { 1499 FT_CMap_Class clazz = cmap->clazz; 1500 FT_Face face = cmap->charmap.face; 1501 FT_Memory memory = FT_FACE_MEMORY(face); 1502 1503 1504 if ( clazz->done ) 1505 clazz->done( cmap ); 1506 1507 FT_FREE( cmap ); 1508 } 1509 } 1510 1511 1512 FT_BASE_DEF( FT_Error ) 1513 FT_CMap_New( FT_CMap_Class clazz, 1514 FT_Pointer init_data, 1515 FT_CharMap charmap, 1516 FT_CMap *acmap ) 1517 { 1518 FT_Error error = 0; 1519 FT_Face face; 1520 FT_Memory memory; 1521 FT_CMap cmap; 1522 1523 1524 if ( clazz == NULL || charmap == NULL || charmap->face == NULL ) 1525 return FT_Err_Invalid_Argument; 1526 1527 face = charmap->face; 1528 memory = FT_FACE_MEMORY(face); 1529 1530 if ( !FT_ALLOC( cmap, clazz->size ) ) 1531 { 1532 cmap->charmap = *charmap; 1533 cmap->clazz = clazz; 1534 1535 if ( clazz->init ) 1536 { 1537 error = clazz->init( cmap, init_data ); 1538 if ( error ) 1539 goto Fail; 1540 } 1541 1542 /* add it to our list of charmaps */ 1543 if ( FT_RENEW_ARRAY( face->charmaps, 1544 face->num_charmaps, 1545 face->num_charmaps+1 ) ) 1546 goto Fail; 1547 1548 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap; 1549 } 1550 1551 Exit: 1552 if ( acmap ) 1553 *acmap = cmap; 1554 1555 return error; 1556 1557 Fail: 1558 FT_CMap_Done( cmap ); 1559 cmap = NULL; 1560 goto Exit; 1561 } 1562 1563 1564 /* documentation is in freetype.h */ 1565 1566 FT_EXPORT_DEF( FT_UInt ) 1567 FT_Get_Char_Index( FT_Face face, 1568 FT_ULong charcode ) 1569 { 1570 FT_UInt result = 0; 1571 1572 1573 if ( face && face->charmap ) 1574 { 1575 FT_CMap cmap = FT_CMAP( face->charmap ); 1576 1577 1578 result = cmap->clazz->char_index( cmap, charcode ); 1579 } 1580 return result; 1581 } 1582 1583 1584 1585 /* documentation is in freetype.h */ 1586 1587 FT_EXPORT_DEF( FT_ULong ) 1588 FT_Get_First_Char( FT_Face face, 1589 FT_UInt *agindex ) 1590 { 1591 FT_ULong result = 0; 1592 FT_UInt gindex = 0; 1593 1594 1595 if ( face && face->charmap ) 1596 { 1597 gindex = FT_Get_Char_Index( face, 0 ); 1598 if ( gindex == 0 ) 1599 result = FT_Get_Next_Char( face, 0, &gindex ); 1600 } 1601 1602 if ( agindex ) 1603 *agindex = gindex; 1604 1605 return result; 1606 } 1607 1608 /* documentation is in freetype.h */ 1609 1610 1611 FT_EXPORT_DEF( FT_ULong ) 1612 FT_Get_Next_Char( FT_Face face, 1613 FT_ULong charcode, 1614 FT_UInt *agindex ) 1615 { 1616 FT_ULong result = 0; 1617 FT_UInt gindex = 0; 1618 1619 1620 if ( face && face->charmap ) 1621 { 1622 FT_UInt32 code = (FT_UInt32)charcode; 1623 FT_CMap cmap = FT_CMAP( face->charmap ); 1624 1625 1626 gindex = cmap->clazz->char_next( cmap, &code ); 1627 result = ( gindex == 0 ) ? 0 : code; 1628 } 1629 1630 if ( agindex ) 1631 *agindex = gindex; 1632 1633 return result; 1634 } 1635 1636 1637 1638 /* documentation is in freetype.h */ 1639 1640 FT_EXPORT_DEF( FT_UInt ) 1641 FT_Get_Name_Index( FT_Face face, 1642 FT_String* glyph_name ) 1643 { 1644 FT_UInt result = 0; 1645 1646 1647 if ( face && FT_HAS_GLYPH_NAMES( face ) ) 1648 { 1649 /* now, lookup for glyph name */ 1650 FT_Driver driver = face->driver; 1651 FT_Module_Class* clazz = FT_MODULE_CLASS( driver ); 1652 1653 1654 if ( clazz->get_interface ) 1655 { 1656 FT_Face_GetGlyphNameIndexFunc requester; 1657 1658 1659 requester = (FT_Face_GetGlyphNameIndexFunc)clazz->get_interface( 1660 FT_MODULE( driver ), "name_index" ); 1661 if ( requester ) 1662 result = requester( face, glyph_name ); 1663 } 1664 } 1665 1666 return result; 1667 } 1668 1669 1670 /* documentation is in freetype.h */ 1671 1672 FT_EXPORT_DEF( FT_Error ) 1673 FT_Get_Glyph_Name( FT_Face face, 1674 FT_UInt glyph_index, 1675 FT_Pointer buffer, 1676 FT_UInt buffer_max ) 1677 { 1678 FT_Error error = FT_Err_Invalid_Argument; 1679 1680 1681 /* clean up buffer */ 1682 if ( buffer && buffer_max > 0 ) 1683 ((FT_Byte*)buffer)[0] = 0; 1684 1685 if ( face && 1686 glyph_index <= (FT_UInt)face->num_glyphs && 1687 FT_HAS_GLYPH_NAMES( face ) ) 1688 { 1689 /* now, lookup for glyph name */ 1690 FT_Driver driver = face->driver; 1691 FT_Module_Class* clazz = FT_MODULE_CLASS( driver ); 1692 1693 1694 if ( clazz->get_interface ) 1695 { 1696 FT_Face_GetGlyphNameFunc requester; 1697 1698 1699 requester = (FT_Face_GetGlyphNameFunc)clazz->get_interface( 1700 FT_MODULE( driver ), "glyph_name" ); 1701 if ( requester ) 1702 error = requester( face, glyph_index, buffer, buffer_max ); 1703 } 1704 } 1705 1706 return error; 1707 } 1708 1709 1710 /* documentation is in freetype.h */ 1711 1712 FT_EXPORT_DEF( const char* ) 1713 FT_Get_Postscript_Name( FT_Face face ) 1714 { 1715 const char* result = NULL; 1716 1717 1718 if ( !face ) 1719 goto Exit; 1720 1721 result = face->internal->postscript_name; 1722 if ( !result ) 1723 { 1724 /* now, look up glyph name */ 1725 FT_Driver driver = face->driver; 1726 FT_Module_Class* clazz = FT_MODULE_CLASS( driver ); 1727 1728 1729 if ( clazz->get_interface ) 1730 { 1731 FT_Face_GetPostscriptNameFunc requester; 1732 1733 1734 requester = (FT_Face_GetPostscriptNameFunc)clazz->get_interface( 1735 FT_MODULE( driver ), "postscript_name" ); 1736 if ( requester ) 1737 result = requester( face ); 1738 } 1739 } 1740 Exit: 1741 return result; 1742 } 1743 1744 1745 /* documentation is in tttables.h */ 1746 1747 FT_EXPORT_DEF( void* ) 1748 FT_Get_Sfnt_Table( FT_Face face, 1749 FT_Sfnt_Tag tag ) 1750 { 1751 void* table = 0; 1752 FT_Get_Sfnt_Table_Func func; 1753 FT_Driver driver; 1754 1755 1756 if ( !face || !FT_IS_SFNT( face ) ) 1757 goto Exit; 1758 1759 driver = face->driver; 1760 func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface( 1761 FT_MODULE( driver ), "get_sfnt" ); 1762 if ( func ) 1763 table = func( face, tag ); 1764 1765 Exit: 1766 return table; 1767 } 1768 1769 1770 FT_EXPORT_DEF( FT_Error ) 1771 FT_Activate_Size( FT_Size size ) 1772 { 1773 FT_Face face; 1774 1775 1776 if ( size == NULL ) 1777 return FT_Err_Bad_Argument; 1778 1779 face = size->face; 1780 if ( face == NULL || face->driver == NULL ) 1781 return FT_Err_Bad_Argument; 1782 1783 /* we don't need anything more complex than that; all size objects */ 1784 /* are already listed by the face */ 1785 face->size = size; 1786 1787 return FT_Err_Ok; 1788 } 1789 1790 1791 /*************************************************************************/ 1792 /*************************************************************************/ 1793 /*************************************************************************/ 1794 /**** ****/ 1795 /**** ****/ 1796 /**** R E N D E R E R S ****/ 1797 /**** ****/ 1798 /**** ****/ 1799 /*************************************************************************/ 1800 /*************************************************************************/ 1801 /*************************************************************************/ 1802 1803 /* lookup a renderer by glyph format in the library's list */ 1804 FT_BASE_DEF( FT_Renderer ) 1805 FT_Lookup_Renderer( FT_Library library, 1806 FT_Glyph_Format format, 1807 FT_ListNode* node ) 1808 { 1809 FT_ListNode cur; 1810 FT_Renderer result = 0; 1811 1812 1813 if ( !library ) 1814 goto Exit; 1815 1816 cur = library->renderers.head; 1817 1818 if ( node ) 1819 { 1820 if ( *node ) 1821 cur = (*node)->next; 1822 *node = 0; 1823 } 1824 1825 while ( cur ) 1826 { 1827 FT_Renderer renderer = FT_RENDERER( cur->data ); 1828 1829 1830 if ( renderer->glyph_format == format ) 1831 { 1832 if ( node ) 1833 *node = cur; 1834 1835 result = renderer; 1836 break; 1837 } 1838 cur = cur->next; 1839 } 1840 1841 Exit: 1842 return result; 1843 } 1844 1845 1846 static FT_Renderer 1847 ft_lookup_glyph_renderer( FT_GlyphSlot slot ) 1848 { 1849 FT_Face face = slot->face; 1850 FT_Library library = FT_FACE_LIBRARY( face ); 1851 FT_Renderer result = library->cur_renderer; 1852 1853 1854 if ( !result || result->glyph_format != slot->format ) 1855 result = FT_Lookup_Renderer( library, slot->format, 0 ); 1856 1857 return result; 1858 } 1859 1860 1861 static void 1862 ft_set_current_renderer( FT_Library library ) 1863 { 1864 FT_Renderer renderer; 1865 1866 1867 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 ); 1868 library->cur_renderer = renderer; 1869 } 1870 1871 1872 static FT_Error 1873 ft_add_renderer( FT_Module module ) 1874 { 1875 FT_Library library = module->library; 1876 FT_Memory memory = library->memory; 1877 FT_Error error; 1878 FT_ListNode node; 1879 1880 1881 if ( FT_NEW( node ) ) 1882 goto Exit; 1883 1884 { 1885 FT_Renderer render = FT_RENDERER( module ); 1886 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz; 1887 1888 1889 render->clazz = clazz; 1890 render->glyph_format = clazz->glyph_format; 1891 1892 /* allocate raster object if needed */ 1893 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && 1894 clazz->raster_class->raster_new ) 1895 { 1896 error = clazz->raster_class->raster_new( memory, &render->raster ); 1897 if ( error ) 1898 goto Fail; 1899 1900 render->raster_render = clazz->raster_class->raster_render; 1901 render->render = clazz->render_glyph; 1902 } 1903 1904 /* add to list */ 1905 node->data = module; 1906 FT_List_Add( &library->renderers, node ); 1907 1908 ft_set_current_renderer( library ); 1909 } 1910 1911 Fail: 1912 if ( error ) 1913 FT_FREE( node ); 1914 1915 Exit: 1916 return error; 1917 } 1918 1919 1920 static void 1921 ft_remove_renderer( FT_Module module ) 1922 { 1923 FT_Library library = module->library; 1924 FT_Memory memory = library->memory; 1925 FT_ListNode node; 1926 1927 1928 node = FT_List_Find( &library->renderers, module ); 1929 if ( node ) 1930 { 1931 FT_Renderer render = FT_RENDERER( module ); 1932 1933 1934 /* release raster object, if any */ 1935 if ( render->raster ) 1936 render->clazz->raster_class->raster_done( render->raster ); 1937 1938 /* remove from list */ 1939 FT_List_Remove( &library->renderers, node ); 1940 FT_FREE( node ); 1941 1942 ft_set_current_renderer( library ); 1943 } 1944 } 1945 1946 1947 /* documentation is in ftrender.h */ 1948 1949 FT_EXPORT_DEF( FT_Renderer ) 1950 FT_Get_Renderer( FT_Library library, 1951 FT_Glyph_Format format ) 1952 { 1953 /* test for valid `library' delayed to FT_Lookup_Renderer() */ 1954 1955 return FT_Lookup_Renderer( library, format, 0 ); 1956 } 1957 1958 1959 /* documentation is in ftrender.h */ 1960 1961 FT_EXPORT_DEF( FT_Error ) 1962 FT_Set_Renderer( FT_Library library, 1963 FT_Renderer renderer, 1964 FT_UInt num_params, 1965 FT_Parameter* parameters ) 1966 { 1967 FT_ListNode node; 1968 FT_Error error = FT_Err_Ok; 1969 1970 1971 if ( !library ) 1972 return FT_Err_Invalid_Library_Handle; 1973 1974 if ( !renderer ) 1975 return FT_Err_Invalid_Argument; 1976 1977 node = FT_List_Find( &library->renderers, renderer ); 1978 if ( !node ) 1979 { 1980 error = FT_Err_Invalid_Argument; 1981 goto Exit; 1982 } 1983 1984 FT_List_Up( &library->renderers, node ); 1985 1986 if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE ) 1987 library->cur_renderer = renderer; 1988 1989 if ( num_params > 0 ) 1990 { 1991 FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode; 1992 1993 1994 for ( ; num_params > 0; num_params-- ) 1995 { 1996 error = set_mode( renderer, parameters->tag, parameters->data ); 1997 if ( error ) 1998 break; 1999 } 2000 } 2001 2002 Exit: 2003 return error; 2004 } 2005 2006 2007 FT_BASE_DEF( FT_Error ) 2008 FT_Render_Glyph_Internal( FT_Library library, 2009 FT_GlyphSlot slot, 2010 FT_Render_Mode render_mode ) 2011 { 2012 FT_Error error = FT_Err_Ok; 2013 FT_Renderer renderer; 2014 2015 2016 /* if it is already a bitmap, no need to do anything */ 2017 switch ( slot->format ) 2018 { 2019 case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */ 2020 break; 2021 2022 default: 2023 { 2024 FT_ListNode node = 0; 2025 FT_Bool update = 0; 2026 2027 2028 /* small shortcut for the very common case */ 2029 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) 2030 { 2031 renderer = library->cur_renderer; 2032 node = library->renderers.head; 2033 } 2034 else 2035 renderer = FT_Lookup_Renderer( library, slot->format, &node ); 2036 2037 error = FT_Err_Unimplemented_Feature; 2038 while ( renderer ) 2039 { 2040 error = renderer->render( renderer, slot, render_mode, NULL ); 2041 if ( !error || 2042 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph ) 2043 break; 2044 2045 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ 2046 /* is unsupported by the current renderer for this glyph image */ 2047 /* format. */ 2048 2049 /* now, look for another renderer that supports the same */ 2050 /* format. */ 2051 renderer = FT_Lookup_Renderer( library, slot->format, &node ); 2052 update = 1; 2053 } 2054 2055 /* if we changed the current renderer for the glyph image format */ 2056 /* we need to select it as the next current one */ 2057 if ( !error && update && renderer ) 2058 FT_Set_Renderer( library, renderer, 0, 0 ); 2059 } 2060 } 2061 2062 return error; 2063 } 2064 2065 2066 /* documentation is in freetype.h */ 2067 2068 FT_EXPORT_DEF( FT_Error ) 2069 FT_Render_Glyph( FT_GlyphSlot slot, 2070 FT_Render_Mode render_mode ) 2071 { 2072 FT_Library library; 2073 2074 2075 if ( !slot ) 2076 return FT_Err_Invalid_Argument; 2077 2078 library = FT_FACE_LIBRARY( slot->face ); 2079 2080 return FT_Render_Glyph_Internal( library, slot, render_mode ); 2081 } 2082 2083 2084 /*************************************************************************/ 2085 /*************************************************************************/ 2086 /*************************************************************************/ 2087 /**** ****/ 2088 /**** ****/ 2089 /**** M O D U L E S ****/ 2090 /**** ****/ 2091 /**** ****/ 2092 /*************************************************************************/ 2093 /*************************************************************************/ 2094 /*************************************************************************/ 2095 2096 2097 /*************************************************************************/ 2098 /* */ 2099 /* <Function> */ 2100 /* Destroy_Module */ 2101 /* */ 2102 /* <Description> */ 2103 /* Destroys a given module object. For drivers, this also destroys */ 2104 /* all child faces. */ 2105 /* */ 2106 /* <InOut> */ 2107 /* module :: A handle to the target driver object. */ 2108 /* */ 2109 /* <Note> */ 2110 /* The driver _must_ be LOCKED! */ 2111 /* */ 2112 static void 2113 Destroy_Module( FT_Module module ) 2114 { 2115 FT_Memory memory = module->memory; 2116 FT_Module_Class* clazz = module->clazz; 2117 FT_Library library = module->library; 2118 2119 2120 /* finalize client-data - before anything else */ 2121 if ( module->generic.finalizer ) 2122 module->generic.finalizer( module ); 2123 2124 if ( library && library->auto_hinter == module ) 2125 library->auto_hinter = 0; 2126 2127 /* if the module is a renderer */ 2128 if ( FT_MODULE_IS_RENDERER( module ) ) 2129 ft_remove_renderer( module ); 2130 2131 /* if the module is a font driver, add some steps */ 2132 if ( FT_MODULE_IS_DRIVER( module ) ) 2133 Destroy_Driver( FT_DRIVER( module ) ); 2134 2135 /* finalize the module object */ 2136 if ( clazz->module_done ) 2137 clazz->module_done( module ); 2138 2139 /* discard it */ 2140 FT_FREE( module ); 2141 } 2142 2143 2144 /* documentation is in ftmodule.h */ 2145 2146 FT_EXPORT_DEF( FT_Error ) 2147 FT_Add_Module( FT_Library library, 2148 const FT_Module_Class* clazz ) 2149 { 2150 FT_Error error; 2151 FT_Memory memory; 2152 FT_Module module; 2153 FT_UInt nn; 2154 2155 2156 #define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \ 2157 FREETYPE_MINOR ) 2158 2159 if ( !library ) 2160 return FT_Err_Invalid_Library_Handle; 2161 2162 if ( !clazz ) 2163 return FT_Err_Invalid_Argument; 2164 2165 /* check freetype version */ 2166 if ( clazz->module_requires > FREETYPE_VER_FIXED ) 2167 return FT_Err_Invalid_Version; 2168 2169 /* look for a module with the same name in the library's table */ 2170 for ( nn = 0; nn < library->num_modules; nn++ ) 2171 { 2172 module = library->modules[nn]; 2173 if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 ) 2174 { 2175 /* this installed module has the same name, compare their versions */ 2176 if ( clazz->module_version <= module->clazz->module_version ) 2177 return FT_Err_Lower_Module_Version; 2178 2179 /* remove the module from our list, then exit the loop to replace */ 2180 /* it by our new version.. */ 2181 FT_Remove_Module( library, module ); 2182 break; 2183 } 2184 } 2185 2186 memory = library->memory; 2187 error = FT_Err_Ok; 2188 2189 if ( library->num_modules >= FT_MAX_MODULES ) 2190 { 2191 error = FT_Err_Too_Many_Drivers; 2192 goto Exit; 2193 } 2194 2195 /* allocate module object */ 2196 if ( FT_ALLOC( module, clazz->module_size ) ) 2197 goto Exit; 2198 2199 /* base initialization */ 2200 module->library = library; 2201 module->memory = memory; 2202 module->clazz = (FT_Module_Class*)clazz; 2203 2204 /* check whether the module is a renderer - this must be performed */ 2205 /* before the normal module initialization */ 2206 if ( FT_MODULE_IS_RENDERER( module ) ) 2207 { 2208 /* add to the renderers list */ 2209 error = ft_add_renderer( module ); 2210 if ( error ) 2211 goto Fail; 2212 } 2213 2214 /* is the module a auto-hinter? */ 2215 if ( FT_MODULE_IS_HINTER( module ) ) 2216 library->auto_hinter = module; 2217 2218 /* if the module is a font driver */ 2219 if ( FT_MODULE_IS_DRIVER( module ) ) 2220 { 2221 /* allocate glyph loader if needed */ 2222 FT_Driver driver = FT_DRIVER( module ); 2223 2224 2225 driver->clazz = (FT_Driver_Class)module->clazz; 2226 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 2227 { 2228 error = FT_GlyphLoader_New( memory, &driver->glyph_loader ); 2229 if ( error ) 2230 goto Fail; 2231 } 2232 } 2233 2234 if ( clazz->module_init ) 2235 { 2236 error = clazz->module_init( module ); 2237 if ( error ) 2238 goto Fail; 2239 } 2240 2241 /* add module to the library's table */ 2242 library->modules[library->num_modules++] = module; 2243 2244 Exit: 2245 return error; 2246 2247 Fail: 2248 if ( FT_MODULE_IS_DRIVER( module ) ) 2249 { 2250 FT_Driver driver = FT_DRIVER( module ); 2251 2252 2253 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 2254 FT_GlyphLoader_Done( driver->glyph_loader ); 2255 } 2256 2257 if ( FT_MODULE_IS_RENDERER( module ) ) 2258 { 2259 FT_Renderer renderer = FT_RENDERER( module ); 2260 2261 2262 if ( renderer->raster ) 2263 renderer->clazz->raster_class->raster_done( renderer->raster ); 2264 } 2265 2266 FT_FREE( module ); 2267 goto Exit; 2268 } 2269 2270 2271 /* documentation is in ftmodule.h */ 2272 2273 FT_EXPORT_DEF( FT_Module ) 2274 FT_Get_Module( FT_Library library, 2275 const char* module_name ) 2276 { 2277 FT_Module result = 0; 2278 FT_Module* cur; 2279 FT_Module* limit; 2280 2281 2282 if ( !library || !module_name ) 2283 return result; 2284 2285 cur = library->modules; 2286 limit = cur + library->num_modules; 2287 2288 for ( ; cur < limit; cur++ ) 2289 if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 ) 2290 { 2291 result = cur[0]; 2292 break; 2293 } 2294 2295 return result; 2296 } 2297 2298 2299 /* documentation is in ftobjs.h */ 2300 2301 FT_BASE_DEF( const void* ) 2302 FT_Get_Module_Interface( FT_Library library, 2303 const char* mod_name ) 2304 { 2305 FT_Module module; 2306 2307 2308 /* test for valid `library' delayed to FT_Get_Module() */ 2309 2310 module = FT_Get_Module( library, mod_name ); 2311 2312 return module ? module->clazz->module_interface : 0; 2313 } 2314 2315 2316 /* documentation is in ftmodule.h */ 2317 2318 FT_EXPORT_DEF( FT_Error ) 2319 FT_Remove_Module( FT_Library library, 2320 FT_Module module ) 2321 { 2322 /* try to find the module from the table, then remove it from there */ 2323 2324 if ( !library ) 2325 return FT_Err_Invalid_Library_Handle; 2326 2327 if ( module ) 2328 { 2329 FT_Module* cur = library->modules; 2330 FT_Module* limit = cur + library->num_modules; 2331 2332 2333 for ( ; cur < limit; cur++ ) 2334 { 2335 if ( cur[0] == module ) 2336 { 2337 /* remove it from the table */ 2338 library->num_modules--; 2339 limit--; 2340 while ( cur < limit ) 2341 { 2342 cur[0] = cur[1]; 2343 cur++; 2344 } 2345 limit[0] = 0; 2346 2347 /* destroy the module */ 2348 Destroy_Module( module ); 2349 2350 return FT_Err_Ok; 2351 } 2352 } 2353 } 2354 return FT_Err_Invalid_Driver_Handle; 2355 } 2356 2357 2358 /*************************************************************************/ 2359 /*************************************************************************/ 2360 /*************************************************************************/ 2361 /**** ****/ 2362 /**** ****/ 2363 /**** L I B R A R Y ****/ 2364 /**** ****/ 2365 /**** ****/ 2366 /*************************************************************************/ 2367 /*************************************************************************/ 2368 /*************************************************************************/ 2369 2370 2371 /* documentation is in ftmodule.h */ 2372 2373 FT_EXPORT_DEF( FT_Error ) 2374 FT_New_Library( FT_Memory memory, 2375 FT_Library *alibrary ) 2376 { 2377 FT_Library library = 0; 2378 FT_Error error; 2379 2380 2381 if ( !memory ) 2382 return FT_Err_Invalid_Argument; 2383 2384 #ifdef FT_DEBUG_LEVEL_ERROR 2385 /* init debugging support */ 2386 ft_debug_init(); 2387 #endif 2388 2389 /* first of all, allocate the library object */ 2390 if ( FT_NEW( library ) ) 2391 return error; 2392 2393 library->memory = memory; 2394 2395 /* allocate the render pool */ 2396 library->raster_pool_size = FT_RENDER_POOL_SIZE; 2397 if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) ) 2398 goto Fail; 2399 2400 /* That's ok now */ 2401 *alibrary = library; 2402 2403 return FT_Err_Ok; 2404 2405 Fail: 2406 FT_FREE( library ); 2407 return error; 2408 } 2409 2410 2411 /* documentation is in freetype.h */ 2412 2413 FT_EXPORT_DEF( void ) 2414 FT_Library_Version( FT_Library library, 2415 FT_Int *amajor, 2416 FT_Int *aminor, 2417 FT_Int *apatch ) 2418 { 2419 FT_Int major = 0; 2420 FT_Int minor = 0; 2421 FT_Int patch = 0; 2422 2423 2424 if ( library ) 2425 { 2426 major = library->version_major; 2427 minor = library->version_minor; 2428 patch = library->version_patch; 2429 } 2430 2431 if ( amajor ) 2432 *amajor = major; 2433 2434 if ( aminor ) 2435 *aminor = minor; 2436 2437 if ( apatch ) 2438 *apatch = patch; 2439 } 2440 2441 2442 /* documentation is in ftmodule.h */ 2443 2444 FT_EXPORT_DEF( FT_Error ) 2445 FT_Done_Library( FT_Library library ) 2446 { 2447 FT_Memory memory; 2448 2449 2450 if ( !library ) 2451 return FT_Err_Invalid_Library_Handle; 2452 2453 memory = library->memory; 2454 2455 /* Discard client-data */ 2456 if ( library->generic.finalizer ) 2457 library->generic.finalizer( library ); 2458 2459 /* Close all modules in the library */ 2460 #if 1 2461 while ( library->num_modules > 0 ) 2462 FT_Remove_Module( library, library->modules[0] ); 2463 #else 2464 { 2465 FT_UInt n; 2466 2467 2468 for ( n = 0; n < library->num_modules; n++ ) 2469 { 2470 FT_Module module = library->modules[n]; 2471 2472 2473 if ( module ) 2474 { 2475 Destroy_Module( module ); 2476 library->modules[n] = 0; 2477 } 2478 } 2479 } 2480 #endif 2481 2482 /* Destroy raster objects */ 2483 FT_FREE( library->raster_pool ); 2484 library->raster_pool_size = 0; 2485 2486 FT_FREE( library ); 2487 return FT_Err_Ok; 2488 } 2489 2490 2491 /* documentation is in ftmodule.h */ 2492 2493 FT_EXPORT_DEF( void ) 2494 FT_Set_Debug_Hook( FT_Library library, 2495 FT_UInt hook_index, 2496 FT_DebugHook_Func debug_hook ) 2497 { 2498 if ( library && debug_hook && 2499 hook_index < 2500 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) ) 2501 library->debug_hooks[hook_index] = debug_hook; 2502 } 2503 2504 2505 /* END */ 2506