1 /***************************************************************************/ 2 /* */ 3 /* ftobjs.c */ 4 /* */ 5 /* The FreeType private base classes (body). */ 6 /* */ 7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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_VALIDATE_H 23 #include FT_INTERNAL_OBJECTS_H 24 #include FT_INTERNAL_DEBUG_H 25 #include FT_INTERNAL_RFORK_H 26 #include FT_INTERNAL_STREAM_H 27 #include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */ 28 #include FT_TRUETYPE_TABLES_H 29 #include FT_TRUETYPE_TAGS_H 30 #include FT_TRUETYPE_IDS_H 31 #include FT_OUTLINE_H 32 33 #include FT_SERVICE_SFNT_H 34 #include FT_SERVICE_POSTSCRIPT_NAME_H 35 #include FT_SERVICE_GLYPH_DICT_H 36 #include FT_SERVICE_TT_CMAP_H 37 #include FT_SERVICE_KERNING_H 38 #include FT_SERVICE_TRUETYPE_ENGINE_H 39 40 #include "ftbase.h" 41 42 #define GRID_FIT_METRICS 43 44 45 FT_BASE_DEF( FT_Pointer ) ft_service_list_lookup(FT_ServiceDesc service_descriptors,const char * service_id)46 ft_service_list_lookup( FT_ServiceDesc service_descriptors, 47 const char* service_id ) 48 { 49 FT_Pointer result = NULL; 50 FT_ServiceDesc desc = service_descriptors; 51 52 53 if ( desc && service_id ) 54 { 55 for ( ; desc->serv_id != NULL; desc++ ) 56 { 57 if ( ft_strcmp( desc->serv_id, service_id ) == 0 ) 58 { 59 result = (FT_Pointer)desc->serv_data; 60 break; 61 } 62 } 63 } 64 65 return result; 66 } 67 68 69 FT_BASE_DEF( void ) ft_validator_init(FT_Validator valid,const FT_Byte * base,const FT_Byte * limit,FT_ValidationLevel level)70 ft_validator_init( FT_Validator valid, 71 const FT_Byte* base, 72 const FT_Byte* limit, 73 FT_ValidationLevel level ) 74 { 75 valid->base = base; 76 valid->limit = limit; 77 valid->level = level; 78 valid->error = FT_Err_Ok; 79 } 80 81 82 FT_BASE_DEF( FT_Int ) ft_validator_run(FT_Validator valid)83 ft_validator_run( FT_Validator valid ) 84 { 85 /* This function doesn't work! None should call it. */ 86 FT_UNUSED( valid ); 87 88 return -1; 89 } 90 91 92 FT_BASE_DEF( void ) ft_validator_error(FT_Validator valid,FT_Error error)93 ft_validator_error( FT_Validator valid, 94 FT_Error error ) 95 { 96 /* since the cast below also disables the compiler's */ 97 /* type check, we introduce a dummy variable, which */ 98 /* will be optimized away */ 99 volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer; 100 101 102 valid->error = error; 103 104 /* throw away volatileness; use `jump_buffer' or the */ 105 /* compiler may warn about an unused local variable */ 106 ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 ); 107 } 108 109 110 /*************************************************************************/ 111 /*************************************************************************/ 112 /*************************************************************************/ 113 /**** ****/ 114 /**** ****/ 115 /**** S T R E A M ****/ 116 /**** ****/ 117 /**** ****/ 118 /*************************************************************************/ 119 /*************************************************************************/ 120 /*************************************************************************/ 121 122 123 /* create a new input stream from an FT_Open_Args structure */ 124 /* */ 125 FT_BASE_DEF( FT_Error ) FT_Stream_New(FT_Library library,const FT_Open_Args * args,FT_Stream * astream)126 FT_Stream_New( FT_Library library, 127 const FT_Open_Args* args, 128 FT_Stream *astream ) 129 { 130 FT_Error error; 131 FT_Memory memory; 132 FT_Stream stream; 133 134 135 *astream = 0; 136 137 if ( !library ) 138 return FT_Err_Invalid_Library_Handle; 139 140 if ( !args ) 141 return FT_Err_Invalid_Argument; 142 143 memory = library->memory; 144 145 if ( FT_NEW( stream ) ) 146 goto Exit; 147 148 stream->memory = memory; 149 150 if ( args->flags & FT_OPEN_MEMORY ) 151 { 152 /* create a memory-based stream */ 153 FT_Stream_OpenMemory( stream, 154 (const FT_Byte*)args->memory_base, 155 args->memory_size ); 156 } 157 else if ( args->flags & FT_OPEN_PATHNAME ) 158 { 159 /* create a normal system stream */ 160 error = FT_Stream_Open( stream, args->pathname ); 161 stream->pathname.pointer = args->pathname; 162 } 163 else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream ) 164 { 165 /* use an existing, user-provided stream */ 166 167 /* in this case, we do not need to allocate a new stream object */ 168 /* since the caller is responsible for closing it himself */ 169 FT_FREE( stream ); 170 stream = args->stream; 171 } 172 else 173 error = FT_Err_Invalid_Argument; 174 175 if ( error ) 176 FT_FREE( stream ); 177 else 178 stream->memory = memory; /* just to be certain */ 179 180 *astream = stream; 181 182 Exit: 183 return error; 184 } 185 186 187 FT_BASE_DEF( void ) FT_Stream_Free(FT_Stream stream,FT_Int external)188 FT_Stream_Free( FT_Stream stream, 189 FT_Int external ) 190 { 191 if ( stream ) 192 { 193 FT_Memory memory = stream->memory; 194 195 196 FT_Stream_Close( stream ); 197 198 if ( !external ) 199 FT_FREE( stream ); 200 } 201 } 202 203 204 /*************************************************************************/ 205 /* */ 206 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 207 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 208 /* messages during execution. */ 209 /* */ 210 #undef FT_COMPONENT 211 #define FT_COMPONENT trace_objs 212 213 214 /*************************************************************************/ 215 /*************************************************************************/ 216 /*************************************************************************/ 217 /**** ****/ 218 /**** ****/ 219 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/ 220 /**** ****/ 221 /**** ****/ 222 /*************************************************************************/ 223 /*************************************************************************/ 224 /*************************************************************************/ 225 226 227 static FT_Error ft_glyphslot_init(FT_GlyphSlot slot)228 ft_glyphslot_init( FT_GlyphSlot slot ) 229 { 230 FT_Driver driver = slot->face->driver; 231 FT_Driver_Class clazz = driver->clazz; 232 FT_Memory memory = driver->root.memory; 233 FT_Error error = FT_Err_Ok; 234 FT_Slot_Internal internal; 235 236 237 slot->library = driver->root.library; 238 239 if ( FT_NEW( internal ) ) 240 goto Exit; 241 242 slot->internal = internal; 243 244 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 245 error = FT_GlyphLoader_New( memory, &internal->loader ); 246 247 if ( !error && clazz->init_slot ) 248 error = clazz->init_slot( slot ); 249 250 Exit: 251 return error; 252 } 253 254 255 FT_BASE_DEF( void ) ft_glyphslot_free_bitmap(FT_GlyphSlot slot)256 ft_glyphslot_free_bitmap( FT_GlyphSlot slot ) 257 { 258 if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) 259 { 260 FT_Memory memory = FT_FACE_MEMORY( slot->face ); 261 262 263 FT_FREE( slot->bitmap.buffer ); 264 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; 265 } 266 else 267 { 268 /* assume that the bitmap buffer was stolen or not */ 269 /* allocated from the heap */ 270 slot->bitmap.buffer = NULL; 271 } 272 } 273 274 275 FT_BASE_DEF( void ) ft_glyphslot_set_bitmap(FT_GlyphSlot slot,FT_Byte * buffer)276 ft_glyphslot_set_bitmap( FT_GlyphSlot slot, 277 FT_Byte* buffer ) 278 { 279 ft_glyphslot_free_bitmap( slot ); 280 281 slot->bitmap.buffer = buffer; 282 283 FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 ); 284 } 285 286 287 FT_BASE_DEF( FT_Error ) ft_glyphslot_alloc_bitmap(FT_GlyphSlot slot,FT_ULong size)288 ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot, 289 FT_ULong size ) 290 { 291 FT_Memory memory = FT_FACE_MEMORY( slot->face ); 292 FT_Error error; 293 294 295 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) 296 FT_FREE( slot->bitmap.buffer ); 297 else 298 slot->internal->flags |= FT_GLYPH_OWN_BITMAP; 299 300 (void)FT_ALLOC( slot->bitmap.buffer, size ); 301 return error; 302 } 303 304 305 static void ft_glyphslot_clear(FT_GlyphSlot slot)306 ft_glyphslot_clear( FT_GlyphSlot slot ) 307 { 308 /* free bitmap if needed */ 309 ft_glyphslot_free_bitmap( slot ); 310 311 /* clear all public fields in the glyph slot */ 312 FT_ZERO( &slot->metrics ); 313 FT_ZERO( &slot->outline ); 314 315 slot->bitmap.width = 0; 316 slot->bitmap.rows = 0; 317 slot->bitmap.pitch = 0; 318 slot->bitmap.pixel_mode = 0; 319 /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */ 320 321 slot->bitmap_left = 0; 322 slot->bitmap_top = 0; 323 slot->num_subglyphs = 0; 324 slot->subglyphs = 0; 325 slot->control_data = 0; 326 slot->control_len = 0; 327 slot->other = 0; 328 slot->format = FT_GLYPH_FORMAT_NONE; 329 330 slot->linearHoriAdvance = 0; 331 slot->linearVertAdvance = 0; 332 slot->lsb_delta = 0; 333 slot->rsb_delta = 0; 334 } 335 336 337 static void ft_glyphslot_done(FT_GlyphSlot slot)338 ft_glyphslot_done( FT_GlyphSlot slot ) 339 { 340 FT_Driver driver = slot->face->driver; 341 FT_Driver_Class clazz = driver->clazz; 342 FT_Memory memory = driver->root.memory; 343 344 345 if ( clazz->done_slot ) 346 clazz->done_slot( slot ); 347 348 /* free bitmap buffer if needed */ 349 ft_glyphslot_free_bitmap( slot ); 350 351 /* free glyph loader */ 352 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 353 { 354 FT_GlyphLoader_Done( slot->internal->loader ); 355 slot->internal->loader = 0; 356 } 357 358 FT_FREE( slot->internal ); 359 } 360 361 362 /* documentation is in ftobjs.h */ 363 364 FT_BASE_DEF( FT_Error ) FT_New_GlyphSlot(FT_Face face,FT_GlyphSlot * aslot)365 FT_New_GlyphSlot( FT_Face face, 366 FT_GlyphSlot *aslot ) 367 { 368 FT_Error error; 369 FT_Driver driver; 370 FT_Driver_Class clazz; 371 FT_Memory memory; 372 FT_GlyphSlot slot; 373 374 375 if ( !face || !face->driver ) 376 return FT_Err_Invalid_Argument; 377 378 driver = face->driver; 379 clazz = driver->clazz; 380 memory = driver->root.memory; 381 382 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" )); 383 if ( !FT_ALLOC( slot, clazz->slot_object_size ) ) 384 { 385 slot->face = face; 386 387 error = ft_glyphslot_init( slot ); 388 if ( error ) 389 { 390 ft_glyphslot_done( slot ); 391 FT_FREE( slot ); 392 goto Exit; 393 } 394 395 slot->next = face->glyph; 396 face->glyph = slot; 397 398 if ( aslot ) 399 *aslot = slot; 400 } 401 else if ( aslot ) 402 *aslot = 0; 403 404 405 Exit: 406 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error )); 407 return error; 408 } 409 410 411 /* documentation is in ftobjs.h */ 412 413 FT_BASE_DEF( void ) FT_Done_GlyphSlot(FT_GlyphSlot slot)414 FT_Done_GlyphSlot( FT_GlyphSlot slot ) 415 { 416 if ( slot ) 417 { 418 FT_Driver driver = slot->face->driver; 419 FT_Memory memory = driver->root.memory; 420 FT_GlyphSlot prev; 421 FT_GlyphSlot cur; 422 423 424 /* Remove slot from its parent face's list */ 425 prev = NULL; 426 cur = slot->face->glyph; 427 428 while ( cur ) 429 { 430 if ( cur == slot ) 431 { 432 if ( !prev ) 433 slot->face->glyph = cur->next; 434 else 435 prev->next = cur->next; 436 437 ft_glyphslot_done( slot ); 438 FT_FREE( slot ); 439 break; 440 } 441 prev = cur; 442 cur = cur->next; 443 } 444 } 445 } 446 447 448 /* documentation is in freetype.h */ 449 450 FT_EXPORT_DEF( void ) FT_Set_Transform(FT_Face face,FT_Matrix * matrix,FT_Vector * delta)451 FT_Set_Transform( FT_Face face, 452 FT_Matrix* matrix, 453 FT_Vector* delta ) 454 { 455 FT_Face_Internal internal; 456 457 458 if ( !face ) 459 return; 460 461 internal = face->internal; 462 463 internal->transform_flags = 0; 464 465 if ( !matrix ) 466 { 467 internal->transform_matrix.xx = 0x10000L; 468 internal->transform_matrix.xy = 0; 469 internal->transform_matrix.yx = 0; 470 internal->transform_matrix.yy = 0x10000L; 471 matrix = &internal->transform_matrix; 472 } 473 else 474 internal->transform_matrix = *matrix; 475 476 /* set transform_flags bit flag 0 if `matrix' isn't the identity */ 477 if ( ( matrix->xy | matrix->yx ) || 478 matrix->xx != 0x10000L || 479 matrix->yy != 0x10000L ) 480 internal->transform_flags |= 1; 481 482 if ( !delta ) 483 { 484 internal->transform_delta.x = 0; 485 internal->transform_delta.y = 0; 486 delta = &internal->transform_delta; 487 } 488 else 489 internal->transform_delta = *delta; 490 491 /* set transform_flags bit flag 1 if `delta' isn't the null vector */ 492 if ( delta->x | delta->y ) 493 internal->transform_flags |= 2; 494 } 495 496 497 static FT_Renderer 498 ft_lookup_glyph_renderer( FT_GlyphSlot slot ); 499 500 501 #ifdef GRID_FIT_METRICS 502 static void ft_glyphslot_grid_fit_metrics(FT_GlyphSlot slot,FT_Bool vertical)503 ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot, 504 FT_Bool vertical ) 505 { 506 FT_Glyph_Metrics* metrics = &slot->metrics; 507 FT_Pos right, bottom; 508 509 510 if ( vertical ) 511 { 512 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX ); 513 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY ); 514 515 right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width ); 516 bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height ); 517 518 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX ); 519 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY ); 520 521 metrics->width = right - metrics->vertBearingX; 522 metrics->height = bottom - metrics->vertBearingY; 523 } 524 else 525 { 526 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX ); 527 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY ); 528 529 right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width ); 530 bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height ); 531 532 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX ); 533 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY ); 534 535 metrics->width = right - metrics->horiBearingX; 536 metrics->height = metrics->horiBearingY - bottom; 537 } 538 539 metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance ); 540 metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance ); 541 } 542 #endif /* GRID_FIT_METRICS */ 543 544 545 /* documentation is in freetype.h */ 546 547 FT_EXPORT_DEF( FT_Error ) FT_Load_Glyph(FT_Face face,FT_UInt glyph_index,FT_Int32 load_flags)548 FT_Load_Glyph( FT_Face face, 549 FT_UInt glyph_index, 550 FT_Int32 load_flags ) 551 { 552 FT_Error error; 553 FT_Driver driver; 554 FT_GlyphSlot slot; 555 FT_Library library; 556 FT_Bool autohint = FALSE; 557 FT_Module hinter; 558 559 560 if ( !face || !face->size || !face->glyph ) 561 return FT_Err_Invalid_Face_Handle; 562 563 /* The validity test for `glyph_index' is performed by the */ 564 /* font drivers. */ 565 566 slot = face->glyph; 567 ft_glyphslot_clear( slot ); 568 569 driver = face->driver; 570 library = driver->root.library; 571 hinter = library->auto_hinter; 572 573 /* resolve load flags dependencies */ 574 575 if ( load_flags & FT_LOAD_NO_RECURSE ) 576 load_flags |= FT_LOAD_NO_SCALE | 577 FT_LOAD_IGNORE_TRANSFORM; 578 579 if ( load_flags & FT_LOAD_NO_SCALE ) 580 { 581 load_flags |= FT_LOAD_NO_HINTING | 582 FT_LOAD_NO_BITMAP; 583 584 load_flags &= ~FT_LOAD_RENDER; 585 } 586 587 /* 588 * Determine whether we need to auto-hint or not. 589 * The general rules are: 590 * 591 * - Do only auto-hinting if we have a hinter module, 592 * a scalable font format dealing with outlines, 593 * and no transforms except simple slants. 594 * 595 * - Then, autohint if FT_LOAD_FORCE_AUTOHINT is set 596 * or if we don't have a native font hinter. 597 * 598 * - Otherwise, auto-hint for LIGHT hinting mode. 599 * 600 * - Exception: The font is `tricky' and requires 601 * the native hinter to load properly. 602 */ 603 604 if ( hinter && 605 !( load_flags & FT_LOAD_NO_HINTING ) && 606 !( load_flags & FT_LOAD_NO_AUTOHINT ) && 607 FT_DRIVER_IS_SCALABLE( driver ) && 608 FT_DRIVER_USES_OUTLINES( driver ) && 609 !FT_IS_TRICKY( face ) && 610 face->internal->transform_matrix.yy > 0 && 611 face->internal->transform_matrix.yx == 0 ) 612 { 613 if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) || 614 !FT_DRIVER_HAS_HINTER( driver ) ) 615 autohint = TRUE; 616 else 617 { 618 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); 619 620 621 if ( mode == FT_RENDER_MODE_LIGHT || 622 face->internal->ignore_unpatented_hinter ) 623 autohint = TRUE; 624 } 625 } 626 627 if ( autohint ) 628 { 629 FT_AutoHinter_Service hinting; 630 631 632 /* try to load embedded bitmaps first if available */ 633 /* */ 634 /* XXX: This is really a temporary hack that should disappear */ 635 /* promptly with FreeType 2.1! */ 636 /* */ 637 if ( FT_HAS_FIXED_SIZES( face ) && 638 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) 639 { 640 error = driver->clazz->load_glyph( slot, face->size, 641 glyph_index, 642 load_flags | FT_LOAD_SBITS_ONLY ); 643 644 if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP ) 645 goto Load_Ok; 646 } 647 648 { 649 FT_Face_Internal internal = face->internal; 650 FT_Int transform_flags = internal->transform_flags; 651 652 653 /* since the auto-hinter calls FT_Load_Glyph by itself, */ 654 /* make sure that glyphs aren't transformed */ 655 internal->transform_flags = 0; 656 657 /* load auto-hinted outline */ 658 hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface; 659 660 error = hinting->load_glyph( (FT_AutoHinter)hinter, 661 slot, face->size, 662 glyph_index, load_flags ); 663 664 internal->transform_flags = transform_flags; 665 } 666 } 667 else 668 { 669 error = driver->clazz->load_glyph( slot, 670 face->size, 671 glyph_index, 672 load_flags ); 673 if ( error ) 674 goto Exit; 675 676 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) 677 { 678 /* check that the loaded outline is correct */ 679 error = FT_Outline_Check( &slot->outline ); 680 if ( error ) 681 goto Exit; 682 683 #ifdef GRID_FIT_METRICS 684 if ( !( load_flags & FT_LOAD_NO_HINTING ) ) 685 ft_glyphslot_grid_fit_metrics( slot, 686 FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) ); 687 #endif 688 } 689 } 690 691 Load_Ok: 692 /* compute the advance */ 693 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 694 { 695 slot->advance.x = 0; 696 slot->advance.y = slot->metrics.vertAdvance; 697 } 698 else 699 { 700 slot->advance.x = slot->metrics.horiAdvance; 701 slot->advance.y = 0; 702 } 703 704 /* compute the linear advance in 16.16 pixels */ 705 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 && 706 ( FT_IS_SCALABLE( face ) ) ) 707 { 708 FT_Size_Metrics* metrics = &face->size->metrics; 709 710 711 /* it's tricky! */ 712 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance, 713 metrics->x_scale, 64 ); 714 715 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance, 716 metrics->y_scale, 64 ); 717 } 718 719 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 ) 720 { 721 FT_Face_Internal internal = face->internal; 722 723 724 /* now, transform the glyph image if needed */ 725 if ( internal->transform_flags ) 726 { 727 /* get renderer */ 728 FT_Renderer renderer = ft_lookup_glyph_renderer( slot ); 729 730 731 if ( renderer ) 732 error = renderer->clazz->transform_glyph( 733 renderer, slot, 734 &internal->transform_matrix, 735 &internal->transform_delta ); 736 /* transform advance */ 737 FT_Vector_Transform( &slot->advance, &internal->transform_matrix ); 738 } 739 } 740 741 /* do we need to render the image now? */ 742 if ( !error && 743 slot->format != FT_GLYPH_FORMAT_BITMAP && 744 slot->format != FT_GLYPH_FORMAT_COMPOSITE && 745 load_flags & FT_LOAD_RENDER ) 746 { 747 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); 748 749 750 if ( mode == FT_RENDER_MODE_NORMAL && 751 (load_flags & FT_LOAD_MONOCHROME ) ) 752 mode = FT_RENDER_MODE_MONO; 753 754 error = FT_Render_Glyph( slot, mode ); 755 } 756 757 Exit: 758 return error; 759 } 760 761 762 /* documentation is in freetype.h */ 763 764 FT_EXPORT_DEF( FT_Error ) FT_Load_Char(FT_Face face,FT_ULong char_code,FT_Int32 load_flags)765 FT_Load_Char( FT_Face face, 766 FT_ULong char_code, 767 FT_Int32 load_flags ) 768 { 769 FT_UInt glyph_index; 770 771 772 if ( !face ) 773 return FT_Err_Invalid_Face_Handle; 774 775 glyph_index = (FT_UInt)char_code; 776 if ( face->charmap ) 777 glyph_index = FT_Get_Char_Index( face, char_code ); 778 779 return FT_Load_Glyph( face, glyph_index, load_flags ); 780 } 781 782 783 /* destructor for sizes list */ 784 static void destroy_size(FT_Memory memory,FT_Size size,FT_Driver driver)785 destroy_size( FT_Memory memory, 786 FT_Size size, 787 FT_Driver driver ) 788 { 789 /* finalize client-specific data */ 790 if ( size->generic.finalizer ) 791 size->generic.finalizer( size ); 792 793 /* finalize format-specific stuff */ 794 if ( driver->clazz->done_size ) 795 driver->clazz->done_size( size ); 796 797 FT_FREE( size->internal ); 798 FT_FREE( size ); 799 } 800 801 802 static void 803 ft_cmap_done_internal( FT_CMap cmap ); 804 805 806 static void destroy_charmaps(FT_Face face,FT_Memory memory)807 destroy_charmaps( FT_Face face, 808 FT_Memory memory ) 809 { 810 FT_Int n; 811 812 813 if ( !face ) 814 return; 815 816 for ( n = 0; n < face->num_charmaps; n++ ) 817 { 818 FT_CMap cmap = FT_CMAP( face->charmaps[n] ); 819 820 821 ft_cmap_done_internal( cmap ); 822 823 face->charmaps[n] = NULL; 824 } 825 826 FT_FREE( face->charmaps ); 827 face->num_charmaps = 0; 828 } 829 830 831 /* destructor for faces list */ 832 static void destroy_face(FT_Memory memory,FT_Face face,FT_Driver driver)833 destroy_face( FT_Memory memory, 834 FT_Face face, 835 FT_Driver driver ) 836 { 837 FT_Driver_Class clazz = driver->clazz; 838 839 840 /* discard auto-hinting data */ 841 if ( face->autohint.finalizer ) 842 face->autohint.finalizer( face->autohint.data ); 843 844 /* Discard glyph slots for this face. */ 845 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */ 846 while ( face->glyph ) 847 FT_Done_GlyphSlot( face->glyph ); 848 849 /* discard all sizes for this face */ 850 FT_List_Finalize( &face->sizes_list, 851 (FT_List_Destructor)destroy_size, 852 memory, 853 driver ); 854 face->size = 0; 855 856 /* now discard client data */ 857 if ( face->generic.finalizer ) 858 face->generic.finalizer( face ); 859 860 /* discard charmaps */ 861 destroy_charmaps( face, memory ); 862 863 /* finalize format-specific stuff */ 864 if ( clazz->done_face ) 865 clazz->done_face( face ); 866 867 /* close the stream for this face if needed */ 868 FT_Stream_Free( 869 face->stream, 870 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 ); 871 872 face->stream = 0; 873 874 /* get rid of it */ 875 if ( face->internal ) 876 { 877 FT_FREE( face->internal ); 878 } 879 FT_FREE( face ); 880 } 881 882 883 static void Destroy_Driver(FT_Driver driver)884 Destroy_Driver( FT_Driver driver ) 885 { 886 FT_List_Finalize( &driver->faces_list, 887 (FT_List_Destructor)destroy_face, 888 driver->root.memory, 889 driver ); 890 891 /* check whether we need to drop the driver's glyph loader */ 892 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 893 FT_GlyphLoader_Done( driver->glyph_loader ); 894 } 895 896 897 /*************************************************************************/ 898 /* */ 899 /* <Function> */ 900 /* find_unicode_charmap */ 901 /* */ 902 /* <Description> */ 903 /* This function finds a Unicode charmap, if there is one. */ 904 /* And if there is more than one, it tries to favour the more */ 905 /* extensive one, i.e., one that supports UCS-4 against those which */ 906 /* are limited to the BMP (said UCS-2 encoding.) */ 907 /* */ 908 /* This function is called from open_face() (just below), and also */ 909 /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */ 910 /* */ 911 static FT_Error find_unicode_charmap(FT_Face face)912 find_unicode_charmap( FT_Face face ) 913 { 914 FT_CharMap* first; 915 FT_CharMap* cur; 916 917 918 /* caller should have already checked that `face' is valid */ 919 FT_ASSERT( face ); 920 921 first = face->charmaps; 922 923 if ( !first ) 924 return FT_Err_Invalid_CharMap_Handle; 925 926 /* 927 * The original TrueType specification(s) only specified charmap 928 * formats that are capable of mapping 8 or 16 bit character codes to 929 * glyph indices. 930 * 931 * However, recent updates to the Apple and OpenType specifications 932 * introduced new formats that are capable of mapping 32-bit character 933 * codes as well. And these are already used on some fonts, mainly to 934 * map non-BMP Asian ideographs as defined in Unicode. 935 * 936 * For compatibility purposes, these fonts generally come with 937 * *several* Unicode charmaps: 938 * 939 * - One of them in the "old" 16-bit format, that cannot access 940 * all glyphs in the font. 941 * 942 * - Another one in the "new" 32-bit format, that can access all 943 * the glyphs. 944 * 945 * This function has been written to always favor a 32-bit charmap 946 * when found. Otherwise, a 16-bit one is returned when found. 947 */ 948 949 /* Since the `interesting' table, with IDs (3,10), is normally the */ 950 /* last one, we loop backwards. This loses with type1 fonts with */ 951 /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */ 952 /* chars (.01% ?), and this is the same about 99.99% of the time! */ 953 954 cur = first + face->num_charmaps; /* points after the last one */ 955 956 for ( ; --cur >= first; ) 957 { 958 if ( cur[0]->encoding == FT_ENCODING_UNICODE ) 959 { 960 /* XXX If some new encodings to represent UCS-4 are added, */ 961 /* they should be added here. */ 962 if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT && 963 cur[0]->encoding_id == TT_MS_ID_UCS_4 ) || 964 ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && 965 cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) ) 966 { 967 face->charmap = cur[0]; 968 return FT_Err_Ok; 969 } 970 } 971 } 972 973 /* We do not have any UCS-4 charmap. */ 974 /* Do the loop again and search for UCS-2 charmaps. */ 975 cur = first + face->num_charmaps; 976 977 for ( ; --cur >= first; ) 978 { 979 if ( cur[0]->encoding == FT_ENCODING_UNICODE ) 980 { 981 face->charmap = cur[0]; 982 return FT_Err_Ok; 983 } 984 } 985 986 return FT_Err_Invalid_CharMap_Handle; 987 } 988 989 990 /*************************************************************************/ 991 /* */ 992 /* <Function> */ 993 /* find_variant_selector_charmap */ 994 /* */ 995 /* <Description> */ 996 /* This function finds the variant selector charmap, if there is one. */ 997 /* There can only be one (platform=0, specific=5, format=14). */ 998 /* */ 999 static FT_CharMap find_variant_selector_charmap(FT_Face face)1000 find_variant_selector_charmap( FT_Face face ) 1001 { 1002 FT_CharMap* first; 1003 FT_CharMap* end; 1004 FT_CharMap* cur; 1005 1006 1007 /* caller should have already checked that `face' is valid */ 1008 FT_ASSERT( face ); 1009 1010 first = face->charmaps; 1011 1012 if ( !first ) 1013 return NULL; 1014 1015 end = first + face->num_charmaps; /* points after the last one */ 1016 1017 for ( cur = first; cur < end; ++cur ) 1018 { 1019 if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && 1020 cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR && 1021 FT_Get_CMap_Format( cur[0] ) == 14 ) 1022 return cur[0]; 1023 } 1024 1025 return NULL; 1026 } 1027 1028 1029 /*************************************************************************/ 1030 /* */ 1031 /* <Function> */ 1032 /* open_face */ 1033 /* */ 1034 /* <Description> */ 1035 /* This function does some work for FT_Open_Face(). */ 1036 /* */ 1037 static FT_Error open_face(FT_Driver driver,FT_Stream stream,FT_Long face_index,FT_Int num_params,FT_Parameter * params,FT_Face * aface)1038 open_face( FT_Driver driver, 1039 FT_Stream stream, 1040 FT_Long face_index, 1041 FT_Int num_params, 1042 FT_Parameter* params, 1043 FT_Face *aface ) 1044 { 1045 FT_Memory memory; 1046 FT_Driver_Class clazz; 1047 FT_Face face = 0; 1048 FT_Error error, error2; 1049 FT_Face_Internal internal = NULL; 1050 1051 1052 clazz = driver->clazz; 1053 memory = driver->root.memory; 1054 1055 /* allocate the face object and perform basic initialization */ 1056 if ( FT_ALLOC( face, clazz->face_object_size ) ) 1057 goto Fail; 1058 1059 if ( FT_NEW( internal ) ) 1060 goto Fail; 1061 1062 face->internal = internal; 1063 1064 face->driver = driver; 1065 face->memory = memory; 1066 face->stream = stream; 1067 1068 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1069 { 1070 int i; 1071 1072 1073 face->internal->incremental_interface = 0; 1074 for ( i = 0; i < num_params && !face->internal->incremental_interface; 1075 i++ ) 1076 if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL ) 1077 face->internal->incremental_interface = 1078 (FT_Incremental_Interface)params[i].data; 1079 } 1080 #endif 1081 1082 if ( clazz->init_face ) 1083 error = clazz->init_face( stream, 1084 face, 1085 (FT_Int)face_index, 1086 num_params, 1087 params ); 1088 if ( error ) 1089 goto Fail; 1090 1091 /* select Unicode charmap by default */ 1092 error2 = find_unicode_charmap( face ); 1093 1094 /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */ 1095 /* is returned. */ 1096 1097 /* no error should happen, but we want to play safe */ 1098 if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle ) 1099 { 1100 error = error2; 1101 goto Fail; 1102 } 1103 1104 *aface = face; 1105 1106 Fail: 1107 if ( error ) 1108 { 1109 destroy_charmaps( face, memory ); 1110 if ( clazz->done_face ) 1111 clazz->done_face( face ); 1112 FT_FREE( internal ); 1113 FT_FREE( face ); 1114 *aface = 0; 1115 } 1116 1117 return error; 1118 } 1119 1120 1121 /* there's a Mac-specific extended implementation of FT_New_Face() */ 1122 /* in src/base/ftmac.c */ 1123 1124 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON ) 1125 1126 /* documentation is in freetype.h */ 1127 1128 FT_EXPORT_DEF( FT_Error ) FT_New_Face(FT_Library library,const char * pathname,FT_Long face_index,FT_Face * aface)1129 FT_New_Face( FT_Library library, 1130 const char* pathname, 1131 FT_Long face_index, 1132 FT_Face *aface ) 1133 { 1134 FT_Open_Args args; 1135 1136 1137 /* test for valid `library' and `aface' delayed to FT_Open_Face() */ 1138 if ( !pathname ) 1139 return FT_Err_Invalid_Argument; 1140 1141 args.flags = FT_OPEN_PATHNAME; 1142 args.pathname = (char*)pathname; 1143 args.stream = NULL; 1144 1145 return FT_Open_Face( library, &args, face_index, aface ); 1146 } 1147 1148 #endif /* defined( FT_MACINTOSH ) && !defined( DARWIN_NO_CARBON ) */ 1149 1150 1151 /* documentation is in freetype.h */ 1152 1153 FT_EXPORT_DEF( FT_Error ) FT_New_Memory_Face(FT_Library library,const FT_Byte * file_base,FT_Long file_size,FT_Long face_index,FT_Face * aface)1154 FT_New_Memory_Face( FT_Library library, 1155 const FT_Byte* file_base, 1156 FT_Long file_size, 1157 FT_Long face_index, 1158 FT_Face *aface ) 1159 { 1160 FT_Open_Args args; 1161 1162 1163 /* test for valid `library' and `face' delayed to FT_Open_Face() */ 1164 if ( !file_base ) 1165 return FT_Err_Invalid_Argument; 1166 1167 args.flags = FT_OPEN_MEMORY; 1168 args.memory_base = file_base; 1169 args.memory_size = file_size; 1170 args.stream = NULL; 1171 1172 return FT_Open_Face( library, &args, face_index, aface ); 1173 } 1174 1175 1176 #ifdef FT_CONFIG_OPTION_MAC_FONTS 1177 1178 /* The behavior here is very similar to that in base/ftmac.c, but it */ 1179 /* is designed to work on non-mac systems, so no mac specific calls. */ 1180 /* */ 1181 /* We look at the file and determine if it is a mac dfont file or a mac */ 1182 /* resource file, or a macbinary file containing a mac resource file. */ 1183 /* */ 1184 /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */ 1185 /* the point, especially since there may be multiple `FOND' resources. */ 1186 /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */ 1187 /* they occur in the file. */ 1188 /* */ 1189 /* Note that multiple `POST' resources do not mean multiple postscript */ 1190 /* fonts; they all get jammed together to make what is essentially a */ 1191 /* pfb file. */ 1192 /* */ 1193 /* We aren't interested in `NFNT' or `FONT' bitmap resources. */ 1194 /* */ 1195 /* As soon as we get an `sfnt' load it into memory and pass it off to */ 1196 /* FT_Open_Face. */ 1197 /* */ 1198 /* If we have a (set of) `POST' resources, massage them into a (memory) */ 1199 /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */ 1200 /* going to try to save the kerning info. After all that lives in the */ 1201 /* `FOND' which isn't in the file containing the `POST' resources so */ 1202 /* we don't really have access to it. */ 1203 1204 1205 /* Finalizer for a memory stream; gets called by FT_Done_Face(). */ 1206 /* It frees the memory it uses. */ 1207 /* From ftmac.c. */ 1208 static void memory_stream_close(FT_Stream stream)1209 memory_stream_close( FT_Stream stream ) 1210 { 1211 FT_Memory memory = stream->memory; 1212 1213 1214 FT_FREE( stream->base ); 1215 1216 stream->size = 0; 1217 stream->base = 0; 1218 stream->close = 0; 1219 } 1220 1221 1222 /* Create a new memory stream from a buffer and a size. */ 1223 /* From ftmac.c. */ 1224 static FT_Error new_memory_stream(FT_Library library,FT_Byte * base,FT_ULong size,FT_Stream_CloseFunc close,FT_Stream * astream)1225 new_memory_stream( FT_Library library, 1226 FT_Byte* base, 1227 FT_ULong size, 1228 FT_Stream_CloseFunc close, 1229 FT_Stream *astream ) 1230 { 1231 FT_Error error; 1232 FT_Memory memory; 1233 FT_Stream stream; 1234 1235 1236 if ( !library ) 1237 return FT_Err_Invalid_Library_Handle; 1238 1239 if ( !base ) 1240 return FT_Err_Invalid_Argument; 1241 1242 *astream = 0; 1243 memory = library->memory; 1244 if ( FT_NEW( stream ) ) 1245 goto Exit; 1246 1247 FT_Stream_OpenMemory( stream, base, size ); 1248 1249 stream->close = close; 1250 1251 *astream = stream; 1252 1253 Exit: 1254 return error; 1255 } 1256 1257 1258 /* Create a new FT_Face given a buffer and a driver name. */ 1259 /* from ftmac.c */ 1260 FT_LOCAL_DEF( FT_Error ) open_face_from_buffer(FT_Library library,FT_Byte * base,FT_ULong size,FT_Long face_index,const char * driver_name,FT_Face * aface)1261 open_face_from_buffer( FT_Library library, 1262 FT_Byte* base, 1263 FT_ULong size, 1264 FT_Long face_index, 1265 const char* driver_name, 1266 FT_Face *aface ) 1267 { 1268 FT_Open_Args args; 1269 FT_Error error; 1270 FT_Stream stream = NULL; 1271 FT_Memory memory = library->memory; 1272 1273 1274 error = new_memory_stream( library, 1275 base, 1276 size, 1277 memory_stream_close, 1278 &stream ); 1279 if ( error ) 1280 { 1281 FT_FREE( base ); 1282 return error; 1283 } 1284 1285 args.flags = FT_OPEN_STREAM; 1286 args.stream = stream; 1287 if ( driver_name ) 1288 { 1289 args.flags = args.flags | FT_OPEN_DRIVER; 1290 args.driver = FT_Get_Module( library, driver_name ); 1291 } 1292 1293 #ifdef FT_MACINTOSH 1294 /* At this point, face_index has served its purpose; */ 1295 /* whoever calls this function has already used it to */ 1296 /* locate the correct font data. We should not propagate */ 1297 /* this index to FT_Open_Face() (unless it is negative). */ 1298 1299 if ( face_index > 0 ) 1300 face_index = 0; 1301 #endif 1302 1303 error = FT_Open_Face( library, &args, face_index, aface ); 1304 1305 if ( error == FT_Err_Ok ) 1306 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; 1307 else 1308 #ifdef FT_MACINTOSH 1309 FT_Stream_Free( stream, 0 ); 1310 #else 1311 { 1312 FT_Stream_Close( stream ); 1313 FT_FREE( stream ); 1314 } 1315 #endif 1316 1317 return error; 1318 } 1319 1320 1321 /* Look up `TYP1' or `CID ' table from sfnt table directory. */ 1322 /* `offset' and `length' must exclude the binary header in tables. */ 1323 1324 /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */ 1325 /* format too. Here, since we can't expect that the TrueType font */ 1326 /* driver is loaded unconditially, we must parse the font by */ 1327 /* ourselves. We are only interested in the name of the table and */ 1328 /* the offset. */ 1329 1330 static FT_Error ft_lookup_PS_in_sfnt_stream(FT_Stream stream,FT_Long face_index,FT_ULong * offset,FT_ULong * length,FT_Bool * is_sfnt_cid)1331 ft_lookup_PS_in_sfnt_stream( FT_Stream stream, 1332 FT_Long face_index, 1333 FT_ULong* offset, 1334 FT_ULong* length, 1335 FT_Bool* is_sfnt_cid ) 1336 { 1337 FT_Error error; 1338 FT_UShort numTables; 1339 FT_Long pstable_index; 1340 FT_ULong tag; 1341 int i; 1342 1343 1344 *offset = 0; 1345 *length = 0; 1346 *is_sfnt_cid = FALSE; 1347 1348 /* TODO: support for sfnt-wrapped PS/CID in TTC format */ 1349 1350 /* version check for 'typ1' (should be ignored?) */ 1351 if ( FT_READ_ULONG( tag ) ) 1352 return error; 1353 if ( tag != TTAG_typ1 ) 1354 return FT_Err_Unknown_File_Format; 1355 1356 if ( FT_READ_USHORT( numTables ) ) 1357 return error; 1358 if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */ 1359 return error; 1360 1361 pstable_index = -1; 1362 *is_sfnt_cid = FALSE; 1363 1364 for ( i = 0; i < numTables; i++ ) 1365 { 1366 if ( FT_READ_ULONG( tag ) || FT_STREAM_SKIP( 4 ) || 1367 FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) ) 1368 return error; 1369 1370 if ( tag == TTAG_CID ) 1371 { 1372 pstable_index++; 1373 *offset += 22; 1374 *length -= 22; 1375 *is_sfnt_cid = TRUE; 1376 if ( face_index < 0 ) 1377 return FT_Err_Ok; 1378 } 1379 else if ( tag == TTAG_TYP1 ) 1380 { 1381 pstable_index++; 1382 *offset += 24; 1383 *length -= 24; 1384 *is_sfnt_cid = FALSE; 1385 if ( face_index < 0 ) 1386 return FT_Err_Ok; 1387 } 1388 if ( face_index >= 0 && pstable_index == face_index ) 1389 return FT_Err_Ok; 1390 } 1391 return FT_Err_Table_Missing; 1392 } 1393 1394 1395 FT_LOCAL_DEF( FT_Error ) open_face_PS_from_sfnt_stream(FT_Library library,FT_Stream stream,FT_Long face_index,FT_Int num_params,FT_Parameter * params,FT_Face * aface)1396 open_face_PS_from_sfnt_stream( FT_Library library, 1397 FT_Stream stream, 1398 FT_Long face_index, 1399 FT_Int num_params, 1400 FT_Parameter *params, 1401 FT_Face *aface ) 1402 { 1403 FT_Error error; 1404 FT_Memory memory = library->memory; 1405 FT_ULong offset, length; 1406 FT_Long pos; 1407 FT_Bool is_sfnt_cid; 1408 FT_Byte* sfnt_ps; 1409 1410 FT_UNUSED( num_params ); 1411 FT_UNUSED( params ); 1412 1413 1414 pos = FT_Stream_Pos( stream ); 1415 1416 error = ft_lookup_PS_in_sfnt_stream( stream, 1417 face_index, 1418 &offset, 1419 &length, 1420 &is_sfnt_cid ); 1421 if ( error ) 1422 goto Exit; 1423 1424 if ( FT_Stream_Seek( stream, pos + offset ) ) 1425 goto Exit; 1426 1427 if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) ) 1428 goto Exit; 1429 1430 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length ); 1431 if ( error ) 1432 goto Exit; 1433 1434 error = open_face_from_buffer( library, 1435 sfnt_ps, 1436 length, 1437 face_index < 0 ? face_index : 0, 1438 is_sfnt_cid ? "cid" : "type1", 1439 aface ); 1440 Exit: 1441 { 1442 FT_Error error1; 1443 1444 1445 if ( error == FT_Err_Unknown_File_Format ) 1446 { 1447 error1 = FT_Stream_Seek( stream, pos ); 1448 if ( error1 ) 1449 return error1; 1450 } 1451 1452 return error; 1453 } 1454 } 1455 1456 1457 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON ) 1458 1459 /* The resource header says we've got resource_cnt `POST' (type1) */ 1460 /* resources in this file. They all need to be coalesced into */ 1461 /* one lump which gets passed on to the type1 driver. */ 1462 /* Here can be only one PostScript font in a file so face_index */ 1463 /* must be 0 (or -1). */ 1464 /* */ 1465 static FT_Error Mac_Read_POST_Resource(FT_Library library,FT_Stream stream,FT_Long * offsets,FT_Long resource_cnt,FT_Long face_index,FT_Face * aface)1466 Mac_Read_POST_Resource( FT_Library library, 1467 FT_Stream stream, 1468 FT_Long *offsets, 1469 FT_Long resource_cnt, 1470 FT_Long face_index, 1471 FT_Face *aface ) 1472 { 1473 FT_Error error = FT_Err_Cannot_Open_Resource; 1474 FT_Memory memory = library->memory; 1475 FT_Byte* pfb_data; 1476 int i, type, flags; 1477 FT_Long len; 1478 FT_Long pfb_len, pfb_pos, pfb_lenpos; 1479 FT_Long rlen, temp; 1480 1481 1482 if ( face_index == -1 ) 1483 face_index = 0; 1484 if ( face_index != 0 ) 1485 return error; 1486 1487 /* Find the length of all the POST resources, concatenated. Assume */ 1488 /* worst case (each resource in its own section). */ 1489 pfb_len = 0; 1490 for ( i = 0; i < resource_cnt; ++i ) 1491 { 1492 error = FT_Stream_Seek( stream, offsets[i] ); 1493 if ( error ) 1494 goto Exit; 1495 if ( FT_READ_LONG( temp ) ) 1496 goto Exit; 1497 pfb_len += temp + 6; 1498 } 1499 1500 if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) ) 1501 goto Exit; 1502 1503 pfb_data[0] = 0x80; 1504 pfb_data[1] = 1; /* Ascii section */ 1505 pfb_data[2] = 0; /* 4-byte length, fill in later */ 1506 pfb_data[3] = 0; 1507 pfb_data[4] = 0; 1508 pfb_data[5] = 0; 1509 pfb_pos = 6; 1510 pfb_lenpos = 2; 1511 1512 len = 0; 1513 type = 1; 1514 for ( i = 0; i < resource_cnt; ++i ) 1515 { 1516 error = FT_Stream_Seek( stream, offsets[i] ); 1517 if ( error ) 1518 goto Exit2; 1519 if ( FT_READ_LONG( rlen ) ) 1520 goto Exit; 1521 if ( FT_READ_USHORT( flags ) ) 1522 goto Exit; 1523 rlen -= 2; /* the flags are part of the resource */ 1524 if ( ( flags >> 8 ) == type ) 1525 len += rlen; 1526 else 1527 { 1528 pfb_data[pfb_lenpos ] = (FT_Byte)( len ); 1529 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); 1530 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); 1531 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 ); 1532 1533 if ( ( flags >> 8 ) == 5 ) /* End of font mark */ 1534 break; 1535 1536 pfb_data[pfb_pos++] = 0x80; 1537 1538 type = flags >> 8; 1539 len = rlen; 1540 1541 pfb_data[pfb_pos++] = (FT_Byte)type; 1542 pfb_lenpos = pfb_pos; 1543 pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */ 1544 pfb_data[pfb_pos++] = 0; 1545 pfb_data[pfb_pos++] = 0; 1546 pfb_data[pfb_pos++] = 0; 1547 } 1548 1549 error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen ); 1550 pfb_pos += rlen; 1551 } 1552 1553 pfb_data[pfb_pos++] = 0x80; 1554 pfb_data[pfb_pos++] = 3; 1555 1556 pfb_data[pfb_lenpos ] = (FT_Byte)( len ); 1557 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); 1558 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); 1559 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 ); 1560 1561 return open_face_from_buffer( library, 1562 pfb_data, 1563 pfb_pos, 1564 face_index, 1565 "type1", 1566 aface ); 1567 1568 Exit2: 1569 FT_FREE( pfb_data ); 1570 1571 Exit: 1572 return error; 1573 } 1574 1575 1576 /* The resource header says we've got resource_cnt `sfnt' */ 1577 /* (TrueType/OpenType) resources in this file. Look through */ 1578 /* them for the one indicated by face_index, load it into mem, */ 1579 /* pass it on the the truetype driver and return it. */ 1580 /* */ 1581 static FT_Error Mac_Read_sfnt_Resource(FT_Library library,FT_Stream stream,FT_Long * offsets,FT_Long resource_cnt,FT_Long face_index,FT_Face * aface)1582 Mac_Read_sfnt_Resource( FT_Library library, 1583 FT_Stream stream, 1584 FT_Long *offsets, 1585 FT_Long resource_cnt, 1586 FT_Long face_index, 1587 FT_Face *aface ) 1588 { 1589 FT_Memory memory = library->memory; 1590 FT_Byte* sfnt_data; 1591 FT_Error error; 1592 FT_Long flag_offset; 1593 FT_Long rlen; 1594 int is_cff; 1595 FT_Long face_index_in_resource = 0; 1596 1597 1598 if ( face_index == -1 ) 1599 face_index = 0; 1600 if ( face_index >= resource_cnt ) 1601 return FT_Err_Cannot_Open_Resource; 1602 1603 flag_offset = offsets[face_index]; 1604 error = FT_Stream_Seek( stream, flag_offset ); 1605 if ( error ) 1606 goto Exit; 1607 1608 if ( FT_READ_LONG( rlen ) ) 1609 goto Exit; 1610 if ( rlen == -1 ) 1611 return FT_Err_Cannot_Open_Resource; 1612 1613 error = open_face_PS_from_sfnt_stream( library, 1614 stream, 1615 face_index, 1616 0, NULL, 1617 aface ); 1618 if ( !error ) 1619 goto Exit; 1620 1621 /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */ 1622 if ( FT_Stream_Seek( stream, flag_offset + 4 ) ) 1623 goto Exit; 1624 1625 if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) ) 1626 return error; 1627 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen ); 1628 if ( error ) 1629 goto Exit; 1630 1631 is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 ); 1632 error = open_face_from_buffer( library, 1633 sfnt_data, 1634 rlen, 1635 face_index_in_resource, 1636 is_cff ? "cff" : "truetype", 1637 aface ); 1638 1639 Exit: 1640 return error; 1641 } 1642 1643 1644 /* Check for a valid resource fork header, or a valid dfont */ 1645 /* header. In a resource fork the first 16 bytes are repeated */ 1646 /* at the location specified by bytes 4-7. In a dfont bytes */ 1647 /* 4-7 point to 16 bytes of zeroes instead. */ 1648 /* */ 1649 static FT_Error IsMacResource(FT_Library library,FT_Stream stream,FT_Long resource_offset,FT_Long face_index,FT_Face * aface)1650 IsMacResource( FT_Library library, 1651 FT_Stream stream, 1652 FT_Long resource_offset, 1653 FT_Long face_index, 1654 FT_Face *aface ) 1655 { 1656 FT_Memory memory = library->memory; 1657 FT_Error error; 1658 FT_Long map_offset, rdara_pos; 1659 FT_Long *data_offsets; 1660 FT_Long count; 1661 1662 1663 error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset, 1664 &map_offset, &rdara_pos ); 1665 if ( error ) 1666 return error; 1667 1668 error = FT_Raccess_Get_DataOffsets( library, stream, 1669 map_offset, rdara_pos, 1670 TTAG_POST, 1671 &data_offsets, &count ); 1672 if ( !error ) 1673 { 1674 error = Mac_Read_POST_Resource( library, stream, data_offsets, count, 1675 face_index, aface ); 1676 FT_FREE( data_offsets ); 1677 /* POST exists in an LWFN providing a single face */ 1678 if ( !error ) 1679 (*aface)->num_faces = 1; 1680 return error; 1681 } 1682 1683 error = FT_Raccess_Get_DataOffsets( library, stream, 1684 map_offset, rdara_pos, 1685 TTAG_sfnt, 1686 &data_offsets, &count ); 1687 if ( !error ) 1688 { 1689 FT_Long face_index_internal = face_index % count; 1690 1691 1692 error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count, 1693 face_index_internal, aface ); 1694 FT_FREE( data_offsets ); 1695 if ( !error ) 1696 (*aface)->num_faces = count; 1697 } 1698 1699 return error; 1700 } 1701 1702 1703 /* Check for a valid macbinary header, and if we find one */ 1704 /* check that the (flattened) resource fork in it is valid. */ 1705 /* */ 1706 static FT_Error IsMacBinary(FT_Library library,FT_Stream stream,FT_Long face_index,FT_Face * aface)1707 IsMacBinary( FT_Library library, 1708 FT_Stream stream, 1709 FT_Long face_index, 1710 FT_Face *aface ) 1711 { 1712 unsigned char header[128]; 1713 FT_Error error; 1714 FT_Long dlen, offset; 1715 1716 1717 if ( NULL == stream ) 1718 return FT_Err_Invalid_Stream_Operation; 1719 1720 error = FT_Stream_Seek( stream, 0 ); 1721 if ( error ) 1722 goto Exit; 1723 1724 error = FT_Stream_Read( stream, (FT_Byte*)header, 128 ); 1725 if ( error ) 1726 goto Exit; 1727 1728 if ( header[ 0] != 0 || 1729 header[74] != 0 || 1730 header[82] != 0 || 1731 header[ 1] == 0 || 1732 header[ 1] > 33 || 1733 header[63] != 0 || 1734 header[2 + header[1]] != 0 ) 1735 return FT_Err_Unknown_File_Format; 1736 1737 dlen = ( header[0x53] << 24 ) | 1738 ( header[0x54] << 16 ) | 1739 ( header[0x55] << 8 ) | 1740 header[0x56]; 1741 #if 0 1742 rlen = ( header[0x57] << 24 ) | 1743 ( header[0x58] << 16 ) | 1744 ( header[0x59] << 8 ) | 1745 header[0x5a]; 1746 #endif /* 0 */ 1747 offset = 128 + ( ( dlen + 127 ) & ~127 ); 1748 1749 return IsMacResource( library, stream, offset, face_index, aface ); 1750 1751 Exit: 1752 return error; 1753 } 1754 1755 1756 static FT_Error load_face_in_embedded_rfork(FT_Library library,FT_Stream stream,FT_Long face_index,FT_Face * aface,const FT_Open_Args * args)1757 load_face_in_embedded_rfork( FT_Library library, 1758 FT_Stream stream, 1759 FT_Long face_index, 1760 FT_Face *aface, 1761 const FT_Open_Args *args ) 1762 { 1763 1764 #undef FT_COMPONENT 1765 #define FT_COMPONENT trace_raccess 1766 1767 FT_Memory memory = library->memory; 1768 FT_Error error = FT_Err_Unknown_File_Format; 1769 int i; 1770 1771 char * file_names[FT_RACCESS_N_RULES]; 1772 FT_Long offsets[FT_RACCESS_N_RULES]; 1773 FT_Error errors[FT_RACCESS_N_RULES]; 1774 1775 FT_Open_Args args2; 1776 FT_Stream stream2 = 0; 1777 1778 1779 FT_Raccess_Guess( library, stream, 1780 args->pathname, file_names, offsets, errors ); 1781 1782 for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) 1783 { 1784 if ( errors[i] ) 1785 { 1786 FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i )); 1787 continue; 1788 } 1789 1790 args2.flags = FT_OPEN_PATHNAME; 1791 args2.pathname = file_names[i] ? file_names[i] : args->pathname; 1792 1793 FT_TRACE3(( "Try rule %d: %s (offset=%d) ...", 1794 i, args2.pathname, offsets[i] )); 1795 1796 error = FT_Stream_New( library, &args2, &stream2 ); 1797 if ( error ) 1798 { 1799 FT_TRACE3(( "failed\n" )); 1800 continue; 1801 } 1802 1803 error = IsMacResource( library, stream2, offsets[i], 1804 face_index, aface ); 1805 FT_Stream_Free( stream2, 0 ); 1806 1807 FT_TRACE3(( "%s\n", error ? "failed": "successful" )); 1808 1809 if ( !error ) 1810 break; 1811 } 1812 1813 for (i = 0; i < FT_RACCESS_N_RULES; i++) 1814 { 1815 if ( file_names[i] ) 1816 FT_FREE( file_names[i] ); 1817 } 1818 1819 /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */ 1820 if ( error ) 1821 error = FT_Err_Unknown_File_Format; 1822 1823 return error; 1824 1825 #undef FT_COMPONENT 1826 #define FT_COMPONENT trace_objs 1827 1828 } 1829 1830 1831 /* Check for some macintosh formats without Carbon framework. */ 1832 /* Is this a macbinary file? If so look at the resource fork. */ 1833 /* Is this a mac dfont file? */ 1834 /* Is this an old style resource fork? (in data) */ 1835 /* Else call load_face_in_embedded_rfork to try extra rules */ 1836 /* (defined in `ftrfork.c'). */ 1837 /* */ 1838 static FT_Error load_mac_face(FT_Library library,FT_Stream stream,FT_Long face_index,FT_Face * aface,const FT_Open_Args * args)1839 load_mac_face( FT_Library library, 1840 FT_Stream stream, 1841 FT_Long face_index, 1842 FT_Face *aface, 1843 const FT_Open_Args *args ) 1844 { 1845 FT_Error error; 1846 FT_UNUSED( args ); 1847 1848 1849 error = IsMacBinary( library, stream, face_index, aface ); 1850 if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ) 1851 { 1852 1853 #undef FT_COMPONENT 1854 #define FT_COMPONENT trace_raccess 1855 1856 FT_TRACE3(( "Try as dfont: %s ...", args->pathname )); 1857 1858 error = IsMacResource( library, stream, 0, face_index, aface ); 1859 1860 FT_TRACE3(( "%s\n", error ? "failed" : "successful" )); 1861 1862 #undef FT_COMPONENT 1863 #define FT_COMPONENT trace_objs 1864 1865 } 1866 1867 if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format || 1868 FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) && 1869 ( args->flags & FT_OPEN_PATHNAME ) ) 1870 error = load_face_in_embedded_rfork( library, stream, 1871 face_index, aface, args ); 1872 return error; 1873 } 1874 #endif 1875 1876 #endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */ 1877 1878 1879 /* documentation is in freetype.h */ 1880 1881 FT_EXPORT_DEF( FT_Error ) FT_Open_Face(FT_Library library,const FT_Open_Args * args,FT_Long face_index,FT_Face * aface)1882 FT_Open_Face( FT_Library library, 1883 const FT_Open_Args* args, 1884 FT_Long face_index, 1885 FT_Face *aface ) 1886 { 1887 FT_Error error; 1888 FT_Driver driver; 1889 FT_Memory memory; 1890 FT_Stream stream = 0; 1891 FT_Face face = 0; 1892 FT_ListNode node = 0; 1893 FT_Bool external_stream; 1894 FT_Module* cur; 1895 FT_Module* limit; 1896 1897 1898 /* test for valid `library' delayed to */ 1899 /* FT_Stream_New() */ 1900 1901 if ( ( !aface && face_index >= 0 ) || !args ) 1902 return FT_Err_Invalid_Argument; 1903 1904 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) && 1905 args->stream ); 1906 1907 /* create input stream */ 1908 error = FT_Stream_New( library, args, &stream ); 1909 if ( error ) 1910 goto Fail3; 1911 1912 memory = library->memory; 1913 1914 /* If the font driver is specified in the `args' structure, use */ 1915 /* it. Otherwise, we scan the list of registered drivers. */ 1916 if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver ) 1917 { 1918 driver = FT_DRIVER( args->driver ); 1919 1920 /* not all modules are drivers, so check... */ 1921 if ( FT_MODULE_IS_DRIVER( driver ) ) 1922 { 1923 FT_Int num_params = 0; 1924 FT_Parameter* params = 0; 1925 1926 1927 if ( args->flags & FT_OPEN_PARAMS ) 1928 { 1929 num_params = args->num_params; 1930 params = args->params; 1931 } 1932 1933 error = open_face( driver, stream, face_index, 1934 num_params, params, &face ); 1935 if ( !error ) 1936 goto Success; 1937 } 1938 else 1939 error = FT_Err_Invalid_Handle; 1940 1941 FT_Stream_Free( stream, external_stream ); 1942 goto Fail; 1943 } 1944 else 1945 { 1946 /* check each font driver for an appropriate format */ 1947 cur = library->modules; 1948 limit = cur + library->num_modules; 1949 1950 1951 for ( ; cur < limit; cur++ ) 1952 { 1953 /* not all modules are font drivers, so check... */ 1954 if ( FT_MODULE_IS_DRIVER( cur[0] ) ) 1955 { 1956 FT_Int num_params = 0; 1957 FT_Parameter* params = 0; 1958 1959 1960 driver = FT_DRIVER( cur[0] ); 1961 1962 if ( args->flags & FT_OPEN_PARAMS ) 1963 { 1964 num_params = args->num_params; 1965 params = args->params; 1966 } 1967 1968 error = open_face( driver, stream, face_index, 1969 num_params, params, &face ); 1970 if ( !error ) 1971 goto Success; 1972 1973 #ifdef FT_CONFIG_OPTION_MAC_FONTS 1974 if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 && 1975 FT_ERROR_BASE( error ) == FT_Err_Table_Missing ) 1976 { 1977 /* TrueType but essential tables are missing */ 1978 if ( FT_Stream_Seek( stream, 0 ) ) 1979 break; 1980 1981 error = open_face_PS_from_sfnt_stream( library, 1982 stream, 1983 face_index, 1984 num_params, 1985 params, 1986 aface ); 1987 if ( !error ) 1988 { 1989 FT_Stream_Free( stream, external_stream ); 1990 return error; 1991 } 1992 } 1993 #endif 1994 1995 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format ) 1996 goto Fail3; 1997 } 1998 } 1999 2000 Fail3: 2001 /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */ 2002 /* it may be because we have an empty data fork, so we need to check */ 2003 /* the resource fork. */ 2004 if ( FT_ERROR_BASE( error ) != FT_Err_Cannot_Open_Stream && 2005 FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format && 2006 FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation ) 2007 goto Fail2; 2008 2009 #if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS ) 2010 error = load_mac_face( library, stream, face_index, aface, args ); 2011 if ( !error ) 2012 { 2013 /* We don't want to go to Success here. We've already done that. */ 2014 /* On the other hand, if we succeeded we still need to close this */ 2015 /* stream (we opened a different stream which extracted the */ 2016 /* interesting information out of this stream here. That stream */ 2017 /* will still be open and the face will point to it). */ 2018 FT_Stream_Free( stream, external_stream ); 2019 return error; 2020 } 2021 2022 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format ) 2023 goto Fail2; 2024 #endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */ 2025 2026 /* no driver is able to handle this format */ 2027 error = FT_Err_Unknown_File_Format; 2028 2029 Fail2: 2030 FT_Stream_Free( stream, external_stream ); 2031 goto Fail; 2032 } 2033 2034 Success: 2035 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" )); 2036 2037 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */ 2038 if ( external_stream ) 2039 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM; 2040 2041 /* add the face object to its driver's list */ 2042 if ( FT_NEW( node ) ) 2043 goto Fail; 2044 2045 node->data = face; 2046 /* don't assume driver is the same as face->driver, so use */ 2047 /* face->driver instead. */ 2048 FT_List_Add( &face->driver->faces_list, node ); 2049 2050 /* now allocate a glyph slot object for the face */ 2051 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" )); 2052 2053 if ( face_index >= 0 ) 2054 { 2055 error = FT_New_GlyphSlot( face, NULL ); 2056 if ( error ) 2057 goto Fail; 2058 2059 /* finally, allocate a size object for the face */ 2060 { 2061 FT_Size size; 2062 2063 2064 FT_TRACE4(( "FT_Open_Face: Creating size object\n" )); 2065 2066 error = FT_New_Size( face, &size ); 2067 if ( error ) 2068 goto Fail; 2069 2070 face->size = size; 2071 } 2072 } 2073 2074 /* some checks */ 2075 2076 if ( FT_IS_SCALABLE( face ) ) 2077 { 2078 if ( face->height < 0 ) 2079 face->height = (FT_Short)-face->height; 2080 2081 if ( !FT_HAS_VERTICAL( face ) ) 2082 face->max_advance_height = (FT_Short)face->height; 2083 } 2084 2085 if ( FT_HAS_FIXED_SIZES( face ) ) 2086 { 2087 FT_Int i; 2088 2089 2090 for ( i = 0; i < face->num_fixed_sizes; i++ ) 2091 { 2092 FT_Bitmap_Size* bsize = face->available_sizes + i; 2093 2094 2095 if ( bsize->height < 0 ) 2096 bsize->height = (FT_Short)-bsize->height; 2097 if ( bsize->x_ppem < 0 ) 2098 bsize->x_ppem = (FT_Short)-bsize->x_ppem; 2099 if ( bsize->y_ppem < 0 ) 2100 bsize->y_ppem = -bsize->y_ppem; 2101 } 2102 } 2103 2104 /* initialize internal face data */ 2105 { 2106 FT_Face_Internal internal = face->internal; 2107 2108 2109 internal->transform_matrix.xx = 0x10000L; 2110 internal->transform_matrix.xy = 0; 2111 internal->transform_matrix.yx = 0; 2112 internal->transform_matrix.yy = 0x10000L; 2113 2114 internal->transform_delta.x = 0; 2115 internal->transform_delta.y = 0; 2116 } 2117 2118 if ( aface ) 2119 *aface = face; 2120 else 2121 FT_Done_Face( face ); 2122 2123 goto Exit; 2124 2125 Fail: 2126 FT_Done_Face( face ); 2127 2128 Exit: 2129 FT_TRACE4(( "FT_Open_Face: Return %d\n", error )); 2130 2131 return error; 2132 } 2133 2134 2135 /* documentation is in freetype.h */ 2136 2137 FT_EXPORT_DEF( FT_Error ) FT_Attach_File(FT_Face face,const char * filepathname)2138 FT_Attach_File( FT_Face face, 2139 const char* filepathname ) 2140 { 2141 FT_Open_Args open; 2142 2143 2144 /* test for valid `face' delayed to FT_Attach_Stream() */ 2145 2146 if ( !filepathname ) 2147 return FT_Err_Invalid_Argument; 2148 2149 open.stream = NULL; 2150 open.flags = FT_OPEN_PATHNAME; 2151 open.pathname = (char*)filepathname; 2152 2153 return FT_Attach_Stream( face, &open ); 2154 } 2155 2156 2157 /* documentation is in freetype.h */ 2158 2159 FT_EXPORT_DEF( FT_Error ) FT_Attach_Stream(FT_Face face,FT_Open_Args * parameters)2160 FT_Attach_Stream( FT_Face face, 2161 FT_Open_Args* parameters ) 2162 { 2163 FT_Stream stream; 2164 FT_Error error; 2165 FT_Driver driver; 2166 2167 FT_Driver_Class clazz; 2168 2169 2170 /* test for valid `parameters' delayed to FT_Stream_New() */ 2171 2172 if ( !face ) 2173 return FT_Err_Invalid_Face_Handle; 2174 2175 driver = face->driver; 2176 if ( !driver ) 2177 return FT_Err_Invalid_Driver_Handle; 2178 2179 error = FT_Stream_New( driver->root.library, parameters, &stream ); 2180 if ( error ) 2181 goto Exit; 2182 2183 /* we implement FT_Attach_Stream in each driver through the */ 2184 /* `attach_file' interface */ 2185 2186 error = FT_Err_Unimplemented_Feature; 2187 clazz = driver->clazz; 2188 if ( clazz->attach_file ) 2189 error = clazz->attach_file( face, stream ); 2190 2191 /* close the attached stream */ 2192 FT_Stream_Free( stream, 2193 (FT_Bool)( parameters->stream && 2194 ( parameters->flags & FT_OPEN_STREAM ) ) ); 2195 2196 Exit: 2197 return error; 2198 } 2199 2200 2201 /* documentation is in freetype.h */ 2202 2203 FT_EXPORT_DEF( FT_Error ) FT_Done_Face(FT_Face face)2204 FT_Done_Face( FT_Face face ) 2205 { 2206 FT_Error error; 2207 FT_Driver driver; 2208 FT_Memory memory; 2209 FT_ListNode node; 2210 2211 2212 error = FT_Err_Invalid_Face_Handle; 2213 if ( face && face->driver ) 2214 { 2215 driver = face->driver; 2216 memory = driver->root.memory; 2217 2218 /* find face in driver's list */ 2219 node = FT_List_Find( &driver->faces_list, face ); 2220 if ( node ) 2221 { 2222 /* remove face object from the driver's list */ 2223 FT_List_Remove( &driver->faces_list, node ); 2224 FT_FREE( node ); 2225 2226 /* now destroy the object proper */ 2227 destroy_face( memory, face, driver ); 2228 error = FT_Err_Ok; 2229 } 2230 } 2231 return error; 2232 } 2233 2234 2235 /* documentation is in ftobjs.h */ 2236 2237 FT_EXPORT_DEF( FT_Error ) FT_New_Size(FT_Face face,FT_Size * asize)2238 FT_New_Size( FT_Face face, 2239 FT_Size *asize ) 2240 { 2241 FT_Error error; 2242 FT_Memory memory; 2243 FT_Driver driver; 2244 FT_Driver_Class clazz; 2245 2246 FT_Size size = 0; 2247 FT_ListNode node = 0; 2248 2249 2250 if ( !face ) 2251 return FT_Err_Invalid_Face_Handle; 2252 2253 if ( !asize ) 2254 return FT_Err_Invalid_Size_Handle; 2255 2256 if ( !face->driver ) 2257 return FT_Err_Invalid_Driver_Handle; 2258 2259 *asize = 0; 2260 2261 driver = face->driver; 2262 clazz = driver->clazz; 2263 memory = face->memory; 2264 2265 /* Allocate new size object and perform basic initialisation */ 2266 if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) ) 2267 goto Exit; 2268 2269 size->face = face; 2270 2271 /* for now, do not use any internal fields in size objects */ 2272 size->internal = 0; 2273 2274 if ( clazz->init_size ) 2275 error = clazz->init_size( size ); 2276 2277 /* in case of success, add to the face's list */ 2278 if ( !error ) 2279 { 2280 *asize = size; 2281 node->data = size; 2282 FT_List_Add( &face->sizes_list, node ); 2283 } 2284 2285 Exit: 2286 if ( error ) 2287 { 2288 FT_FREE( node ); 2289 FT_FREE( size ); 2290 } 2291 2292 return error; 2293 } 2294 2295 2296 /* documentation is in ftobjs.h */ 2297 2298 FT_EXPORT_DEF( FT_Error ) FT_Done_Size(FT_Size size)2299 FT_Done_Size( FT_Size size ) 2300 { 2301 FT_Error error; 2302 FT_Driver driver; 2303 FT_Memory memory; 2304 FT_Face face; 2305 FT_ListNode node; 2306 2307 2308 if ( !size ) 2309 return FT_Err_Invalid_Size_Handle; 2310 2311 face = size->face; 2312 if ( !face ) 2313 return FT_Err_Invalid_Face_Handle; 2314 2315 driver = face->driver; 2316 if ( !driver ) 2317 return FT_Err_Invalid_Driver_Handle; 2318 2319 memory = driver->root.memory; 2320 2321 error = FT_Err_Ok; 2322 node = FT_List_Find( &face->sizes_list, size ); 2323 if ( node ) 2324 { 2325 FT_List_Remove( &face->sizes_list, node ); 2326 FT_FREE( node ); 2327 2328 if ( face->size == size ) 2329 { 2330 face->size = 0; 2331 if ( face->sizes_list.head ) 2332 face->size = (FT_Size)(face->sizes_list.head->data); 2333 } 2334 2335 destroy_size( memory, size, driver ); 2336 } 2337 else 2338 error = FT_Err_Invalid_Size_Handle; 2339 2340 return error; 2341 } 2342 2343 2344 /* documentation is in ftobjs.h */ 2345 2346 FT_BASE_DEF( FT_Error ) FT_Match_Size(FT_Face face,FT_Size_Request req,FT_Bool ignore_width,FT_ULong * size_index)2347 FT_Match_Size( FT_Face face, 2348 FT_Size_Request req, 2349 FT_Bool ignore_width, 2350 FT_ULong* size_index ) 2351 { 2352 FT_Int i; 2353 FT_Long w, h; 2354 2355 2356 if ( !FT_HAS_FIXED_SIZES( face ) ) 2357 return FT_Err_Invalid_Face_Handle; 2358 2359 /* FT_Bitmap_Size doesn't provide enough info... */ 2360 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL ) 2361 return FT_Err_Unimplemented_Feature; 2362 2363 w = FT_REQUEST_WIDTH ( req ); 2364 h = FT_REQUEST_HEIGHT( req ); 2365 2366 if ( req->width && !req->height ) 2367 h = w; 2368 else if ( !req->width && req->height ) 2369 w = h; 2370 2371 w = FT_PIX_ROUND( w ); 2372 h = FT_PIX_ROUND( h ); 2373 2374 for ( i = 0; i < face->num_fixed_sizes; i++ ) 2375 { 2376 FT_Bitmap_Size* bsize = face->available_sizes + i; 2377 2378 2379 if ( h != FT_PIX_ROUND( bsize->y_ppem ) ) 2380 continue; 2381 2382 if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width ) 2383 { 2384 if ( size_index ) 2385 *size_index = (FT_ULong)i; 2386 2387 return FT_Err_Ok; 2388 } 2389 } 2390 2391 return FT_Err_Invalid_Pixel_Size; 2392 } 2393 2394 2395 /* documentation is in ftobjs.h */ 2396 2397 FT_BASE_DEF( void ) ft_synthesize_vertical_metrics(FT_Glyph_Metrics * metrics,FT_Pos advance)2398 ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics, 2399 FT_Pos advance ) 2400 { 2401 /* the factor 1.2 is a heuristical value */ 2402 if ( !advance ) 2403 advance = metrics->height * 12 / 10; 2404 2405 metrics->vertBearingX = -( metrics->width / 2 ); 2406 metrics->vertBearingY = ( advance - metrics->height ) / 2; 2407 metrics->vertAdvance = advance; 2408 } 2409 2410 2411 static void ft_recompute_scaled_metrics(FT_Face face,FT_Size_Metrics * metrics)2412 ft_recompute_scaled_metrics( FT_Face face, 2413 FT_Size_Metrics* metrics ) 2414 { 2415 /* Compute root ascender, descender, test height, and max_advance */ 2416 2417 #ifdef GRID_FIT_METRICS 2418 metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender, 2419 metrics->y_scale ) ); 2420 2421 metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender, 2422 metrics->y_scale ) ); 2423 2424 metrics->height = FT_PIX_ROUND( FT_MulFix( face->height, 2425 metrics->y_scale ) ); 2426 2427 metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width, 2428 metrics->x_scale ) ); 2429 #else /* !GRID_FIT_METRICS */ 2430 metrics->ascender = FT_MulFix( face->ascender, 2431 metrics->y_scale ); 2432 2433 metrics->descender = FT_MulFix( face->descender, 2434 metrics->y_scale ); 2435 2436 metrics->height = FT_MulFix( face->height, 2437 metrics->y_scale ); 2438 2439 metrics->max_advance = FT_MulFix( face->max_advance_width, 2440 metrics->x_scale ); 2441 #endif /* !GRID_FIT_METRICS */ 2442 } 2443 2444 2445 FT_BASE_DEF( void ) FT_Select_Metrics(FT_Face face,FT_ULong strike_index)2446 FT_Select_Metrics( FT_Face face, 2447 FT_ULong strike_index ) 2448 { 2449 FT_Size_Metrics* metrics; 2450 FT_Bitmap_Size* bsize; 2451 2452 2453 metrics = &face->size->metrics; 2454 bsize = face->available_sizes + strike_index; 2455 2456 metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 ); 2457 metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 ); 2458 2459 if ( FT_IS_SCALABLE( face ) ) 2460 { 2461 metrics->x_scale = FT_DivFix( bsize->x_ppem, 2462 face->units_per_EM ); 2463 metrics->y_scale = FT_DivFix( bsize->y_ppem, 2464 face->units_per_EM ); 2465 2466 ft_recompute_scaled_metrics( face, metrics ); 2467 } 2468 else 2469 { 2470 metrics->x_scale = 1L << 16; 2471 metrics->y_scale = 1L << 16; 2472 metrics->ascender = bsize->y_ppem; 2473 metrics->descender = 0; 2474 metrics->height = bsize->height << 6; 2475 metrics->max_advance = bsize->x_ppem; 2476 } 2477 } 2478 2479 2480 FT_BASE_DEF( void ) FT_Request_Metrics(FT_Face face,FT_Size_Request req)2481 FT_Request_Metrics( FT_Face face, 2482 FT_Size_Request req ) 2483 { 2484 FT_Size_Metrics* metrics; 2485 2486 2487 metrics = &face->size->metrics; 2488 2489 if ( FT_IS_SCALABLE( face ) ) 2490 { 2491 FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0; 2492 2493 2494 switch ( req->type ) 2495 { 2496 case FT_SIZE_REQUEST_TYPE_NOMINAL: 2497 w = h = face->units_per_EM; 2498 break; 2499 2500 case FT_SIZE_REQUEST_TYPE_REAL_DIM: 2501 w = h = face->ascender - face->descender; 2502 break; 2503 2504 case FT_SIZE_REQUEST_TYPE_BBOX: 2505 w = face->bbox.xMax - face->bbox.xMin; 2506 h = face->bbox.yMax - face->bbox.yMin; 2507 break; 2508 2509 case FT_SIZE_REQUEST_TYPE_CELL: 2510 w = face->max_advance_width; 2511 h = face->ascender - face->descender; 2512 break; 2513 2514 case FT_SIZE_REQUEST_TYPE_SCALES: 2515 metrics->x_scale = (FT_Fixed)req->width; 2516 metrics->y_scale = (FT_Fixed)req->height; 2517 if ( !metrics->x_scale ) 2518 metrics->x_scale = metrics->y_scale; 2519 else if ( !metrics->y_scale ) 2520 metrics->y_scale = metrics->x_scale; 2521 goto Calculate_Ppem; 2522 2523 case FT_SIZE_REQUEST_TYPE_MAX: 2524 break; 2525 } 2526 2527 /* to be on the safe side */ 2528 if ( w < 0 ) 2529 w = -w; 2530 2531 if ( h < 0 ) 2532 h = -h; 2533 2534 scaled_w = FT_REQUEST_WIDTH ( req ); 2535 scaled_h = FT_REQUEST_HEIGHT( req ); 2536 2537 /* determine scales */ 2538 if ( req->width ) 2539 { 2540 metrics->x_scale = FT_DivFix( scaled_w, w ); 2541 2542 if ( req->height ) 2543 { 2544 metrics->y_scale = FT_DivFix( scaled_h, h ); 2545 2546 if ( req->type == FT_SIZE_REQUEST_TYPE_CELL ) 2547 { 2548 if ( metrics->y_scale > metrics->x_scale ) 2549 metrics->y_scale = metrics->x_scale; 2550 else 2551 metrics->x_scale = metrics->y_scale; 2552 } 2553 } 2554 else 2555 { 2556 metrics->y_scale = metrics->x_scale; 2557 scaled_h = FT_MulDiv( scaled_w, h, w ); 2558 } 2559 } 2560 else 2561 { 2562 metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h ); 2563 scaled_w = FT_MulDiv( scaled_h, w, h ); 2564 } 2565 2566 Calculate_Ppem: 2567 /* calculate the ppems */ 2568 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL ) 2569 { 2570 scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale ); 2571 scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale ); 2572 } 2573 2574 metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 ); 2575 metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 ); 2576 2577 ft_recompute_scaled_metrics( face, metrics ); 2578 } 2579 else 2580 { 2581 FT_ZERO( metrics ); 2582 metrics->x_scale = 1L << 16; 2583 metrics->y_scale = 1L << 16; 2584 } 2585 } 2586 2587 2588 /* documentation is in freetype.h */ 2589 2590 FT_EXPORT_DEF( FT_Error ) FT_Select_Size(FT_Face face,FT_Int strike_index)2591 FT_Select_Size( FT_Face face, 2592 FT_Int strike_index ) 2593 { 2594 FT_Driver_Class clazz; 2595 2596 2597 if ( !face || !FT_HAS_FIXED_SIZES( face ) ) 2598 return FT_Err_Invalid_Face_Handle; 2599 2600 if ( strike_index < 0 || strike_index >= face->num_fixed_sizes ) 2601 return FT_Err_Invalid_Argument; 2602 2603 clazz = face->driver->clazz; 2604 2605 if ( clazz->select_size ) 2606 return clazz->select_size( face->size, (FT_ULong)strike_index ); 2607 2608 FT_Select_Metrics( face, (FT_ULong)strike_index ); 2609 2610 return FT_Err_Ok; 2611 } 2612 2613 2614 /* documentation is in freetype.h */ 2615 2616 FT_EXPORT_DEF( FT_Error ) FT_Request_Size(FT_Face face,FT_Size_Request req)2617 FT_Request_Size( FT_Face face, 2618 FT_Size_Request req ) 2619 { 2620 FT_Driver_Class clazz; 2621 FT_ULong strike_index; 2622 2623 2624 if ( !face ) 2625 return FT_Err_Invalid_Face_Handle; 2626 2627 if ( !req || req->width < 0 || req->height < 0 || 2628 req->type >= FT_SIZE_REQUEST_TYPE_MAX ) 2629 return FT_Err_Invalid_Argument; 2630 2631 clazz = face->driver->clazz; 2632 2633 if ( clazz->request_size ) 2634 return clazz->request_size( face->size, req ); 2635 2636 /* 2637 * The reason that a driver doesn't have `request_size' defined is 2638 * either that the scaling here suffices or that the supported formats 2639 * are bitmap-only and size matching is not implemented. 2640 * 2641 * In the latter case, a simple size matching is done. 2642 */ 2643 if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) ) 2644 { 2645 FT_Error error; 2646 2647 2648 error = FT_Match_Size( face, req, 0, &strike_index ); 2649 if ( error ) 2650 return error; 2651 2652 FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n", 2653 strike_index )); 2654 2655 return FT_Select_Size( face, (FT_Int)strike_index ); 2656 } 2657 2658 FT_Request_Metrics( face, req ); 2659 2660 return FT_Err_Ok; 2661 } 2662 2663 2664 /* documentation is in freetype.h */ 2665 2666 FT_EXPORT_DEF( FT_Error ) FT_Set_Char_Size(FT_Face face,FT_F26Dot6 char_width,FT_F26Dot6 char_height,FT_UInt horz_resolution,FT_UInt vert_resolution)2667 FT_Set_Char_Size( FT_Face face, 2668 FT_F26Dot6 char_width, 2669 FT_F26Dot6 char_height, 2670 FT_UInt horz_resolution, 2671 FT_UInt vert_resolution ) 2672 { 2673 FT_Size_RequestRec req; 2674 2675 2676 if ( !char_width ) 2677 char_width = char_height; 2678 else if ( !char_height ) 2679 char_height = char_width; 2680 2681 if ( !horz_resolution ) 2682 horz_resolution = vert_resolution; 2683 else if ( !vert_resolution ) 2684 vert_resolution = horz_resolution; 2685 2686 if ( char_width < 1 * 64 ) 2687 char_width = 1 * 64; 2688 if ( char_height < 1 * 64 ) 2689 char_height = 1 * 64; 2690 2691 if ( !horz_resolution ) 2692 horz_resolution = vert_resolution = 72; 2693 2694 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; 2695 req.width = char_width; 2696 req.height = char_height; 2697 req.horiResolution = horz_resolution; 2698 req.vertResolution = vert_resolution; 2699 2700 return FT_Request_Size( face, &req ); 2701 } 2702 2703 2704 /* documentation is in freetype.h */ 2705 2706 FT_EXPORT_DEF( FT_Error ) FT_Set_Pixel_Sizes(FT_Face face,FT_UInt pixel_width,FT_UInt pixel_height)2707 FT_Set_Pixel_Sizes( FT_Face face, 2708 FT_UInt pixel_width, 2709 FT_UInt pixel_height ) 2710 { 2711 FT_Size_RequestRec req; 2712 2713 2714 if ( pixel_width == 0 ) 2715 pixel_width = pixel_height; 2716 else if ( pixel_height == 0 ) 2717 pixel_height = pixel_width; 2718 2719 if ( pixel_width < 1 ) 2720 pixel_width = 1; 2721 if ( pixel_height < 1 ) 2722 pixel_height = 1; 2723 2724 /* use `>=' to avoid potential compiler warning on 16bit platforms */ 2725 if ( pixel_width >= 0xFFFFU ) 2726 pixel_width = 0xFFFFU; 2727 if ( pixel_height >= 0xFFFFU ) 2728 pixel_height = 0xFFFFU; 2729 2730 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; 2731 req.width = pixel_width << 6; 2732 req.height = pixel_height << 6; 2733 req.horiResolution = 0; 2734 req.vertResolution = 0; 2735 2736 return FT_Request_Size( face, &req ); 2737 } 2738 2739 2740 /* documentation is in freetype.h */ 2741 2742 FT_EXPORT_DEF( FT_Error ) FT_Get_Kerning(FT_Face face,FT_UInt left_glyph,FT_UInt right_glyph,FT_UInt kern_mode,FT_Vector * akerning)2743 FT_Get_Kerning( FT_Face face, 2744 FT_UInt left_glyph, 2745 FT_UInt right_glyph, 2746 FT_UInt kern_mode, 2747 FT_Vector *akerning ) 2748 { 2749 FT_Error error = FT_Err_Ok; 2750 FT_Driver driver; 2751 2752 2753 if ( !face ) 2754 return FT_Err_Invalid_Face_Handle; 2755 2756 if ( !akerning ) 2757 return FT_Err_Invalid_Argument; 2758 2759 driver = face->driver; 2760 2761 akerning->x = 0; 2762 akerning->y = 0; 2763 2764 if ( driver->clazz->get_kerning ) 2765 { 2766 error = driver->clazz->get_kerning( face, 2767 left_glyph, 2768 right_glyph, 2769 akerning ); 2770 if ( !error ) 2771 { 2772 if ( kern_mode != FT_KERNING_UNSCALED ) 2773 { 2774 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale ); 2775 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale ); 2776 2777 if ( kern_mode != FT_KERNING_UNFITTED ) 2778 { 2779 /* we scale down kerning values for small ppem values */ 2780 /* to avoid that rounding makes them too big. */ 2781 /* `25' has been determined heuristically. */ 2782 if ( face->size->metrics.x_ppem < 25 ) 2783 akerning->x = FT_MulDiv( akerning->x, 2784 face->size->metrics.x_ppem, 25 ); 2785 if ( face->size->metrics.y_ppem < 25 ) 2786 akerning->y = FT_MulDiv( akerning->y, 2787 face->size->metrics.y_ppem, 25 ); 2788 2789 akerning->x = FT_PIX_ROUND( akerning->x ); 2790 akerning->y = FT_PIX_ROUND( akerning->y ); 2791 } 2792 } 2793 } 2794 } 2795 2796 return error; 2797 } 2798 2799 2800 /* documentation is in freetype.h */ 2801 2802 FT_EXPORT_DEF( FT_Error ) FT_Get_Track_Kerning(FT_Face face,FT_Fixed point_size,FT_Int degree,FT_Fixed * akerning)2803 FT_Get_Track_Kerning( FT_Face face, 2804 FT_Fixed point_size, 2805 FT_Int degree, 2806 FT_Fixed* akerning ) 2807 { 2808 FT_Service_Kerning service; 2809 FT_Error error = FT_Err_Ok; 2810 2811 2812 if ( !face ) 2813 return FT_Err_Invalid_Face_Handle; 2814 2815 if ( !akerning ) 2816 return FT_Err_Invalid_Argument; 2817 2818 FT_FACE_FIND_SERVICE( face, service, KERNING ); 2819 if ( !service ) 2820 return FT_Err_Unimplemented_Feature; 2821 2822 error = service->get_track( face, 2823 point_size, 2824 degree, 2825 akerning ); 2826 2827 return error; 2828 } 2829 2830 2831 /* documentation is in freetype.h */ 2832 2833 FT_EXPORT_DEF( FT_Error ) FT_Select_Charmap(FT_Face face,FT_Encoding encoding)2834 FT_Select_Charmap( FT_Face face, 2835 FT_Encoding encoding ) 2836 { 2837 FT_CharMap* cur; 2838 FT_CharMap* limit; 2839 2840 2841 if ( !face ) 2842 return FT_Err_Invalid_Face_Handle; 2843 2844 if ( encoding == FT_ENCODING_NONE ) 2845 return FT_Err_Invalid_Argument; 2846 2847 /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */ 2848 /* charmap available, i.e., one with UCS-4 characters, if possible. */ 2849 /* */ 2850 /* This is done by find_unicode_charmap() above, to share code. */ 2851 if ( encoding == FT_ENCODING_UNICODE ) 2852 return find_unicode_charmap( face ); 2853 2854 cur = face->charmaps; 2855 if ( !cur ) 2856 return FT_Err_Invalid_CharMap_Handle; 2857 2858 limit = cur + face->num_charmaps; 2859 2860 for ( ; cur < limit; cur++ ) 2861 { 2862 if ( cur[0]->encoding == encoding ) 2863 { 2864 face->charmap = cur[0]; 2865 return 0; 2866 } 2867 } 2868 2869 return FT_Err_Invalid_Argument; 2870 } 2871 2872 2873 /* documentation is in freetype.h */ 2874 2875 FT_EXPORT_DEF( FT_Error ) FT_Set_Charmap(FT_Face face,FT_CharMap charmap)2876 FT_Set_Charmap( FT_Face face, 2877 FT_CharMap charmap ) 2878 { 2879 FT_CharMap* cur; 2880 FT_CharMap* limit; 2881 2882 2883 if ( !face ) 2884 return FT_Err_Invalid_Face_Handle; 2885 2886 cur = face->charmaps; 2887 if ( !cur ) 2888 return FT_Err_Invalid_CharMap_Handle; 2889 if ( FT_Get_CMap_Format( charmap ) == 14 ) 2890 return FT_Err_Invalid_Argument; 2891 2892 limit = cur + face->num_charmaps; 2893 2894 for ( ; cur < limit; cur++ ) 2895 { 2896 if ( cur[0] == charmap ) 2897 { 2898 face->charmap = cur[0]; 2899 return 0; 2900 } 2901 } 2902 return FT_Err_Invalid_Argument; 2903 } 2904 2905 2906 /* documentation is in freetype.h */ 2907 2908 FT_EXPORT_DEF( FT_Int ) FT_Get_Charmap_Index(FT_CharMap charmap)2909 FT_Get_Charmap_Index( FT_CharMap charmap ) 2910 { 2911 FT_Int i; 2912 2913 2914 for ( i = 0; i < charmap->face->num_charmaps; i++ ) 2915 if ( charmap->face->charmaps[i] == charmap ) 2916 break; 2917 2918 FT_ASSERT( i < charmap->face->num_charmaps ); 2919 2920 return i; 2921 } 2922 2923 2924 static void ft_cmap_done_internal(FT_CMap cmap)2925 ft_cmap_done_internal( FT_CMap cmap ) 2926 { 2927 FT_CMap_Class clazz = cmap->clazz; 2928 FT_Face face = cmap->charmap.face; 2929 FT_Memory memory = FT_FACE_MEMORY(face); 2930 2931 2932 if ( clazz->done ) 2933 clazz->done( cmap ); 2934 2935 FT_FREE( cmap ); 2936 } 2937 2938 2939 FT_BASE_DEF( void ) FT_CMap_Done(FT_CMap cmap)2940 FT_CMap_Done( FT_CMap cmap ) 2941 { 2942 if ( cmap ) 2943 { 2944 FT_Face face = cmap->charmap.face; 2945 FT_Memory memory = FT_FACE_MEMORY( face ); 2946 FT_Error error; 2947 FT_Int i, j; 2948 2949 2950 for ( i = 0; i < face->num_charmaps; i++ ) 2951 { 2952 if ( (FT_CMap)face->charmaps[i] == cmap ) 2953 { 2954 FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1]; 2955 2956 2957 if ( FT_RENEW_ARRAY( face->charmaps, 2958 face->num_charmaps, 2959 face->num_charmaps - 1 ) ) 2960 return; 2961 2962 /* remove it from our list of charmaps */ 2963 for ( j = i + 1; j < face->num_charmaps; j++ ) 2964 { 2965 if ( j == face->num_charmaps - 1 ) 2966 face->charmaps[j - 1] = last_charmap; 2967 else 2968 face->charmaps[j - 1] = face->charmaps[j]; 2969 } 2970 2971 face->num_charmaps--; 2972 2973 if ( (FT_CMap)face->charmap == cmap ) 2974 face->charmap = NULL; 2975 2976 ft_cmap_done_internal( cmap ); 2977 2978 break; 2979 } 2980 } 2981 } 2982 } 2983 2984 2985 FT_BASE_DEF( FT_Error ) FT_CMap_New(FT_CMap_Class clazz,FT_Pointer init_data,FT_CharMap charmap,FT_CMap * acmap)2986 FT_CMap_New( FT_CMap_Class clazz, 2987 FT_Pointer init_data, 2988 FT_CharMap charmap, 2989 FT_CMap *acmap ) 2990 { 2991 FT_Error error = FT_Err_Ok; 2992 FT_Face face; 2993 FT_Memory memory; 2994 FT_CMap cmap; 2995 2996 2997 if ( clazz == NULL || charmap == NULL || charmap->face == NULL ) 2998 return FT_Err_Invalid_Argument; 2999 3000 face = charmap->face; 3001 memory = FT_FACE_MEMORY( face ); 3002 3003 if ( !FT_ALLOC( cmap, clazz->size ) ) 3004 { 3005 cmap->charmap = *charmap; 3006 cmap->clazz = clazz; 3007 3008 if ( clazz->init ) 3009 { 3010 error = clazz->init( cmap, init_data ); 3011 if ( error ) 3012 goto Fail; 3013 } 3014 3015 /* add it to our list of charmaps */ 3016 if ( FT_RENEW_ARRAY( face->charmaps, 3017 face->num_charmaps, 3018 face->num_charmaps + 1 ) ) 3019 goto Fail; 3020 3021 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap; 3022 } 3023 3024 Exit: 3025 if ( acmap ) 3026 *acmap = cmap; 3027 3028 return error; 3029 3030 Fail: 3031 ft_cmap_done_internal( cmap ); 3032 cmap = NULL; 3033 goto Exit; 3034 } 3035 3036 3037 /* documentation is in freetype.h */ 3038 3039 FT_EXPORT_DEF( FT_UInt ) FT_Get_Char_Index(FT_Face face,FT_ULong charcode)3040 FT_Get_Char_Index( FT_Face face, 3041 FT_ULong charcode ) 3042 { 3043 FT_UInt result = 0; 3044 3045 3046 if ( face && face->charmap ) 3047 { 3048 FT_CMap cmap = FT_CMAP( face->charmap ); 3049 3050 3051 result = cmap->clazz->char_index( cmap, charcode ); 3052 } 3053 return result; 3054 } 3055 3056 3057 /* documentation is in freetype.h */ 3058 3059 FT_EXPORT_DEF( FT_ULong ) FT_Get_First_Char(FT_Face face,FT_UInt * agindex)3060 FT_Get_First_Char( FT_Face face, 3061 FT_UInt *agindex ) 3062 { 3063 FT_ULong result = 0; 3064 FT_UInt gindex = 0; 3065 3066 3067 if ( face && face->charmap ) 3068 { 3069 gindex = FT_Get_Char_Index( face, 0 ); 3070 if ( gindex == 0 ) 3071 result = FT_Get_Next_Char( face, 0, &gindex ); 3072 } 3073 3074 if ( agindex ) 3075 *agindex = gindex; 3076 3077 return result; 3078 } 3079 3080 3081 /* documentation is in freetype.h */ 3082 3083 FT_EXPORT_DEF( FT_ULong ) FT_Get_Next_Char(FT_Face face,FT_ULong charcode,FT_UInt * agindex)3084 FT_Get_Next_Char( FT_Face face, 3085 FT_ULong charcode, 3086 FT_UInt *agindex ) 3087 { 3088 FT_ULong result = 0; 3089 FT_UInt gindex = 0; 3090 3091 3092 if ( face && face->charmap ) 3093 { 3094 FT_UInt32 code = (FT_UInt32)charcode; 3095 FT_CMap cmap = FT_CMAP( face->charmap ); 3096 3097 3098 gindex = cmap->clazz->char_next( cmap, &code ); 3099 result = ( gindex == 0 ) ? 0 : code; 3100 } 3101 3102 if ( agindex ) 3103 *agindex = gindex; 3104 3105 return result; 3106 } 3107 3108 3109 /* documentation is in freetype.h */ 3110 3111 FT_EXPORT_DEF( FT_UInt ) FT_Face_GetCharVariantIndex(FT_Face face,FT_ULong charcode,FT_ULong variantSelector)3112 FT_Face_GetCharVariantIndex( FT_Face face, 3113 FT_ULong charcode, 3114 FT_ULong variantSelector ) 3115 { 3116 FT_UInt result = 0; 3117 3118 3119 if ( face && face->charmap && 3120 face->charmap->encoding == FT_ENCODING_UNICODE ) 3121 { 3122 FT_CharMap charmap = find_variant_selector_charmap( face ); 3123 FT_CMap ucmap = FT_CMAP( face->charmap ); 3124 3125 3126 if ( charmap != NULL ) 3127 { 3128 FT_CMap vcmap = FT_CMAP( charmap ); 3129 3130 3131 result = vcmap->clazz->char_var_index( vcmap, ucmap, charcode, 3132 variantSelector ); 3133 } 3134 } 3135 3136 return result; 3137 } 3138 3139 3140 /* documentation is in freetype.h */ 3141 3142 FT_EXPORT_DEF( FT_Int ) FT_Face_GetCharVariantIsDefault(FT_Face face,FT_ULong charcode,FT_ULong variantSelector)3143 FT_Face_GetCharVariantIsDefault( FT_Face face, 3144 FT_ULong charcode, 3145 FT_ULong variantSelector ) 3146 { 3147 FT_Int result = -1; 3148 3149 3150 if ( face ) 3151 { 3152 FT_CharMap charmap = find_variant_selector_charmap( face ); 3153 3154 3155 if ( charmap != NULL ) 3156 { 3157 FT_CMap vcmap = FT_CMAP( charmap ); 3158 3159 3160 result = vcmap->clazz->char_var_default( vcmap, charcode, 3161 variantSelector ); 3162 } 3163 } 3164 3165 return result; 3166 } 3167 3168 3169 /* documentation is in freetype.h */ 3170 3171 FT_EXPORT_DEF( FT_UInt32* ) FT_Face_GetVariantSelectors(FT_Face face)3172 FT_Face_GetVariantSelectors( FT_Face face ) 3173 { 3174 FT_UInt32 *result = NULL; 3175 3176 3177 if ( face ) 3178 { 3179 FT_CharMap charmap = find_variant_selector_charmap( face ); 3180 3181 3182 if ( charmap != NULL ) 3183 { 3184 FT_CMap vcmap = FT_CMAP( charmap ); 3185 FT_Memory memory = FT_FACE_MEMORY( face ); 3186 3187 3188 result = vcmap->clazz->variant_list( vcmap, memory ); 3189 } 3190 } 3191 3192 return result; 3193 } 3194 3195 3196 /* documentation is in freetype.h */ 3197 3198 FT_EXPORT_DEF( FT_UInt32* ) FT_Face_GetVariantsOfChar(FT_Face face,FT_ULong charcode)3199 FT_Face_GetVariantsOfChar( FT_Face face, 3200 FT_ULong charcode ) 3201 { 3202 FT_UInt32 *result = NULL; 3203 3204 3205 if ( face ) 3206 { 3207 FT_CharMap charmap = find_variant_selector_charmap( face ); 3208 3209 3210 if ( charmap != NULL ) 3211 { 3212 FT_CMap vcmap = FT_CMAP( charmap ); 3213 FT_Memory memory = FT_FACE_MEMORY( face ); 3214 3215 3216 result = vcmap->clazz->charvariant_list( vcmap, memory, charcode ); 3217 } 3218 } 3219 return result; 3220 } 3221 3222 3223 /* documentation is in freetype.h */ 3224 3225 FT_EXPORT_DEF( FT_UInt32* ) FT_Face_GetCharsOfVariant(FT_Face face,FT_ULong variantSelector)3226 FT_Face_GetCharsOfVariant( FT_Face face, 3227 FT_ULong variantSelector ) 3228 { 3229 FT_UInt32 *result = NULL; 3230 3231 3232 if ( face ) 3233 { 3234 FT_CharMap charmap = find_variant_selector_charmap( face ); 3235 3236 3237 if ( charmap != NULL ) 3238 { 3239 FT_CMap vcmap = FT_CMAP( charmap ); 3240 FT_Memory memory = FT_FACE_MEMORY( face ); 3241 3242 3243 result = vcmap->clazz->variantchar_list( vcmap, memory, 3244 variantSelector ); 3245 } 3246 } 3247 3248 return result; 3249 } 3250 3251 3252 /* documentation is in freetype.h */ 3253 3254 FT_EXPORT_DEF( FT_UInt ) FT_Get_Name_Index(FT_Face face,FT_String * glyph_name)3255 FT_Get_Name_Index( FT_Face face, 3256 FT_String* glyph_name ) 3257 { 3258 FT_UInt result = 0; 3259 3260 3261 if ( face && FT_HAS_GLYPH_NAMES( face ) ) 3262 { 3263 FT_Service_GlyphDict service; 3264 3265 3266 FT_FACE_LOOKUP_SERVICE( face, 3267 service, 3268 GLYPH_DICT ); 3269 3270 if ( service && service->name_index ) 3271 result = service->name_index( face, glyph_name ); 3272 } 3273 3274 return result; 3275 } 3276 3277 3278 /* documentation is in freetype.h */ 3279 3280 FT_EXPORT_DEF( FT_Error ) FT_Get_Glyph_Name(FT_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)3281 FT_Get_Glyph_Name( FT_Face face, 3282 FT_UInt glyph_index, 3283 FT_Pointer buffer, 3284 FT_UInt buffer_max ) 3285 { 3286 FT_Error error = FT_Err_Invalid_Argument; 3287 3288 3289 /* clean up buffer */ 3290 if ( buffer && buffer_max > 0 ) 3291 ((FT_Byte*)buffer)[0] = 0; 3292 3293 if ( face && 3294 glyph_index <= (FT_UInt)face->num_glyphs && 3295 FT_HAS_GLYPH_NAMES( face ) ) 3296 { 3297 FT_Service_GlyphDict service; 3298 3299 3300 FT_FACE_LOOKUP_SERVICE( face, 3301 service, 3302 GLYPH_DICT ); 3303 3304 if ( service && service->get_name ) 3305 error = service->get_name( face, glyph_index, buffer, buffer_max ); 3306 } 3307 3308 return error; 3309 } 3310 3311 3312 /* documentation is in freetype.h */ 3313 3314 FT_EXPORT_DEF( const char* ) FT_Get_Postscript_Name(FT_Face face)3315 FT_Get_Postscript_Name( FT_Face face ) 3316 { 3317 const char* result = NULL; 3318 3319 3320 if ( !face ) 3321 goto Exit; 3322 3323 if ( !result ) 3324 { 3325 FT_Service_PsFontName service; 3326 3327 3328 FT_FACE_LOOKUP_SERVICE( face, 3329 service, 3330 POSTSCRIPT_FONT_NAME ); 3331 3332 if ( service && service->get_ps_font_name ) 3333 result = service->get_ps_font_name( face ); 3334 } 3335 3336 Exit: 3337 return result; 3338 } 3339 3340 3341 /* documentation is in tttables.h */ 3342 3343 FT_EXPORT_DEF( void* ) FT_Get_Sfnt_Table(FT_Face face,FT_Sfnt_Tag tag)3344 FT_Get_Sfnt_Table( FT_Face face, 3345 FT_Sfnt_Tag tag ) 3346 { 3347 void* table = 0; 3348 FT_Service_SFNT_Table service; 3349 3350 3351 if ( face && FT_IS_SFNT( face ) ) 3352 { 3353 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); 3354 if ( service != NULL ) 3355 table = service->get_table( face, tag ); 3356 } 3357 3358 return table; 3359 } 3360 3361 3362 /* documentation is in tttables.h */ 3363 3364 FT_EXPORT_DEF( FT_Error ) FT_Load_Sfnt_Table(FT_Face face,FT_ULong tag,FT_Long offset,FT_Byte * buffer,FT_ULong * length)3365 FT_Load_Sfnt_Table( FT_Face face, 3366 FT_ULong tag, 3367 FT_Long offset, 3368 FT_Byte* buffer, 3369 FT_ULong* length ) 3370 { 3371 FT_Service_SFNT_Table service; 3372 3373 3374 if ( !face || !FT_IS_SFNT( face ) ) 3375 return FT_Err_Invalid_Face_Handle; 3376 3377 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); 3378 if ( service == NULL ) 3379 return FT_Err_Unimplemented_Feature; 3380 3381 return service->load_table( face, tag, offset, buffer, length ); 3382 } 3383 3384 3385 /* documentation is in tttables.h */ 3386 3387 FT_EXPORT_DEF( FT_Error ) FT_Sfnt_Table_Info(FT_Face face,FT_UInt table_index,FT_ULong * tag,FT_ULong * length)3388 FT_Sfnt_Table_Info( FT_Face face, 3389 FT_UInt table_index, 3390 FT_ULong *tag, 3391 FT_ULong *length ) 3392 { 3393 FT_Service_SFNT_Table service; 3394 3395 3396 if ( !face || !FT_IS_SFNT( face ) ) 3397 return FT_Err_Invalid_Face_Handle; 3398 3399 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); 3400 if ( service == NULL ) 3401 return FT_Err_Unimplemented_Feature; 3402 3403 return service->table_info( face, table_index, tag, length ); 3404 } 3405 3406 3407 /* documentation is in tttables.h */ 3408 3409 FT_EXPORT_DEF( FT_ULong ) FT_Get_CMap_Language_ID(FT_CharMap charmap)3410 FT_Get_CMap_Language_ID( FT_CharMap charmap ) 3411 { 3412 FT_Service_TTCMaps service; 3413 FT_Face face; 3414 TT_CMapInfo cmap_info; 3415 3416 3417 if ( !charmap || !charmap->face ) 3418 return 0; 3419 3420 face = charmap->face; 3421 FT_FACE_FIND_SERVICE( face, service, TT_CMAP ); 3422 if ( service == NULL ) 3423 return 0; 3424 if ( service->get_cmap_info( charmap, &cmap_info )) 3425 return 0; 3426 3427 return cmap_info.language; 3428 } 3429 3430 3431 /* documentation is in tttables.h */ 3432 3433 FT_EXPORT_DEF( FT_Long ) FT_Get_CMap_Format(FT_CharMap charmap)3434 FT_Get_CMap_Format( FT_CharMap charmap ) 3435 { 3436 FT_Service_TTCMaps service; 3437 FT_Face face; 3438 TT_CMapInfo cmap_info; 3439 3440 3441 if ( !charmap || !charmap->face ) 3442 return -1; 3443 3444 face = charmap->face; 3445 FT_FACE_FIND_SERVICE( face, service, TT_CMAP ); 3446 if ( service == NULL ) 3447 return -1; 3448 if ( service->get_cmap_info( charmap, &cmap_info )) 3449 return -1; 3450 3451 return cmap_info.format; 3452 } 3453 3454 3455 /* documentation is in ftsizes.h */ 3456 3457 FT_EXPORT_DEF( FT_Error ) FT_Activate_Size(FT_Size size)3458 FT_Activate_Size( FT_Size size ) 3459 { 3460 FT_Face face; 3461 3462 3463 if ( size == NULL ) 3464 return FT_Err_Invalid_Argument; 3465 3466 face = size->face; 3467 if ( face == NULL || face->driver == NULL ) 3468 return FT_Err_Invalid_Argument; 3469 3470 /* we don't need anything more complex than that; all size objects */ 3471 /* are already listed by the face */ 3472 face->size = size; 3473 3474 return FT_Err_Ok; 3475 } 3476 3477 3478 /*************************************************************************/ 3479 /*************************************************************************/ 3480 /*************************************************************************/ 3481 /**** ****/ 3482 /**** ****/ 3483 /**** R E N D E R E R S ****/ 3484 /**** ****/ 3485 /**** ****/ 3486 /*************************************************************************/ 3487 /*************************************************************************/ 3488 /*************************************************************************/ 3489 3490 /* lookup a renderer by glyph format in the library's list */ 3491 FT_BASE_DEF( FT_Renderer ) FT_Lookup_Renderer(FT_Library library,FT_Glyph_Format format,FT_ListNode * node)3492 FT_Lookup_Renderer( FT_Library library, 3493 FT_Glyph_Format format, 3494 FT_ListNode* node ) 3495 { 3496 FT_ListNode cur; 3497 FT_Renderer result = 0; 3498 3499 3500 if ( !library ) 3501 goto Exit; 3502 3503 cur = library->renderers.head; 3504 3505 if ( node ) 3506 { 3507 if ( *node ) 3508 cur = (*node)->next; 3509 *node = 0; 3510 } 3511 3512 while ( cur ) 3513 { 3514 FT_Renderer renderer = FT_RENDERER( cur->data ); 3515 3516 3517 if ( renderer->glyph_format == format ) 3518 { 3519 if ( node ) 3520 *node = cur; 3521 3522 result = renderer; 3523 break; 3524 } 3525 cur = cur->next; 3526 } 3527 3528 Exit: 3529 return result; 3530 } 3531 3532 3533 static FT_Renderer ft_lookup_glyph_renderer(FT_GlyphSlot slot)3534 ft_lookup_glyph_renderer( FT_GlyphSlot slot ) 3535 { 3536 FT_Face face = slot->face; 3537 FT_Library library = FT_FACE_LIBRARY( face ); 3538 FT_Renderer result = library->cur_renderer; 3539 3540 3541 if ( !result || result->glyph_format != slot->format ) 3542 result = FT_Lookup_Renderer( library, slot->format, 0 ); 3543 3544 return result; 3545 } 3546 3547 3548 static void ft_set_current_renderer(FT_Library library)3549 ft_set_current_renderer( FT_Library library ) 3550 { 3551 FT_Renderer renderer; 3552 3553 3554 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 ); 3555 library->cur_renderer = renderer; 3556 } 3557 3558 3559 static FT_Error ft_add_renderer(FT_Module module)3560 ft_add_renderer( FT_Module module ) 3561 { 3562 FT_Library library = module->library; 3563 FT_Memory memory = library->memory; 3564 FT_Error error; 3565 FT_ListNode node; 3566 3567 3568 if ( FT_NEW( node ) ) 3569 goto Exit; 3570 3571 { 3572 FT_Renderer render = FT_RENDERER( module ); 3573 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz; 3574 3575 3576 render->clazz = clazz; 3577 render->glyph_format = clazz->glyph_format; 3578 3579 /* allocate raster object if needed */ 3580 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && 3581 clazz->raster_class->raster_new ) 3582 { 3583 error = clazz->raster_class->raster_new( memory, &render->raster ); 3584 if ( error ) 3585 goto Fail; 3586 3587 render->raster_render = clazz->raster_class->raster_render; 3588 render->render = clazz->render_glyph; 3589 } 3590 3591 /* add to list */ 3592 node->data = module; 3593 FT_List_Add( &library->renderers, node ); 3594 3595 ft_set_current_renderer( library ); 3596 } 3597 3598 Fail: 3599 if ( error ) 3600 FT_FREE( node ); 3601 3602 Exit: 3603 return error; 3604 } 3605 3606 3607 static void ft_remove_renderer(FT_Module module)3608 ft_remove_renderer( FT_Module module ) 3609 { 3610 FT_Library library = module->library; 3611 FT_Memory memory = library->memory; 3612 FT_ListNode node; 3613 3614 3615 node = FT_List_Find( &library->renderers, module ); 3616 if ( node ) 3617 { 3618 FT_Renderer render = FT_RENDERER( module ); 3619 3620 3621 /* release raster object, if any */ 3622 if ( render->raster ) 3623 render->clazz->raster_class->raster_done( render->raster ); 3624 3625 /* remove from list */ 3626 FT_List_Remove( &library->renderers, node ); 3627 FT_FREE( node ); 3628 3629 ft_set_current_renderer( library ); 3630 } 3631 } 3632 3633 3634 /* documentation is in ftrender.h */ 3635 3636 FT_EXPORT_DEF( FT_Renderer ) FT_Get_Renderer(FT_Library library,FT_Glyph_Format format)3637 FT_Get_Renderer( FT_Library library, 3638 FT_Glyph_Format format ) 3639 { 3640 /* test for valid `library' delayed to FT_Lookup_Renderer() */ 3641 3642 return FT_Lookup_Renderer( library, format, 0 ); 3643 } 3644 3645 3646 /* documentation is in ftrender.h */ 3647 3648 FT_EXPORT_DEF( FT_Error ) FT_Set_Renderer(FT_Library library,FT_Renderer renderer,FT_UInt num_params,FT_Parameter * parameters)3649 FT_Set_Renderer( FT_Library library, 3650 FT_Renderer renderer, 3651 FT_UInt num_params, 3652 FT_Parameter* parameters ) 3653 { 3654 FT_ListNode node; 3655 FT_Error error = FT_Err_Ok; 3656 3657 3658 if ( !library ) 3659 return FT_Err_Invalid_Library_Handle; 3660 3661 if ( !renderer ) 3662 return FT_Err_Invalid_Argument; 3663 3664 node = FT_List_Find( &library->renderers, renderer ); 3665 if ( !node ) 3666 { 3667 error = FT_Err_Invalid_Argument; 3668 goto Exit; 3669 } 3670 3671 FT_List_Up( &library->renderers, node ); 3672 3673 if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE ) 3674 library->cur_renderer = renderer; 3675 3676 if ( num_params > 0 ) 3677 { 3678 FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode; 3679 3680 3681 for ( ; num_params > 0; num_params-- ) 3682 { 3683 error = set_mode( renderer, parameters->tag, parameters->data ); 3684 if ( error ) 3685 break; 3686 } 3687 } 3688 3689 Exit: 3690 return error; 3691 } 3692 3693 3694 FT_BASE_DEF( FT_Error ) FT_Render_Glyph_Internal(FT_Library library,FT_GlyphSlot slot,FT_Render_Mode render_mode)3695 FT_Render_Glyph_Internal( FT_Library library, 3696 FT_GlyphSlot slot, 3697 FT_Render_Mode render_mode ) 3698 { 3699 FT_Error error = FT_Err_Ok; 3700 FT_Renderer renderer; 3701 3702 3703 /* if it is already a bitmap, no need to do anything */ 3704 switch ( slot->format ) 3705 { 3706 case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */ 3707 break; 3708 3709 default: 3710 { 3711 FT_ListNode node = 0; 3712 FT_Bool update = 0; 3713 3714 3715 /* small shortcut for the very common case */ 3716 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) 3717 { 3718 renderer = library->cur_renderer; 3719 node = library->renderers.head; 3720 } 3721 else 3722 renderer = FT_Lookup_Renderer( library, slot->format, &node ); 3723 3724 error = FT_Err_Unimplemented_Feature; 3725 while ( renderer ) 3726 { 3727 error = renderer->render( renderer, slot, render_mode, NULL ); 3728 if ( !error || 3729 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph ) 3730 break; 3731 3732 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ 3733 /* is unsupported by the current renderer for this glyph image */ 3734 /* format. */ 3735 3736 /* now, look for another renderer that supports the same */ 3737 /* format. */ 3738 renderer = FT_Lookup_Renderer( library, slot->format, &node ); 3739 update = 1; 3740 } 3741 3742 /* if we changed the current renderer for the glyph image format */ 3743 /* we need to select it as the next current one */ 3744 if ( !error && update && renderer ) 3745 FT_Set_Renderer( library, renderer, 0, 0 ); 3746 } 3747 } 3748 3749 return error; 3750 } 3751 3752 3753 /* documentation is in freetype.h */ 3754 3755 FT_EXPORT_DEF( FT_Error ) FT_Render_Glyph(FT_GlyphSlot slot,FT_Render_Mode render_mode)3756 FT_Render_Glyph( FT_GlyphSlot slot, 3757 FT_Render_Mode render_mode ) 3758 { 3759 FT_Library library; 3760 3761 3762 if ( !slot ) 3763 return FT_Err_Invalid_Argument; 3764 3765 library = FT_FACE_LIBRARY( slot->face ); 3766 3767 return FT_Render_Glyph_Internal( library, slot, render_mode ); 3768 } 3769 3770 3771 /*************************************************************************/ 3772 /*************************************************************************/ 3773 /*************************************************************************/ 3774 /**** ****/ 3775 /**** ****/ 3776 /**** M O D U L E S ****/ 3777 /**** ****/ 3778 /**** ****/ 3779 /*************************************************************************/ 3780 /*************************************************************************/ 3781 /*************************************************************************/ 3782 3783 3784 /*************************************************************************/ 3785 /* */ 3786 /* <Function> */ 3787 /* Destroy_Module */ 3788 /* */ 3789 /* <Description> */ 3790 /* Destroys a given module object. For drivers, this also destroys */ 3791 /* all child faces. */ 3792 /* */ 3793 /* <InOut> */ 3794 /* module :: A handle to the target driver object. */ 3795 /* */ 3796 /* <Note> */ 3797 /* The driver _must_ be LOCKED! */ 3798 /* */ 3799 static void Destroy_Module(FT_Module module)3800 Destroy_Module( FT_Module module ) 3801 { 3802 FT_Memory memory = module->memory; 3803 FT_Module_Class* clazz = module->clazz; 3804 FT_Library library = module->library; 3805 3806 3807 /* finalize client-data - before anything else */ 3808 if ( module->generic.finalizer ) 3809 module->generic.finalizer( module ); 3810 3811 if ( library && library->auto_hinter == module ) 3812 library->auto_hinter = 0; 3813 3814 /* if the module is a renderer */ 3815 if ( FT_MODULE_IS_RENDERER( module ) ) 3816 ft_remove_renderer( module ); 3817 3818 /* if the module is a font driver, add some steps */ 3819 if ( FT_MODULE_IS_DRIVER( module ) ) 3820 Destroy_Driver( FT_DRIVER( module ) ); 3821 3822 /* finalize the module object */ 3823 if ( clazz->module_done ) 3824 clazz->module_done( module ); 3825 3826 /* discard it */ 3827 FT_FREE( module ); 3828 } 3829 3830 3831 /* documentation is in ftmodapi.h */ 3832 3833 FT_EXPORT_DEF( FT_Error ) FT_Add_Module(FT_Library library,const FT_Module_Class * clazz)3834 FT_Add_Module( FT_Library library, 3835 const FT_Module_Class* clazz ) 3836 { 3837 FT_Error error; 3838 FT_Memory memory; 3839 FT_Module module; 3840 FT_UInt nn; 3841 3842 3843 #define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \ 3844 FREETYPE_MINOR ) 3845 3846 if ( !library ) 3847 return FT_Err_Invalid_Library_Handle; 3848 3849 if ( !clazz ) 3850 return FT_Err_Invalid_Argument; 3851 3852 /* check freetype version */ 3853 if ( clazz->module_requires > FREETYPE_VER_FIXED ) 3854 return FT_Err_Invalid_Version; 3855 3856 /* look for a module with the same name in the library's table */ 3857 for ( nn = 0; nn < library->num_modules; nn++ ) 3858 { 3859 module = library->modules[nn]; 3860 if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 ) 3861 { 3862 /* this installed module has the same name, compare their versions */ 3863 if ( clazz->module_version <= module->clazz->module_version ) 3864 return FT_Err_Lower_Module_Version; 3865 3866 /* remove the module from our list, then exit the loop to replace */ 3867 /* it by our new version.. */ 3868 FT_Remove_Module( library, module ); 3869 break; 3870 } 3871 } 3872 3873 memory = library->memory; 3874 error = FT_Err_Ok; 3875 3876 if ( library->num_modules >= FT_MAX_MODULES ) 3877 { 3878 error = FT_Err_Too_Many_Drivers; 3879 goto Exit; 3880 } 3881 3882 /* allocate module object */ 3883 if ( FT_ALLOC( module, clazz->module_size ) ) 3884 goto Exit; 3885 3886 /* base initialization */ 3887 module->library = library; 3888 module->memory = memory; 3889 module->clazz = (FT_Module_Class*)clazz; 3890 3891 /* check whether the module is a renderer - this must be performed */ 3892 /* before the normal module initialization */ 3893 if ( FT_MODULE_IS_RENDERER( module ) ) 3894 { 3895 /* add to the renderers list */ 3896 error = ft_add_renderer( module ); 3897 if ( error ) 3898 goto Fail; 3899 } 3900 3901 /* is the module a auto-hinter? */ 3902 if ( FT_MODULE_IS_HINTER( module ) ) 3903 library->auto_hinter = module; 3904 3905 /* if the module is a font driver */ 3906 if ( FT_MODULE_IS_DRIVER( module ) ) 3907 { 3908 /* allocate glyph loader if needed */ 3909 FT_Driver driver = FT_DRIVER( module ); 3910 3911 3912 driver->clazz = (FT_Driver_Class)module->clazz; 3913 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 3914 { 3915 error = FT_GlyphLoader_New( memory, &driver->glyph_loader ); 3916 if ( error ) 3917 goto Fail; 3918 } 3919 } 3920 3921 if ( clazz->module_init ) 3922 { 3923 error = clazz->module_init( module ); 3924 if ( error ) 3925 goto Fail; 3926 } 3927 3928 /* add module to the library's table */ 3929 library->modules[library->num_modules++] = module; 3930 3931 Exit: 3932 return error; 3933 3934 Fail: 3935 if ( FT_MODULE_IS_DRIVER( module ) ) 3936 { 3937 FT_Driver driver = FT_DRIVER( module ); 3938 3939 3940 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 3941 FT_GlyphLoader_Done( driver->glyph_loader ); 3942 } 3943 3944 if ( FT_MODULE_IS_RENDERER( module ) ) 3945 { 3946 FT_Renderer renderer = FT_RENDERER( module ); 3947 3948 3949 if ( renderer->raster ) 3950 renderer->clazz->raster_class->raster_done( renderer->raster ); 3951 } 3952 3953 FT_FREE( module ); 3954 goto Exit; 3955 } 3956 3957 3958 /* documentation is in ftmodapi.h */ 3959 3960 FT_EXPORT_DEF( FT_Module ) FT_Get_Module(FT_Library library,const char * module_name)3961 FT_Get_Module( FT_Library library, 3962 const char* module_name ) 3963 { 3964 FT_Module result = 0; 3965 FT_Module* cur; 3966 FT_Module* limit; 3967 3968 3969 if ( !library || !module_name ) 3970 return result; 3971 3972 cur = library->modules; 3973 limit = cur + library->num_modules; 3974 3975 for ( ; cur < limit; cur++ ) 3976 if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 ) 3977 { 3978 result = cur[0]; 3979 break; 3980 } 3981 3982 return result; 3983 } 3984 3985 3986 /* documentation is in ftobjs.h */ 3987 3988 FT_BASE_DEF( const void* ) FT_Get_Module_Interface(FT_Library library,const char * mod_name)3989 FT_Get_Module_Interface( FT_Library library, 3990 const char* mod_name ) 3991 { 3992 FT_Module module; 3993 3994 3995 /* test for valid `library' delayed to FT_Get_Module() */ 3996 3997 module = FT_Get_Module( library, mod_name ); 3998 3999 return module ? module->clazz->module_interface : 0; 4000 } 4001 4002 4003 FT_BASE_DEF( FT_Pointer ) ft_module_get_service(FT_Module module,const char * service_id)4004 ft_module_get_service( FT_Module module, 4005 const char* service_id ) 4006 { 4007 FT_Pointer result = NULL; 4008 4009 if ( module ) 4010 { 4011 FT_ASSERT( module->clazz && module->clazz->get_interface ); 4012 4013 /* first, look for the service in the module 4014 */ 4015 if ( module->clazz->get_interface ) 4016 result = module->clazz->get_interface( module, service_id ); 4017 4018 if ( result == NULL ) 4019 { 4020 /* we didn't find it, look in all other modules then 4021 */ 4022 FT_Library library = module->library; 4023 FT_Module* cur = library->modules; 4024 FT_Module* limit = cur + library->num_modules; 4025 4026 for ( ; cur < limit; cur++ ) 4027 { 4028 if ( cur[0] != module ) 4029 { 4030 FT_ASSERT( cur[0]->clazz ); 4031 4032 if ( cur[0]->clazz->get_interface ) 4033 { 4034 result = cur[0]->clazz->get_interface( cur[0], service_id ); 4035 if ( result != NULL ) 4036 break; 4037 } 4038 } 4039 } 4040 } 4041 } 4042 4043 return result; 4044 } 4045 4046 4047 /* documentation is in ftmodapi.h */ 4048 4049 FT_EXPORT_DEF( FT_Error ) FT_Remove_Module(FT_Library library,FT_Module module)4050 FT_Remove_Module( FT_Library library, 4051 FT_Module module ) 4052 { 4053 /* try to find the module from the table, then remove it from there */ 4054 4055 if ( !library ) 4056 return FT_Err_Invalid_Library_Handle; 4057 4058 if ( module ) 4059 { 4060 FT_Module* cur = library->modules; 4061 FT_Module* limit = cur + library->num_modules; 4062 4063 4064 for ( ; cur < limit; cur++ ) 4065 { 4066 if ( cur[0] == module ) 4067 { 4068 /* remove it from the table */ 4069 library->num_modules--; 4070 limit--; 4071 while ( cur < limit ) 4072 { 4073 cur[0] = cur[1]; 4074 cur++; 4075 } 4076 limit[0] = 0; 4077 4078 /* destroy the module */ 4079 Destroy_Module( module ); 4080 4081 return FT_Err_Ok; 4082 } 4083 } 4084 } 4085 return FT_Err_Invalid_Driver_Handle; 4086 } 4087 4088 4089 /*************************************************************************/ 4090 /*************************************************************************/ 4091 /*************************************************************************/ 4092 /**** ****/ 4093 /**** ****/ 4094 /**** L I B R A R Y ****/ 4095 /**** ****/ 4096 /**** ****/ 4097 /*************************************************************************/ 4098 /*************************************************************************/ 4099 /*************************************************************************/ 4100 4101 4102 /* documentation is in ftmodapi.h */ 4103 4104 FT_EXPORT_DEF( FT_Error ) FT_New_Library(FT_Memory memory,FT_Library * alibrary)4105 FT_New_Library( FT_Memory memory, 4106 FT_Library *alibrary ) 4107 { 4108 FT_Library library = 0; 4109 FT_Error error; 4110 4111 4112 if ( !memory ) 4113 return FT_Err_Invalid_Argument; 4114 4115 #ifdef FT_DEBUG_LEVEL_ERROR 4116 /* init debugging support */ 4117 ft_debug_init(); 4118 #endif 4119 4120 /* first of all, allocate the library object */ 4121 if ( FT_NEW( library ) ) 4122 return error; 4123 4124 library->memory = memory; 4125 4126 /* allocate the render pool */ 4127 library->raster_pool_size = FT_RENDER_POOL_SIZE; 4128 #if FT_RENDER_POOL_SIZE > 0 4129 if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) ) 4130 goto Fail; 4131 #endif 4132 4133 /* That's ok now */ 4134 *alibrary = library; 4135 4136 return FT_Err_Ok; 4137 4138 Fail: 4139 FT_FREE( library ); 4140 return error; 4141 } 4142 4143 4144 /* documentation is in freetype.h */ 4145 4146 FT_EXPORT_DEF( void ) FT_Library_Version(FT_Library library,FT_Int * amajor,FT_Int * aminor,FT_Int * apatch)4147 FT_Library_Version( FT_Library library, 4148 FT_Int *amajor, 4149 FT_Int *aminor, 4150 FT_Int *apatch ) 4151 { 4152 FT_Int major = 0; 4153 FT_Int minor = 0; 4154 FT_Int patch = 0; 4155 4156 4157 if ( library ) 4158 { 4159 major = library->version_major; 4160 minor = library->version_minor; 4161 patch = library->version_patch; 4162 } 4163 4164 if ( amajor ) 4165 *amajor = major; 4166 4167 if ( aminor ) 4168 *aminor = minor; 4169 4170 if ( apatch ) 4171 *apatch = patch; 4172 } 4173 4174 4175 /* documentation is in ftmodapi.h */ 4176 4177 FT_EXPORT_DEF( FT_Error ) FT_Done_Library(FT_Library library)4178 FT_Done_Library( FT_Library library ) 4179 { 4180 FT_Memory memory; 4181 4182 4183 if ( !library ) 4184 return FT_Err_Invalid_Library_Handle; 4185 4186 memory = library->memory; 4187 4188 /* Discard client-data */ 4189 if ( library->generic.finalizer ) 4190 library->generic.finalizer( library ); 4191 4192 /* Close all faces in the library. If we don't do 4193 * this, we can have some subtle memory leaks. 4194 * Example: 4195 * 4196 * - the cff font driver uses the pshinter module in cff_size_done 4197 * - if the pshinter module is destroyed before the cff font driver, 4198 * opened FT_Face objects managed by the driver are not properly 4199 * destroyed, resulting in a memory leak 4200 */ 4201 { 4202 FT_UInt n; 4203 4204 4205 for ( n = 0; n < library->num_modules; n++ ) 4206 { 4207 FT_Module module = library->modules[n]; 4208 FT_List faces; 4209 4210 4211 if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 ) 4212 continue; 4213 4214 faces = &FT_DRIVER(module)->faces_list; 4215 while ( faces->head ) 4216 { 4217 FT_Done_Face( FT_FACE( faces->head->data ) ); 4218 if ( faces->head ) 4219 FT_ERROR(( "FT_Done_Library: failed to free some faces\n" )); 4220 } 4221 } 4222 } 4223 4224 /* Close all other modules in the library */ 4225 #if 1 4226 /* XXX Modules are removed in the reversed order so that */ 4227 /* type42 module is removed before truetype module. This */ 4228 /* avoids double free in some occasions. It is a hack. */ 4229 while ( library->num_modules > 0 ) 4230 FT_Remove_Module( library, 4231 library->modules[library->num_modules - 1] ); 4232 #else 4233 { 4234 FT_UInt n; 4235 4236 4237 for ( n = 0; n < library->num_modules; n++ ) 4238 { 4239 FT_Module module = library->modules[n]; 4240 4241 4242 if ( module ) 4243 { 4244 Destroy_Module( module ); 4245 library->modules[n] = 0; 4246 } 4247 } 4248 } 4249 #endif 4250 4251 /* Destroy raster objects */ 4252 FT_FREE( library->raster_pool ); 4253 library->raster_pool_size = 0; 4254 4255 FT_FREE( library ); 4256 return FT_Err_Ok; 4257 } 4258 4259 4260 /* documentation is in ftmodapi.h */ 4261 4262 FT_EXPORT_DEF( void ) FT_Set_Debug_Hook(FT_Library library,FT_UInt hook_index,FT_DebugHook_Func debug_hook)4263 FT_Set_Debug_Hook( FT_Library library, 4264 FT_UInt hook_index, 4265 FT_DebugHook_Func debug_hook ) 4266 { 4267 if ( library && debug_hook && 4268 hook_index < 4269 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) ) 4270 library->debug_hooks[hook_index] = debug_hook; 4271 } 4272 4273 4274 /* documentation is in ftmodapi.h */ 4275 4276 FT_EXPORT_DEF( FT_TrueTypeEngineType ) FT_Get_TrueType_Engine_Type(FT_Library library)4277 FT_Get_TrueType_Engine_Type( FT_Library library ) 4278 { 4279 FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE; 4280 4281 4282 if ( library ) 4283 { 4284 FT_Module module = FT_Get_Module( library, "truetype" ); 4285 4286 4287 if ( module ) 4288 { 4289 FT_Service_TrueTypeEngine service; 4290 4291 4292 service = (FT_Service_TrueTypeEngine) 4293 ft_module_get_service( module, 4294 FT_SERVICE_ID_TRUETYPE_ENGINE ); 4295 if ( service ) 4296 result = service->engine_type; 4297 } 4298 } 4299 4300 return result; 4301 } 4302 4303 4304 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 4305 4306 FT_BASE_DEF( FT_Error ) ft_stub_set_char_sizes(FT_Size size,FT_F26Dot6 width,FT_F26Dot6 height,FT_UInt horz_res,FT_UInt vert_res)4307 ft_stub_set_char_sizes( FT_Size size, 4308 FT_F26Dot6 width, 4309 FT_F26Dot6 height, 4310 FT_UInt horz_res, 4311 FT_UInt vert_res ) 4312 { 4313 FT_Size_RequestRec req; 4314 FT_Driver driver = size->face->driver; 4315 4316 4317 if ( driver->clazz->request_size ) 4318 { 4319 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; 4320 req.width = width; 4321 req.height = height; 4322 4323 if ( horz_res == 0 ) 4324 horz_res = vert_res; 4325 4326 if ( vert_res == 0 ) 4327 vert_res = horz_res; 4328 4329 if ( horz_res == 0 ) 4330 horz_res = vert_res = 72; 4331 4332 req.horiResolution = horz_res; 4333 req.vertResolution = vert_res; 4334 4335 return driver->clazz->request_size( size, &req ); 4336 } 4337 4338 return 0; 4339 } 4340 4341 4342 FT_BASE_DEF( FT_Error ) ft_stub_set_pixel_sizes(FT_Size size,FT_UInt width,FT_UInt height)4343 ft_stub_set_pixel_sizes( FT_Size size, 4344 FT_UInt width, 4345 FT_UInt height ) 4346 { 4347 FT_Size_RequestRec req; 4348 FT_Driver driver = size->face->driver; 4349 4350 4351 if ( driver->clazz->request_size ) 4352 { 4353 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; 4354 req.width = width << 6; 4355 req.height = height << 6; 4356 req.horiResolution = 0; 4357 req.vertResolution = 0; 4358 4359 return driver->clazz->request_size( size, &req ); 4360 } 4361 4362 return 0; 4363 } 4364 4365 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ 4366 4367 4368 FT_EXPORT_DEF( FT_Error ) FT_Get_SubGlyph_Info(FT_GlyphSlot glyph,FT_UInt sub_index,FT_Int * p_index,FT_UInt * p_flags,FT_Int * p_arg1,FT_Int * p_arg2,FT_Matrix * p_transform)4369 FT_Get_SubGlyph_Info( FT_GlyphSlot glyph, 4370 FT_UInt sub_index, 4371 FT_Int *p_index, 4372 FT_UInt *p_flags, 4373 FT_Int *p_arg1, 4374 FT_Int *p_arg2, 4375 FT_Matrix *p_transform ) 4376 { 4377 FT_Error error = FT_Err_Invalid_Argument; 4378 4379 4380 if ( glyph != NULL && 4381 glyph->format == FT_GLYPH_FORMAT_COMPOSITE && 4382 sub_index < glyph->num_subglyphs ) 4383 { 4384 FT_SubGlyph subg = glyph->subglyphs + sub_index; 4385 4386 4387 *p_index = subg->index; 4388 *p_flags = subg->flags; 4389 *p_arg1 = subg->arg1; 4390 *p_arg2 = subg->arg2; 4391 *p_transform = subg->transform; 4392 } 4393 4394 return error; 4395 } 4396 4397 4398 /* END */ 4399