00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <ft2build.h>
00021 #include FT_LIST_H
00022 #include FT_OUTLINE_H
00023 #include FT_INTERNAL_VALIDATE_H
00024 #include FT_INTERNAL_OBJECTS_H
00025 #include FT_INTERNAL_DEBUG_H
00026 #include FT_INTERNAL_RFORK_H
00027 #include FT_INTERNAL_STREAM_H
00028 #include FT_INTERNAL_SFNT_H
00029 #include FT_TRUETYPE_TABLES_H
00030 #include FT_TRUETYPE_TAGS_H
00031 #include FT_TRUETYPE_IDS_H
00032 #include FT_OUTLINE_H
00033
00034 #include FT_SERVICE_SFNT_H
00035 #include FT_SERVICE_POSTSCRIPT_NAME_H
00036 #include FT_SERVICE_GLYPH_DICT_H
00037 #include FT_SERVICE_TT_CMAP_H
00038 #include FT_SERVICE_KERNING_H
00039 #include FT_SERVICE_TRUETYPE_ENGINE_H
00040
00041 #ifdef FT_CONFIG_OPTION_MAC_FONTS
00042 #include "ftbase.h"
00043 #endif
00044
00045 #define GRID_FIT_METRICS
00046
00047
00048 FT_BASE_DEF( FT_Pointer )
00049 ft_service_list_lookup( FT_ServiceDesc service_descriptors,
00050 const char* service_id )
00051 {
00052 FT_Pointer result = NULL;
00053 FT_ServiceDesc desc = service_descriptors;
00054
00055
00056 if ( desc && service_id )
00057 {
00058 for ( ; desc->serv_id != NULL; desc++ )
00059 {
00060 if ( ft_strcmp( desc->serv_id, service_id ) == 0 )
00061 {
00062 result = (FT_Pointer)desc->serv_data;
00063 break;
00064 }
00065 }
00066 }
00067
00068 return result;
00069 }
00070
00071
00072 FT_BASE_DEF( void )
00073 ft_validator_init( FT_Validator valid,
00074 const FT_Byte* base,
00075 const FT_Byte* limit,
00076 FT_ValidationLevel level )
00077 {
00078 valid->base = base;
00079 valid->limit = limit;
00080 valid->level = level;
00081 valid->error = FT_Err_Ok;
00082 }
00083
00084
00085 FT_BASE_DEF( FT_Int )
00086 ft_validator_run( FT_Validator valid )
00087 {
00088
00089 FT_UNUSED( valid );
00090
00091 return -1;
00092 }
00093
00094
00095 FT_BASE_DEF( void )
00096 ft_validator_error( FT_Validator valid,
00097 FT_Error error )
00098 {
00099
00100
00101
00102 volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer;
00103
00104
00105 valid->error = error;
00106
00107
00108
00109 ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 );
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 FT_BASE_DEF( FT_Error )
00129 FT_Stream_New( FT_Library library,
00130 const FT_Open_Args* args,
00131 FT_Stream *astream )
00132 {
00133 FT_Error error;
00134 FT_Memory memory;
00135 FT_Stream stream;
00136
00137
00138 *astream = 0;
00139
00140 if ( !library )
00141 return FT_Err_Invalid_Library_Handle;
00142
00143 if ( !args )
00144 return FT_Err_Invalid_Argument;
00145
00146 memory = library->memory;
00147
00148 if ( FT_NEW( stream ) )
00149 goto Exit;
00150
00151 stream->memory = memory;
00152
00153 if ( args->flags & FT_OPEN_MEMORY )
00154 {
00155
00156 FT_Stream_OpenMemory( stream,
00157 (const FT_Byte*)args->memory_base,
00158 args->memory_size );
00159 }
00160 else if ( args->flags & FT_OPEN_PATHNAME )
00161 {
00162
00163 error = FT_Stream_Open( stream, args->pathname );
00164 stream->pathname.pointer = args->pathname;
00165 }
00166 else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
00167 {
00168
00169
00170
00171
00172 FT_FREE( stream );
00173 stream = args->stream;
00174 }
00175 else
00176 error = FT_Err_Invalid_Argument;
00177
00178 if ( error )
00179 FT_FREE( stream );
00180 else
00181 stream->memory = memory;
00182
00183 *astream = stream;
00184
00185 Exit:
00186 return error;
00187 }
00188
00189
00190 FT_BASE_DEF( void )
00191 FT_Stream_Free( FT_Stream stream,
00192 FT_Int external )
00193 {
00194 if ( stream )
00195 {
00196 FT_Memory memory = stream->memory;
00197
00198
00199 FT_Stream_Close( stream );
00200
00201 if ( !external )
00202 FT_FREE( stream );
00203 }
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213 #undef FT_COMPONENT
00214 #define FT_COMPONENT trace_objs
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 static FT_Error
00231 ft_glyphslot_init( FT_GlyphSlot slot )
00232 {
00233 FT_Driver driver = slot->face->driver;
00234 FT_Driver_Class clazz = driver->clazz;
00235 FT_Memory memory = driver->root.memory;
00236 FT_Error error = FT_Err_Ok;
00237 FT_Slot_Internal internal;
00238
00239
00240 slot->library = driver->root.library;
00241
00242 if ( FT_NEW( internal ) )
00243 goto Exit;
00244
00245 slot->internal = internal;
00246
00247 if ( FT_DRIVER_USES_OUTLINES( driver ) )
00248 error = FT_GlyphLoader_New( memory, &internal->loader );
00249
00250 if ( !error && clazz->init_slot )
00251 error = clazz->init_slot( slot );
00252
00253 Exit:
00254 return error;
00255 }
00256
00257
00258 FT_BASE_DEF( void )
00259 ft_glyphslot_free_bitmap( FT_GlyphSlot slot )
00260 {
00261 if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
00262 {
00263 FT_Memory memory = FT_FACE_MEMORY( slot->face );
00264
00265
00266 FT_FREE( slot->bitmap.buffer );
00267 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
00268 }
00269 else
00270 {
00271
00272
00273 slot->bitmap.buffer = NULL;
00274 }
00275 }
00276
00277
00278 FT_BASE_DEF( void )
00279 ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
00280 FT_Byte* buffer )
00281 {
00282 ft_glyphslot_free_bitmap( slot );
00283
00284 slot->bitmap.buffer = buffer;
00285
00286 FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );
00287 }
00288
00289
00290 FT_BASE_DEF( FT_Error )
00291 ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
00292 FT_ULong size )
00293 {
00294 FT_Memory memory = FT_FACE_MEMORY( slot->face );
00295 FT_Error error;
00296
00297
00298 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
00299 FT_FREE( slot->bitmap.buffer );
00300 else
00301 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
00302
00303 (void)FT_ALLOC( slot->bitmap.buffer, size );
00304 return error;
00305 }
00306
00307
00308 static void
00309 ft_glyphslot_clear( FT_GlyphSlot slot )
00310 {
00311
00312 ft_glyphslot_free_bitmap( slot );
00313
00314
00315 FT_ZERO( &slot->metrics );
00316 FT_ZERO( &slot->outline );
00317
00318 slot->bitmap.width = 0;
00319 slot->bitmap.rows = 0;
00320 slot->bitmap.pitch = 0;
00321 slot->bitmap.pixel_mode = 0;
00322
00323
00324 slot->bitmap_left = 0;
00325 slot->bitmap_top = 0;
00326 slot->num_subglyphs = 0;
00327 slot->subglyphs = 0;
00328 slot->control_data = 0;
00329 slot->control_len = 0;
00330 slot->other = 0;
00331 slot->format = FT_GLYPH_FORMAT_NONE;
00332
00333 slot->linearHoriAdvance = 0;
00334 slot->linearVertAdvance = 0;
00335 slot->lsb_delta = 0;
00336 slot->rsb_delta = 0;
00337 }
00338
00339
00340 static void
00341 ft_glyphslot_done( FT_GlyphSlot slot )
00342 {
00343 FT_Driver driver = slot->face->driver;
00344 FT_Driver_Class clazz = driver->clazz;
00345 FT_Memory memory = driver->root.memory;
00346
00347
00348 if ( clazz->done_slot )
00349 clazz->done_slot( slot );
00350
00351
00352 ft_glyphslot_free_bitmap( slot );
00353
00354
00355 if ( slot->internal )
00356 {
00357
00358 if ( FT_DRIVER_USES_OUTLINES( driver ) )
00359 {
00360 FT_GlyphLoader_Done( slot->internal->loader );
00361 slot->internal->loader = 0;
00362 }
00363
00364 FT_FREE( slot->internal );
00365 }
00366 }
00367
00368
00369
00370
00371 FT_BASE_DEF( FT_Error )
00372 FT_New_GlyphSlot( FT_Face face,
00373 FT_GlyphSlot *aslot )
00374 {
00375 FT_Error error;
00376 FT_Driver driver;
00377 FT_Driver_Class clazz;
00378 FT_Memory memory;
00379 FT_GlyphSlot slot;
00380
00381
00382 if ( !face || !face->driver )
00383 return FT_Err_Invalid_Argument;
00384
00385 driver = face->driver;
00386 clazz = driver->clazz;
00387 memory = driver->root.memory;
00388
00389 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
00390 if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
00391 {
00392 slot->face = face;
00393
00394 error = ft_glyphslot_init( slot );
00395 if ( error )
00396 {
00397 ft_glyphslot_done( slot );
00398 FT_FREE( slot );
00399 goto Exit;
00400 }
00401
00402 slot->next = face->glyph;
00403 face->glyph = slot;
00404
00405 if ( aslot )
00406 *aslot = slot;
00407 }
00408 else if ( aslot )
00409 *aslot = 0;
00410
00411
00412 Exit:
00413 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
00414 return error;
00415 }
00416
00417
00418
00419
00420 FT_BASE_DEF( void )
00421 FT_Done_GlyphSlot( FT_GlyphSlot slot )
00422 {
00423 if ( slot )
00424 {
00425 FT_Driver driver = slot->face->driver;
00426 FT_Memory memory = driver->root.memory;
00427 FT_GlyphSlot prev;
00428 FT_GlyphSlot cur;
00429
00430
00431
00432 prev = NULL;
00433 cur = slot->face->glyph;
00434
00435 while ( cur )
00436 {
00437 if ( cur == slot )
00438 {
00439 if ( !prev )
00440 slot->face->glyph = cur->next;
00441 else
00442 prev->next = cur->next;
00443
00444 ft_glyphslot_done( slot );
00445 FT_FREE( slot );
00446 break;
00447 }
00448 prev = cur;
00449 cur = cur->next;
00450 }
00451 }
00452 }
00453
00454
00455
00456
00457 FT_EXPORT_DEF( void )
00458 FT_Set_Transform( FT_Face face,
00459 FT_Matrix* matrix,
00460 FT_Vector* delta )
00461 {
00462 FT_Face_Internal internal;
00463
00464
00465 if ( !face )
00466 return;
00467
00468 internal = face->internal;
00469
00470 internal->transform_flags = 0;
00471
00472 if ( !matrix )
00473 {
00474 internal->transform_matrix.xx = 0x10000L;
00475 internal->transform_matrix.xy = 0;
00476 internal->transform_matrix.yx = 0;
00477 internal->transform_matrix.yy = 0x10000L;
00478 matrix = &internal->transform_matrix;
00479 }
00480 else
00481 internal->transform_matrix = *matrix;
00482
00483
00484 if ( ( matrix->xy | matrix->yx ) ||
00485 matrix->xx != 0x10000L ||
00486 matrix->yy != 0x10000L )
00487 internal->transform_flags |= 1;
00488
00489 if ( !delta )
00490 {
00491 internal->transform_delta.x = 0;
00492 internal->transform_delta.y = 0;
00493 delta = &internal->transform_delta;
00494 }
00495 else
00496 internal->transform_delta = *delta;
00497
00498
00499 if ( delta->x | delta->y )
00500 internal->transform_flags |= 2;
00501 }
00502
00503
00504 static FT_Renderer
00505 ft_lookup_glyph_renderer( FT_GlyphSlot slot );
00506
00507
00508 #ifdef GRID_FIT_METRICS
00509 static void
00510 ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot,
00511 FT_Bool vertical )
00512 {
00513 FT_Glyph_Metrics* metrics = &slot->metrics;
00514 FT_Pos right, bottom;
00515
00516
00517 if ( vertical )
00518 {
00519 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
00520 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
00521
00522 right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );
00523 bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );
00524
00525 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
00526 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
00527
00528 metrics->width = right - metrics->vertBearingX;
00529 metrics->height = bottom - metrics->vertBearingY;
00530 }
00531 else
00532 {
00533 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
00534 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
00535
00536 right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );
00537 bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );
00538
00539 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
00540 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
00541
00542 metrics->width = right - metrics->horiBearingX;
00543 metrics->height = metrics->horiBearingY - bottom;
00544 }
00545
00546 metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
00547 metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
00548 }
00549 #endif
00550
00551
00552
00553
00554 FT_EXPORT_DEF( FT_Error )
00555 FT_Load_Glyph( FT_Face face,
00556 FT_UInt glyph_index,
00557 FT_Int32 load_flags )
00558 {
00559 FT_Error error;
00560 FT_Driver driver;
00561 FT_GlyphSlot slot;
00562 FT_Library library;
00563 FT_Bool autohint = FALSE;
00564 FT_Module hinter;
00565
00566
00567 if ( !face || !face->size || !face->glyph )
00568 return FT_Err_Invalid_Face_Handle;
00569
00570
00571
00572
00573 slot = face->glyph;
00574 ft_glyphslot_clear( slot );
00575
00576 driver = face->driver;
00577 library = driver->root.library;
00578 hinter = library->auto_hinter;
00579
00580
00581
00582 if ( load_flags & FT_LOAD_NO_RECURSE )
00583 load_flags |= FT_LOAD_NO_SCALE |
00584 FT_LOAD_IGNORE_TRANSFORM;
00585
00586 if ( load_flags & FT_LOAD_NO_SCALE )
00587 {
00588 load_flags |= FT_LOAD_NO_HINTING |
00589 FT_LOAD_NO_BITMAP;
00590
00591 load_flags &= ~FT_LOAD_RENDER;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 if ( hinter &&
00612 !( load_flags & FT_LOAD_NO_HINTING ) &&
00613 !( load_flags & FT_LOAD_NO_AUTOHINT ) &&
00614 FT_DRIVER_IS_SCALABLE( driver ) &&
00615 FT_DRIVER_USES_OUTLINES( driver ) &&
00616 !FT_IS_TRICKY( face ) &&
00617 ( ( face->internal->transform_matrix.yx == 0 &&
00618 face->internal->transform_matrix.xx != 0 ) ||
00619 ( face->internal->transform_matrix.xx == 0 &&
00620 face->internal->transform_matrix.yx != 0 ) ) )
00621 {
00622 if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) ||
00623 !FT_DRIVER_HAS_HINTER( driver ) )
00624 autohint = TRUE;
00625 else
00626 {
00627 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
00628
00629
00630 if ( mode == FT_RENDER_MODE_LIGHT ||
00631 face->internal->ignore_unpatented_hinter )
00632 autohint = TRUE;
00633 }
00634 }
00635
00636 if ( autohint )
00637 {
00638 FT_AutoHinter_Service hinting;
00639
00640
00641
00642
00643
00644
00645
00646 if ( FT_HAS_FIXED_SIZES( face ) &&
00647 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
00648 {
00649 error = driver->clazz->load_glyph( slot, face->size,
00650 glyph_index,
00651 load_flags | FT_LOAD_SBITS_ONLY );
00652
00653 if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
00654 goto Load_Ok;
00655 }
00656
00657 {
00658 FT_Face_Internal internal = face->internal;
00659 FT_Int transform_flags = internal->transform_flags;
00660
00661
00662
00663
00664 internal->transform_flags = 0;
00665
00666
00667 hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
00668
00669 error = hinting->load_glyph( (FT_AutoHinter)hinter,
00670 slot, face->size,
00671 glyph_index, load_flags );
00672
00673 internal->transform_flags = transform_flags;
00674 }
00675 }
00676 else
00677 {
00678 error = driver->clazz->load_glyph( slot,
00679 face->size,
00680 glyph_index,
00681 load_flags );
00682 if ( error )
00683 goto Exit;
00684
00685 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
00686 {
00687
00688 error = FT_Outline_Check( &slot->outline );
00689 if ( error )
00690 goto Exit;
00691
00692 #ifdef GRID_FIT_METRICS
00693 if ( !( load_flags & FT_LOAD_NO_HINTING ) )
00694 ft_glyphslot_grid_fit_metrics( slot,
00695 FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
00696 #endif
00697 }
00698 }
00699
00700 Load_Ok:
00701
00702 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
00703 {
00704 slot->advance.x = 0;
00705 slot->advance.y = slot->metrics.vertAdvance;
00706 }
00707 else
00708 {
00709 slot->advance.x = slot->metrics.horiAdvance;
00710 slot->advance.y = 0;
00711 }
00712
00713
00714 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
00715 ( FT_IS_SCALABLE( face ) ) )
00716 {
00717 FT_Size_Metrics* metrics = &face->size->metrics;
00718
00719
00720
00721 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
00722 metrics->x_scale, 64 );
00723
00724 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
00725 metrics->y_scale, 64 );
00726 }
00727
00728 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
00729 {
00730 FT_Face_Internal internal = face->internal;
00731
00732
00733
00734 if ( internal->transform_flags )
00735 {
00736
00737 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
00738
00739
00740 if ( renderer )
00741 error = renderer->clazz->transform_glyph(
00742 renderer, slot,
00743 &internal->transform_matrix,
00744 &internal->transform_delta );
00745 else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
00746 {
00747
00748 if ( &internal->transform_matrix )
00749 FT_Outline_Transform( &slot->outline,
00750 &internal->transform_matrix );
00751
00752 if ( &internal->transform_delta )
00753 FT_Outline_Translate( &slot->outline,
00754 internal->transform_delta.x,
00755 internal->transform_delta.y );
00756 }
00757
00758
00759 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
00760 }
00761 }
00762
00763 FT_TRACE5(( " x advance: %d\n" , slot->advance.x ));
00764 FT_TRACE5(( " y advance: %d\n" , slot->advance.y ));
00765
00766 FT_TRACE5(( " linear x advance: %d\n" , slot->linearHoriAdvance ));
00767 FT_TRACE5(( " linear y advance: %d\n" , slot->linearVertAdvance ));
00768
00769
00770 if ( !error &&
00771 slot->format != FT_GLYPH_FORMAT_BITMAP &&
00772 slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
00773 load_flags & FT_LOAD_RENDER )
00774 {
00775 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
00776
00777
00778 if ( mode == FT_RENDER_MODE_NORMAL &&
00779 (load_flags & FT_LOAD_MONOCHROME ) )
00780 mode = FT_RENDER_MODE_MONO;
00781
00782 error = FT_Render_Glyph( slot, mode );
00783 }
00784
00785 Exit:
00786 return error;
00787 }
00788
00789
00790
00791
00792 FT_EXPORT_DEF( FT_Error )
00793 FT_Load_Char( FT_Face face,
00794 FT_ULong char_code,
00795 FT_Int32 load_flags )
00796 {
00797 FT_UInt glyph_index;
00798
00799
00800 if ( !face )
00801 return FT_Err_Invalid_Face_Handle;
00802
00803 glyph_index = (FT_UInt)char_code;
00804 if ( face->charmap )
00805 glyph_index = FT_Get_Char_Index( face, char_code );
00806
00807 return FT_Load_Glyph( face, glyph_index, load_flags );
00808 }
00809
00810
00811
00812 static void
00813 destroy_size( FT_Memory memory,
00814 FT_Size size,
00815 FT_Driver driver )
00816 {
00817
00818 if ( size->generic.finalizer )
00819 size->generic.finalizer( size );
00820
00821
00822 if ( driver->clazz->done_size )
00823 driver->clazz->done_size( size );
00824
00825 FT_FREE( size->internal );
00826 FT_FREE( size );
00827 }
00828
00829
00830 static void
00831 ft_cmap_done_internal( FT_CMap cmap );
00832
00833
00834 static void
00835 destroy_charmaps( FT_Face face,
00836 FT_Memory memory )
00837 {
00838 FT_Int n;
00839
00840
00841 if ( !face )
00842 return;
00843
00844 for ( n = 0; n < face->num_charmaps; n++ )
00845 {
00846 FT_CMap cmap = FT_CMAP( face->charmaps[n] );
00847
00848
00849 ft_cmap_done_internal( cmap );
00850
00851 face->charmaps[n] = NULL;
00852 }
00853
00854 FT_FREE( face->charmaps );
00855 face->num_charmaps = 0;
00856 }
00857
00858
00859
00860 static void
00861 destroy_face( FT_Memory memory,
00862 FT_Face face,
00863 FT_Driver driver )
00864 {
00865 FT_Driver_Class clazz = driver->clazz;
00866
00867
00868
00869 if ( face->autohint.finalizer )
00870 face->autohint.finalizer( face->autohint.data );
00871
00872
00873
00874 while ( face->glyph )
00875 FT_Done_GlyphSlot( face->glyph );
00876
00877
00878 FT_List_Finalize( &face->sizes_list,
00879 (FT_List_Destructor)destroy_size,
00880 memory,
00881 driver );
00882 face->size = 0;
00883
00884
00885 if ( face->generic.finalizer )
00886 face->generic.finalizer( face );
00887
00888
00889 destroy_charmaps( face, memory );
00890
00891
00892 if ( clazz->done_face )
00893 clazz->done_face( face );
00894
00895
00896 FT_Stream_Free(
00897 face->stream,
00898 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
00899
00900 face->stream = 0;
00901
00902
00903 if ( face->internal )
00904 {
00905 FT_FREE( face->internal );
00906 }
00907 FT_FREE( face );
00908 }
00909
00910
00911 static void
00912 Destroy_Driver( FT_Driver driver )
00913 {
00914 FT_List_Finalize( &driver->faces_list,
00915 (FT_List_Destructor)destroy_face,
00916 driver->root.memory,
00917 driver );
00918
00919
00920 if ( FT_DRIVER_USES_OUTLINES( driver ) )
00921 FT_GlyphLoader_Done( driver->glyph_loader );
00922 }
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939 static FT_Error
00940 find_unicode_charmap( FT_Face face )
00941 {
00942 FT_CharMap* first;
00943 FT_CharMap* cur;
00944
00945
00946
00947 FT_ASSERT( face );
00948
00949 first = face->charmaps;
00950
00951 if ( !first )
00952 return FT_Err_Invalid_CharMap_Handle;
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982 cur = first + face->num_charmaps;
00983
00984 for ( ; --cur >= first; )
00985 {
00986 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
00987 {
00988
00989
00990 if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
00991 cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
00992 ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
00993 cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
00994 {
00995 face->charmap = cur[0];
00996 return FT_Err_Ok;
00997 }
00998 }
00999 }
01000
01001
01002
01003 cur = first + face->num_charmaps;
01004
01005 for ( ; --cur >= first; )
01006 {
01007 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
01008 {
01009 face->charmap = cur[0];
01010 return FT_Err_Ok;
01011 }
01012 }
01013
01014 return FT_Err_Invalid_CharMap_Handle;
01015 }
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027 static FT_CharMap
01028 find_variant_selector_charmap( FT_Face face )
01029 {
01030 FT_CharMap* first;
01031 FT_CharMap* end;
01032 FT_CharMap* cur;
01033
01034
01035
01036 FT_ASSERT( face );
01037
01038 first = face->charmaps;
01039
01040 if ( !first )
01041 return NULL;
01042
01043 end = first + face->num_charmaps;
01044
01045 for ( cur = first; cur < end; ++cur )
01046 {
01047 if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
01048 cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
01049 FT_Get_CMap_Format( cur[0] ) == 14 )
01050 return cur[0];
01051 }
01052
01053 return NULL;
01054 }
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065 static FT_Error
01066 open_face( FT_Driver driver,
01067 FT_Stream stream,
01068 FT_Long face_index,
01069 FT_Int num_params,
01070 FT_Parameter* params,
01071 FT_Face *aface )
01072 {
01073 FT_Memory memory;
01074 FT_Driver_Class clazz;
01075 FT_Face face = 0;
01076 FT_Error error, error2;
01077 FT_Face_Internal internal = NULL;
01078
01079
01080 clazz = driver->clazz;
01081 memory = driver->root.memory;
01082
01083
01084 if ( FT_ALLOC( face, clazz->face_object_size ) )
01085 goto Fail;
01086
01087 if ( FT_NEW( internal ) )
01088 goto Fail;
01089
01090 face->internal = internal;
01091
01092 face->driver = driver;
01093 face->memory = memory;
01094 face->stream = stream;
01095
01096 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01097 {
01098 int i;
01099
01100
01101 face->internal->incremental_interface = 0;
01102 for ( i = 0; i < num_params && !face->internal->incremental_interface;
01103 i++ )
01104 if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
01105 face->internal->incremental_interface =
01106 (FT_Incremental_Interface)params[i].data;
01107 }
01108 #endif
01109
01110 if ( clazz->init_face )
01111 error = clazz->init_face( stream,
01112 face,
01113 (FT_Int)face_index,
01114 num_params,
01115 params );
01116 if ( error )
01117 goto Fail;
01118
01119
01120 error2 = find_unicode_charmap( face );
01121
01122
01123
01124
01125
01126 if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
01127 {
01128 error = error2;
01129 goto Fail;
01130 }
01131
01132 *aface = face;
01133
01134 Fail:
01135 if ( error )
01136 {
01137 destroy_charmaps( face, memory );
01138 if ( clazz->done_face )
01139 clazz->done_face( face );
01140 FT_FREE( internal );
01141 FT_FREE( face );
01142 *aface = 0;
01143 }
01144
01145 return error;
01146 }
01147
01148
01149
01150
01151
01152 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
01153
01154
01155
01156 FT_EXPORT_DEF( FT_Error )
01157 FT_New_Face( FT_Library library,
01158 const char* pathname,
01159 FT_Long face_index,
01160 FT_Face *aface )
01161 {
01162 FT_Open_Args args;
01163
01164
01165
01166 if ( !pathname )
01167 return FT_Err_Invalid_Argument;
01168
01169 args.flags = FT_OPEN_PATHNAME;
01170 args.pathname = (char*)pathname;
01171 args.stream = NULL;
01172
01173 return FT_Open_Face( library, &args, face_index, aface );
01174 }
01175
01176 #endif
01177
01178
01179
01180
01181 FT_EXPORT_DEF( FT_Error )
01182 FT_New_Memory_Face( FT_Library library,
01183 const FT_Byte* file_base,
01184 FT_Long file_size,
01185 FT_Long face_index,
01186 FT_Face *aface )
01187 {
01188 FT_Open_Args args;
01189
01190
01191
01192 if ( !file_base )
01193 return FT_Err_Invalid_Argument;
01194
01195 args.flags = FT_OPEN_MEMORY;
01196 args.memory_base = file_base;
01197 args.memory_size = file_size;
01198 args.stream = NULL;
01199
01200 return FT_Open_Face( library, &args, face_index, aface );
01201 }
01202
01203
01204 #ifdef FT_CONFIG_OPTION_MAC_FONTS
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236 static void
01237 memory_stream_close( FT_Stream stream )
01238 {
01239 FT_Memory memory = stream->memory;
01240
01241
01242 FT_FREE( stream->base );
01243
01244 stream->size = 0;
01245 stream->base = 0;
01246 stream->close = 0;
01247 }
01248
01249
01250
01251
01252 static FT_Error
01253 new_memory_stream( FT_Library library,
01254 FT_Byte* base,
01255 FT_ULong size,
01256 FT_Stream_CloseFunc close,
01257 FT_Stream *astream )
01258 {
01259 FT_Error error;
01260 FT_Memory memory;
01261 FT_Stream stream;
01262
01263
01264 if ( !library )
01265 return FT_Err_Invalid_Library_Handle;
01266
01267 if ( !base )
01268 return FT_Err_Invalid_Argument;
01269
01270 *astream = 0;
01271 memory = library->memory;
01272 if ( FT_NEW( stream ) )
01273 goto Exit;
01274
01275 FT_Stream_OpenMemory( stream, base, size );
01276
01277 stream->close = close;
01278
01279 *astream = stream;
01280
01281 Exit:
01282 return error;
01283 }
01284
01285
01286
01287
01288 FT_LOCAL_DEF( FT_Error )
01289 open_face_from_buffer( FT_Library library,
01290 FT_Byte* base,
01291 FT_ULong size,
01292 FT_Long face_index,
01293 const char* driver_name,
01294 FT_Face *aface )
01295 {
01296 FT_Open_Args args;
01297 FT_Error error;
01298 FT_Stream stream = NULL;
01299 FT_Memory memory = library->memory;
01300
01301
01302 error = new_memory_stream( library,
01303 base,
01304 size,
01305 memory_stream_close,
01306 &stream );
01307 if ( error )
01308 {
01309 FT_FREE( base );
01310 return error;
01311 }
01312
01313 args.flags = FT_OPEN_STREAM;
01314 args.stream = stream;
01315 if ( driver_name )
01316 {
01317 args.flags = args.flags | FT_OPEN_DRIVER;
01318 args.driver = FT_Get_Module( library, driver_name );
01319 }
01320
01321 #ifdef FT_MACINTOSH
01322
01323
01324
01325
01326
01327 if ( face_index > 0 )
01328 face_index = 0;
01329 #endif
01330
01331 error = FT_Open_Face( library, &args, face_index, aface );
01332
01333 if ( error == FT_Err_Ok )
01334 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
01335 else
01336 #ifdef FT_MACINTOSH
01337 FT_Stream_Free( stream, 0 );
01338 #else
01339 {
01340 FT_Stream_Close( stream );
01341 FT_FREE( stream );
01342 }
01343 #endif
01344
01345 return error;
01346 }
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358 static FT_Error
01359 ft_lookup_PS_in_sfnt_stream( FT_Stream stream,
01360 FT_Long face_index,
01361 FT_ULong* offset,
01362 FT_ULong* length,
01363 FT_Bool* is_sfnt_cid )
01364 {
01365 FT_Error error;
01366 FT_UShort numTables;
01367 FT_Long pstable_index;
01368 FT_ULong tag;
01369 int i;
01370
01371
01372 *offset = 0;
01373 *length = 0;
01374 *is_sfnt_cid = FALSE;
01375
01376
01377
01378
01379 if ( FT_READ_ULONG( tag ) )
01380 return error;
01381 if ( tag != TTAG_typ1 )
01382 return FT_Err_Unknown_File_Format;
01383
01384 if ( FT_READ_USHORT( numTables ) )
01385 return error;
01386 if ( FT_STREAM_SKIP( 2 * 3 ) )
01387 return error;
01388
01389 pstable_index = -1;
01390 *is_sfnt_cid = FALSE;
01391
01392 for ( i = 0; i < numTables; i++ )
01393 {
01394 if ( FT_READ_ULONG( tag ) || FT_STREAM_SKIP( 4 ) ||
01395 FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) )
01396 return error;
01397
01398 if ( tag == TTAG_CID )
01399 {
01400 pstable_index++;
01401 *offset += 22;
01402 *length -= 22;
01403 *is_sfnt_cid = TRUE;
01404 if ( face_index < 0 )
01405 return FT_Err_Ok;
01406 }
01407 else if ( tag == TTAG_TYP1 )
01408 {
01409 pstable_index++;
01410 *offset += 24;
01411 *length -= 24;
01412 *is_sfnt_cid = FALSE;
01413 if ( face_index < 0 )
01414 return FT_Err_Ok;
01415 }
01416 if ( face_index >= 0 && pstable_index == face_index )
01417 return FT_Err_Ok;
01418 }
01419 return FT_Err_Table_Missing;
01420 }
01421
01422
01423 FT_LOCAL_DEF( FT_Error )
01424 open_face_PS_from_sfnt_stream( FT_Library library,
01425 FT_Stream stream,
01426 FT_Long face_index,
01427 FT_Int num_params,
01428 FT_Parameter *params,
01429 FT_Face *aface )
01430 {
01431 FT_Error error;
01432 FT_Memory memory = library->memory;
01433 FT_ULong offset, length;
01434 FT_Long pos;
01435 FT_Bool is_sfnt_cid;
01436 FT_Byte* sfnt_ps;
01437
01438 FT_UNUSED( num_params );
01439 FT_UNUSED( params );
01440
01441
01442 pos = FT_Stream_Pos( stream );
01443
01444 error = ft_lookup_PS_in_sfnt_stream( stream,
01445 face_index,
01446 &offset,
01447 &length,
01448 &is_sfnt_cid );
01449 if ( error )
01450 goto Exit;
01451
01452 if ( FT_Stream_Seek( stream, pos + offset ) )
01453 goto Exit;
01454
01455 if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
01456 goto Exit;
01457
01458 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
01459 if ( error )
01460 goto Exit;
01461
01462 error = open_face_from_buffer( library,
01463 sfnt_ps,
01464 length,
01465 face_index < 0 ? face_index : 0,
01466 is_sfnt_cid ? "cid" : "type1",
01467 aface );
01468 Exit:
01469 {
01470 FT_Error error1;
01471
01472
01473 if ( error == FT_Err_Unknown_File_Format )
01474 {
01475 error1 = FT_Stream_Seek( stream, pos );
01476 if ( error1 )
01477 return error1;
01478 }
01479
01480 return error;
01481 }
01482 }
01483
01484
01485 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
01486
01487
01488
01489
01490
01491
01492
01493 static FT_Error
01494 Mac_Read_POST_Resource( FT_Library library,
01495 FT_Stream stream,
01496 FT_Long *offsets,
01497 FT_Long resource_cnt,
01498 FT_Long face_index,
01499 FT_Face *aface )
01500 {
01501 FT_Error error = FT_Err_Cannot_Open_Resource;
01502 FT_Memory memory = library->memory;
01503 FT_Byte* pfb_data;
01504 int i, type, flags;
01505 FT_Long len;
01506 FT_Long pfb_len, pfb_pos, pfb_lenpos;
01507 FT_Long rlen, temp;
01508
01509
01510 if ( face_index == -1 )
01511 face_index = 0;
01512 if ( face_index != 0 )
01513 return error;
01514
01515
01516
01517 pfb_len = 0;
01518 for ( i = 0; i < resource_cnt; ++i )
01519 {
01520 error = FT_Stream_Seek( stream, offsets[i] );
01521 if ( error )
01522 goto Exit;
01523 if ( FT_READ_LONG( temp ) )
01524 goto Exit;
01525 pfb_len += temp + 6;
01526 }
01527
01528 if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
01529 goto Exit;
01530
01531 pfb_data[0] = 0x80;
01532 pfb_data[1] = 1;
01533 pfb_data[2] = 0;
01534 pfb_data[3] = 0;
01535 pfb_data[4] = 0;
01536 pfb_data[5] = 0;
01537 pfb_pos = 6;
01538 pfb_lenpos = 2;
01539
01540 len = 0;
01541 type = 1;
01542 for ( i = 0; i < resource_cnt; ++i )
01543 {
01544 error = FT_Stream_Seek( stream, offsets[i] );
01545 if ( error )
01546 goto Exit2;
01547 if ( FT_READ_LONG( rlen ) )
01548 goto Exit;
01549 if ( FT_READ_USHORT( flags ) )
01550 goto Exit;
01551 rlen -= 2;
01552 if ( ( flags >> 8 ) == type )
01553 len += rlen;
01554 else
01555 {
01556 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
01557 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
01558 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
01559 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
01560
01561 if ( ( flags >> 8 ) == 5 )
01562 break;
01563
01564 pfb_data[pfb_pos++] = 0x80;
01565
01566 type = flags >> 8;
01567 len = rlen;
01568
01569 pfb_data[pfb_pos++] = (FT_Byte)type;
01570 pfb_lenpos = pfb_pos;
01571 pfb_data[pfb_pos++] = 0;
01572 pfb_data[pfb_pos++] = 0;
01573 pfb_data[pfb_pos++] = 0;
01574 pfb_data[pfb_pos++] = 0;
01575 }
01576
01577 error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
01578 pfb_pos += rlen;
01579 }
01580
01581 pfb_data[pfb_pos++] = 0x80;
01582 pfb_data[pfb_pos++] = 3;
01583
01584 pfb_data[pfb_lenpos ] = (FT_Byte)( len );
01585 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
01586 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
01587 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
01588
01589 return open_face_from_buffer( library,
01590 pfb_data,
01591 pfb_pos,
01592 face_index,
01593 "type1",
01594 aface );
01595
01596 Exit2:
01597 FT_FREE( pfb_data );
01598
01599 Exit:
01600 return error;
01601 }
01602
01603
01604
01605
01606
01607
01608
01609 static FT_Error
01610 Mac_Read_sfnt_Resource( FT_Library library,
01611 FT_Stream stream,
01612 FT_Long *offsets,
01613 FT_Long resource_cnt,
01614 FT_Long face_index,
01615 FT_Face *aface )
01616 {
01617 FT_Memory memory = library->memory;
01618 FT_Byte* sfnt_data;
01619 FT_Error error;
01620 FT_Long flag_offset;
01621 FT_Long rlen;
01622 int is_cff;
01623 FT_Long face_index_in_resource = 0;
01624
01625
01626 if ( face_index == -1 )
01627 face_index = 0;
01628 if ( face_index >= resource_cnt )
01629 return FT_Err_Cannot_Open_Resource;
01630
01631 flag_offset = offsets[face_index];
01632 error = FT_Stream_Seek( stream, flag_offset );
01633 if ( error )
01634 goto Exit;
01635
01636 if ( FT_READ_LONG( rlen ) )
01637 goto Exit;
01638 if ( rlen == -1 )
01639 return FT_Err_Cannot_Open_Resource;
01640
01641 error = open_face_PS_from_sfnt_stream( library,
01642 stream,
01643 face_index,
01644 0, NULL,
01645 aface );
01646 if ( !error )
01647 goto Exit;
01648
01649
01650 if ( FT_Stream_Seek( stream, flag_offset + 4 ) )
01651 goto Exit;
01652
01653 if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
01654 return error;
01655 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
01656 if ( error )
01657 goto Exit;
01658
01659 is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
01660 error = open_face_from_buffer( library,
01661 sfnt_data,
01662 rlen,
01663 face_index_in_resource,
01664 is_cff ? "cff" : "truetype",
01665 aface );
01666
01667 Exit:
01668 return error;
01669 }
01670
01671
01672
01673
01674
01675
01676
01677 static FT_Error
01678 IsMacResource( FT_Library library,
01679 FT_Stream stream,
01680 FT_Long resource_offset,
01681 FT_Long face_index,
01682 FT_Face *aface )
01683 {
01684 FT_Memory memory = library->memory;
01685 FT_Error error;
01686 FT_Long map_offset, rdara_pos;
01687 FT_Long *data_offsets;
01688 FT_Long count;
01689
01690
01691 error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
01692 &map_offset, &rdara_pos );
01693 if ( error )
01694 return error;
01695
01696 error = FT_Raccess_Get_DataOffsets( library, stream,
01697 map_offset, rdara_pos,
01698 TTAG_POST,
01699 &data_offsets, &count );
01700 if ( !error )
01701 {
01702 error = Mac_Read_POST_Resource( library, stream, data_offsets, count,
01703 face_index, aface );
01704 FT_FREE( data_offsets );
01705
01706 if ( !error )
01707 (*aface)->num_faces = 1;
01708 return error;
01709 }
01710
01711 error = FT_Raccess_Get_DataOffsets( library, stream,
01712 map_offset, rdara_pos,
01713 TTAG_sfnt,
01714 &data_offsets, &count );
01715 if ( !error )
01716 {
01717 FT_Long face_index_internal = face_index % count;
01718
01719
01720 error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,
01721 face_index_internal, aface );
01722 FT_FREE( data_offsets );
01723 if ( !error )
01724 (*aface)->num_faces = count;
01725 }
01726
01727 return error;
01728 }
01729
01730
01731
01732
01733
01734 static FT_Error
01735 IsMacBinary( FT_Library library,
01736 FT_Stream stream,
01737 FT_Long face_index,
01738 FT_Face *aface )
01739 {
01740 unsigned char header[128];
01741 FT_Error error;
01742 FT_Long dlen, offset;
01743
01744
01745 if ( NULL == stream )
01746 return FT_Err_Invalid_Stream_Operation;
01747
01748 error = FT_Stream_Seek( stream, 0 );
01749 if ( error )
01750 goto Exit;
01751
01752 error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );
01753 if ( error )
01754 goto Exit;
01755
01756 if ( header[ 0] != 0 ||
01757 header[74] != 0 ||
01758 header[82] != 0 ||
01759 header[ 1] == 0 ||
01760 header[ 1] > 33 ||
01761 header[63] != 0 ||
01762 header[2 + header[1]] != 0 )
01763 return FT_Err_Unknown_File_Format;
01764
01765 dlen = ( header[0x53] << 24 ) |
01766 ( header[0x54] << 16 ) |
01767 ( header[0x55] << 8 ) |
01768 header[0x56];
01769 #if 0
01770 rlen = ( header[0x57] << 24 ) |
01771 ( header[0x58] << 16 ) |
01772 ( header[0x59] << 8 ) |
01773 header[0x5a];
01774 #endif
01775 offset = 128 + ( ( dlen + 127 ) & ~127 );
01776
01777 return IsMacResource( library, stream, offset, face_index, aface );
01778
01779 Exit:
01780 return error;
01781 }
01782
01783
01784 static FT_Error
01785 load_face_in_embedded_rfork( FT_Library library,
01786 FT_Stream stream,
01787 FT_Long face_index,
01788 FT_Face *aface,
01789 const FT_Open_Args *args )
01790 {
01791
01792 #undef FT_COMPONENT
01793 #define FT_COMPONENT trace_raccess
01794
01795 FT_Memory memory = library->memory;
01796 FT_Error error = FT_Err_Unknown_File_Format;
01797 int i;
01798
01799 char * file_names[FT_RACCESS_N_RULES];
01800 FT_Long offsets[FT_RACCESS_N_RULES];
01801 FT_Error errors[FT_RACCESS_N_RULES];
01802
01803 FT_Open_Args args2;
01804 FT_Stream stream2 = 0;
01805
01806
01807 FT_Raccess_Guess( library, stream,
01808 args->pathname, file_names, offsets, errors );
01809
01810 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
01811 {
01812 if ( errors[i] )
01813 {
01814 FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
01815 continue;
01816 }
01817
01818 args2.flags = FT_OPEN_PATHNAME;
01819 args2.pathname = file_names[i] ? file_names[i] : args->pathname;
01820
01821 FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
01822 i, args2.pathname, offsets[i] ));
01823
01824 error = FT_Stream_New( library, &args2, &stream2 );
01825 if ( error )
01826 {
01827 FT_TRACE3(( "failed\n" ));
01828 continue;
01829 }
01830
01831 error = IsMacResource( library, stream2, offsets[i],
01832 face_index, aface );
01833 FT_Stream_Free( stream2, 0 );
01834
01835 FT_TRACE3(( "%s\n", error ? "failed": "successful" ));
01836
01837 if ( !error )
01838 break;
01839 }
01840
01841 for (i = 0; i < FT_RACCESS_N_RULES; i++)
01842 {
01843 if ( file_names[i] )
01844 FT_FREE( file_names[i] );
01845 }
01846
01847
01848 if ( error )
01849 error = FT_Err_Unknown_File_Format;
01850
01851 return error;
01852
01853 #undef FT_COMPONENT
01854 #define FT_COMPONENT trace_objs
01855
01856 }
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866 static FT_Error
01867 load_mac_face( FT_Library library,
01868 FT_Stream stream,
01869 FT_Long face_index,
01870 FT_Face *aface,
01871 const FT_Open_Args *args )
01872 {
01873 FT_Error error;
01874 FT_UNUSED( args );
01875
01876
01877 error = IsMacBinary( library, stream, face_index, aface );
01878 if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )
01879 {
01880
01881 #undef FT_COMPONENT
01882 #define FT_COMPONENT trace_raccess
01883
01884 FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
01885
01886 error = IsMacResource( library, stream, 0, face_index, aface );
01887
01888 FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
01889
01890 #undef FT_COMPONENT
01891 #define FT_COMPONENT trace_objs
01892
01893 }
01894
01895 if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ||
01896 FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&
01897 ( args->flags & FT_OPEN_PATHNAME ) )
01898 error = load_face_in_embedded_rfork( library, stream,
01899 face_index, aface, args );
01900 return error;
01901 }
01902 #endif
01903
01904 #endif
01905
01906
01907
01908
01909 FT_EXPORT_DEF( FT_Error )
01910 FT_Open_Face( FT_Library library,
01911 const FT_Open_Args* args,
01912 FT_Long face_index,
01913 FT_Face *aface )
01914 {
01915 FT_Error error;
01916 FT_Driver driver;
01917 FT_Memory memory;
01918 FT_Stream stream = 0;
01919 FT_Face face = 0;
01920 FT_ListNode node = 0;
01921 FT_Bool external_stream;
01922 FT_Module* cur;
01923 FT_Module* limit;
01924
01925
01926
01927
01928
01929 if ( ( !aface && face_index >= 0 ) || !args )
01930 return FT_Err_Invalid_Argument;
01931
01932 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
01933 args->stream );
01934
01935
01936 error = FT_Stream_New( library, args, &stream );
01937 if ( error )
01938 goto Fail3;
01939
01940 memory = library->memory;
01941
01942
01943
01944 if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
01945 {
01946 driver = FT_DRIVER( args->driver );
01947
01948
01949 if ( FT_MODULE_IS_DRIVER( driver ) )
01950 {
01951 FT_Int num_params = 0;
01952 FT_Parameter* params = 0;
01953
01954
01955 if ( args->flags & FT_OPEN_PARAMS )
01956 {
01957 num_params = args->num_params;
01958 params = args->params;
01959 }
01960
01961 error = open_face( driver, stream, face_index,
01962 num_params, params, &face );
01963 if ( !error )
01964 goto Success;
01965 }
01966 else
01967 error = FT_Err_Invalid_Handle;
01968
01969 FT_Stream_Free( stream, external_stream );
01970 goto Fail;
01971 }
01972 else
01973 {
01974
01975 cur = library->modules;
01976 limit = cur + library->num_modules;
01977
01978
01979 for ( ; cur < limit; cur++ )
01980 {
01981
01982 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
01983 {
01984 FT_Int num_params = 0;
01985 FT_Parameter* params = 0;
01986
01987
01988 driver = FT_DRIVER( cur[0] );
01989
01990 if ( args->flags & FT_OPEN_PARAMS )
01991 {
01992 num_params = args->num_params;
01993 params = args->params;
01994 }
01995
01996 error = open_face( driver, stream, face_index,
01997 num_params, params, &face );
01998 if ( !error )
01999 goto Success;
02000
02001 #ifdef FT_CONFIG_OPTION_MAC_FONTS
02002 if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 &&
02003 FT_ERROR_BASE( error ) == FT_Err_Table_Missing )
02004 {
02005
02006 if ( FT_Stream_Seek( stream, 0 ) )
02007 break;
02008
02009 error = open_face_PS_from_sfnt_stream( library,
02010 stream,
02011 face_index,
02012 num_params,
02013 params,
02014 aface );
02015 if ( !error )
02016 {
02017 FT_Stream_Free( stream, external_stream );
02018 return error;
02019 }
02020 }
02021 #endif
02022
02023 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
02024 goto Fail3;
02025 }
02026 }
02027
02028 Fail3:
02029
02030
02031
02032 if ( FT_ERROR_BASE( error ) != FT_Err_Cannot_Open_Stream &&
02033 FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format &&
02034 FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )
02035 goto Fail2;
02036
02037 #if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
02038 error = load_mac_face( library, stream, face_index, aface, args );
02039 if ( !error )
02040 {
02041
02042
02043
02044
02045
02046 FT_Stream_Free( stream, external_stream );
02047 return error;
02048 }
02049
02050 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
02051 goto Fail2;
02052 #endif
02053
02054
02055 error = FT_Err_Unknown_File_Format;
02056
02057 Fail2:
02058 FT_Stream_Free( stream, external_stream );
02059 goto Fail;
02060 }
02061
02062 Success:
02063 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
02064
02065
02066 if ( external_stream )
02067 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
02068
02069
02070 if ( FT_NEW( node ) )
02071 goto Fail;
02072
02073 node->data = face;
02074
02075
02076 FT_List_Add( &face->driver->faces_list, node );
02077
02078
02079 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
02080
02081 if ( face_index >= 0 )
02082 {
02083 error = FT_New_GlyphSlot( face, NULL );
02084 if ( error )
02085 goto Fail;
02086
02087
02088 {
02089 FT_Size size;
02090
02091
02092 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
02093
02094 error = FT_New_Size( face, &size );
02095 if ( error )
02096 goto Fail;
02097
02098 face->size = size;
02099 }
02100 }
02101
02102
02103
02104 if ( FT_IS_SCALABLE( face ) )
02105 {
02106 if ( face->height < 0 )
02107 face->height = (FT_Short)-face->height;
02108
02109 if ( !FT_HAS_VERTICAL( face ) )
02110 face->max_advance_height = (FT_Short)face->height;
02111 }
02112
02113 if ( FT_HAS_FIXED_SIZES( face ) )
02114 {
02115 FT_Int i;
02116
02117
02118 for ( i = 0; i < face->num_fixed_sizes; i++ )
02119 {
02120 FT_Bitmap_Size* bsize = face->available_sizes + i;
02121
02122
02123 if ( bsize->height < 0 )
02124 bsize->height = (FT_Short)-bsize->height;
02125 if ( bsize->x_ppem < 0 )
02126 bsize->x_ppem = (FT_Short)-bsize->x_ppem;
02127 if ( bsize->y_ppem < 0 )
02128 bsize->y_ppem = -bsize->y_ppem;
02129 }
02130 }
02131
02132
02133 {
02134 FT_Face_Internal internal = face->internal;
02135
02136
02137 internal->transform_matrix.xx = 0x10000L;
02138 internal->transform_matrix.xy = 0;
02139 internal->transform_matrix.yx = 0;
02140 internal->transform_matrix.yy = 0x10000L;
02141
02142 internal->transform_delta.x = 0;
02143 internal->transform_delta.y = 0;
02144 }
02145
02146 if ( aface )
02147 *aface = face;
02148 else
02149 FT_Done_Face( face );
02150
02151 goto Exit;
02152
02153 Fail:
02154 FT_Done_Face( face );
02155
02156 Exit:
02157 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
02158
02159 return error;
02160 }
02161
02162
02163
02164
02165 FT_EXPORT_DEF( FT_Error )
02166 FT_Attach_File( FT_Face face,
02167 const char* filepathname )
02168 {
02169 FT_Open_Args open;
02170
02171
02172
02173
02174 if ( !filepathname )
02175 return FT_Err_Invalid_Argument;
02176
02177 open.stream = NULL;
02178 open.flags = FT_OPEN_PATHNAME;
02179 open.pathname = (char*)filepathname;
02180
02181 return FT_Attach_Stream( face, &open );
02182 }
02183
02184
02185
02186
02187 FT_EXPORT_DEF( FT_Error )
02188 FT_Attach_Stream( FT_Face face,
02189 FT_Open_Args* parameters )
02190 {
02191 FT_Stream stream;
02192 FT_Error error;
02193 FT_Driver driver;
02194
02195 FT_Driver_Class clazz;
02196
02197
02198
02199
02200 if ( !face )
02201 return FT_Err_Invalid_Face_Handle;
02202
02203 driver = face->driver;
02204 if ( !driver )
02205 return FT_Err_Invalid_Driver_Handle;
02206
02207 error = FT_Stream_New( driver->root.library, parameters, &stream );
02208 if ( error )
02209 goto Exit;
02210
02211
02212
02213
02214 error = FT_Err_Unimplemented_Feature;
02215 clazz = driver->clazz;
02216 if ( clazz->attach_file )
02217 error = clazz->attach_file( face, stream );
02218
02219
02220 FT_Stream_Free( stream,
02221 (FT_Bool)( parameters->stream &&
02222 ( parameters->flags & FT_OPEN_STREAM ) ) );
02223
02224 Exit:
02225 return error;
02226 }
02227
02228
02229
02230
02231 FT_EXPORT_DEF( FT_Error )
02232 FT_Done_Face( FT_Face face )
02233 {
02234 FT_Error error;
02235 FT_Driver driver;
02236 FT_Memory memory;
02237 FT_ListNode node;
02238
02239
02240 error = FT_Err_Invalid_Face_Handle;
02241 if ( face && face->driver )
02242 {
02243 driver = face->driver;
02244 memory = driver->root.memory;
02245
02246
02247 node = FT_List_Find( &driver->faces_list, face );
02248 if ( node )
02249 {
02250
02251 FT_List_Remove( &driver->faces_list, node );
02252 FT_FREE( node );
02253
02254
02255 destroy_face( memory, face, driver );
02256 error = FT_Err_Ok;
02257 }
02258 }
02259 return error;
02260 }
02261
02262
02263
02264
02265 FT_EXPORT_DEF( FT_Error )
02266 FT_New_Size( FT_Face face,
02267 FT_Size *asize )
02268 {
02269 FT_Error error;
02270 FT_Memory memory;
02271 FT_Driver driver;
02272 FT_Driver_Class clazz;
02273
02274 FT_Size size = 0;
02275 FT_ListNode node = 0;
02276
02277
02278 if ( !face )
02279 return FT_Err_Invalid_Face_Handle;
02280
02281 if ( !asize )
02282 return FT_Err_Invalid_Size_Handle;
02283
02284 if ( !face->driver )
02285 return FT_Err_Invalid_Driver_Handle;
02286
02287 *asize = 0;
02288
02289 driver = face->driver;
02290 clazz = driver->clazz;
02291 memory = face->memory;
02292
02293
02294 if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
02295 goto Exit;
02296
02297 size->face = face;
02298
02299
02300 size->internal = 0;
02301
02302 if ( clazz->init_size )
02303 error = clazz->init_size( size );
02304
02305
02306 if ( !error )
02307 {
02308 *asize = size;
02309 node->data = size;
02310 FT_List_Add( &face->sizes_list, node );
02311 }
02312
02313 Exit:
02314 if ( error )
02315 {
02316 FT_FREE( node );
02317 FT_FREE( size );
02318 }
02319
02320 return error;
02321 }
02322
02323
02324
02325
02326 FT_EXPORT_DEF( FT_Error )
02327 FT_Done_Size( FT_Size size )
02328 {
02329 FT_Error error;
02330 FT_Driver driver;
02331 FT_Memory memory;
02332 FT_Face face;
02333 FT_ListNode node;
02334
02335
02336 if ( !size )
02337 return FT_Err_Invalid_Size_Handle;
02338
02339 face = size->face;
02340 if ( !face )
02341 return FT_Err_Invalid_Face_Handle;
02342
02343 driver = face->driver;
02344 if ( !driver )
02345 return FT_Err_Invalid_Driver_Handle;
02346
02347 memory = driver->root.memory;
02348
02349 error = FT_Err_Ok;
02350 node = FT_List_Find( &face->sizes_list, size );
02351 if ( node )
02352 {
02353 FT_List_Remove( &face->sizes_list, node );
02354 FT_FREE( node );
02355
02356 if ( face->size == size )
02357 {
02358 face->size = 0;
02359 if ( face->sizes_list.head )
02360 face->size = (FT_Size)(face->sizes_list.head->data);
02361 }
02362
02363 destroy_size( memory, size, driver );
02364 }
02365 else
02366 error = FT_Err_Invalid_Size_Handle;
02367
02368 return error;
02369 }
02370
02371
02372
02373
02374 FT_BASE_DEF( FT_Error )
02375 FT_Match_Size( FT_Face face,
02376 FT_Size_Request req,
02377 FT_Bool ignore_width,
02378 FT_ULong* size_index )
02379 {
02380 FT_Int i;
02381 FT_Long w, h;
02382
02383
02384 if ( !FT_HAS_FIXED_SIZES( face ) )
02385 return FT_Err_Invalid_Face_Handle;
02386
02387
02388 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
02389 return FT_Err_Unimplemented_Feature;
02390
02391 w = FT_REQUEST_WIDTH ( req );
02392 h = FT_REQUEST_HEIGHT( req );
02393
02394 if ( req->width && !req->height )
02395 h = w;
02396 else if ( !req->width && req->height )
02397 w = h;
02398
02399 w = FT_PIX_ROUND( w );
02400 h = FT_PIX_ROUND( h );
02401
02402 for ( i = 0; i < face->num_fixed_sizes; i++ )
02403 {
02404 FT_Bitmap_Size* bsize = face->available_sizes + i;
02405
02406
02407 if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
02408 continue;
02409
02410 if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
02411 {
02412 if ( size_index )
02413 *size_index = (FT_ULong)i;
02414
02415 return FT_Err_Ok;
02416 }
02417 }
02418
02419 return FT_Err_Invalid_Pixel_Size;
02420 }
02421
02422
02423
02424
02425 FT_BASE_DEF( void )
02426 ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,
02427 FT_Pos advance )
02428 {
02429 FT_Pos height = metrics->height;
02430
02431
02432
02433 if ( metrics->horiBearingY < 0 )
02434 {
02435 if ( height < metrics->horiBearingY )
02436 height = metrics->horiBearingY;
02437 }
02438 else if ( metrics->horiBearingY > 0 )
02439 height -= metrics->horiBearingY;
02440
02441
02442 if ( !advance )
02443 advance = height * 12 / 10;
02444
02445 metrics->vertBearingX = metrics->horiBearingX - metrics->horiAdvance / 2;
02446 metrics->vertBearingY = ( advance - height ) / 2;
02447 metrics->vertAdvance = advance;
02448 }
02449
02450
02451 static void
02452 ft_recompute_scaled_metrics( FT_Face face,
02453 FT_Size_Metrics* metrics )
02454 {
02455
02456
02457 #ifdef GRID_FIT_METRICS
02458 metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender,
02459 metrics->y_scale ) );
02460
02461 metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender,
02462 metrics->y_scale ) );
02463
02464 metrics->height = FT_PIX_ROUND( FT_MulFix( face->height,
02465 metrics->y_scale ) );
02466
02467 metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width,
02468 metrics->x_scale ) );
02469 #else
02470 metrics->ascender = FT_MulFix( face->ascender,
02471 metrics->y_scale );
02472
02473 metrics->descender = FT_MulFix( face->descender,
02474 metrics->y_scale );
02475
02476 metrics->height = FT_MulFix( face->height,
02477 metrics->y_scale );
02478
02479 metrics->max_advance = FT_MulFix( face->max_advance_width,
02480 metrics->x_scale );
02481 #endif
02482 }
02483
02484
02485 FT_BASE_DEF( void )
02486 FT_Select_Metrics( FT_Face face,
02487 FT_ULong strike_index )
02488 {
02489 FT_Size_Metrics* metrics;
02490 FT_Bitmap_Size* bsize;
02491
02492
02493 metrics = &face->size->metrics;
02494 bsize = face->available_sizes + strike_index;
02495
02496 metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );
02497 metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );
02498
02499 if ( FT_IS_SCALABLE( face ) )
02500 {
02501 metrics->x_scale = FT_DivFix( bsize->x_ppem,
02502 face->units_per_EM );
02503 metrics->y_scale = FT_DivFix( bsize->y_ppem,
02504 face->units_per_EM );
02505
02506 ft_recompute_scaled_metrics( face, metrics );
02507 }
02508 else
02509 {
02510 metrics->x_scale = 1L << 16;
02511 metrics->y_scale = 1L << 16;
02512 metrics->ascender = bsize->y_ppem;
02513 metrics->descender = 0;
02514 metrics->height = bsize->height << 6;
02515 metrics->max_advance = bsize->x_ppem;
02516 }
02517 }
02518
02519
02520 FT_BASE_DEF( void )
02521 FT_Request_Metrics( FT_Face face,
02522 FT_Size_Request req )
02523 {
02524 FT_Size_Metrics* metrics;
02525
02526
02527 metrics = &face->size->metrics;
02528
02529 if ( FT_IS_SCALABLE( face ) )
02530 {
02531 FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0;
02532
02533
02534 switch ( req->type )
02535 {
02536 case FT_SIZE_REQUEST_TYPE_NOMINAL:
02537 w = h = face->units_per_EM;
02538 break;
02539
02540 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
02541 w = h = face->ascender - face->descender;
02542 break;
02543
02544 case FT_SIZE_REQUEST_TYPE_BBOX:
02545 w = face->bbox.xMax - face->bbox.xMin;
02546 h = face->bbox.yMax - face->bbox.yMin;
02547 break;
02548
02549 case FT_SIZE_REQUEST_TYPE_CELL:
02550 w = face->max_advance_width;
02551 h = face->ascender - face->descender;
02552 break;
02553
02554 case FT_SIZE_REQUEST_TYPE_SCALES:
02555 metrics->x_scale = (FT_Fixed)req->width;
02556 metrics->y_scale = (FT_Fixed)req->height;
02557 if ( !metrics->x_scale )
02558 metrics->x_scale = metrics->y_scale;
02559 else if ( !metrics->y_scale )
02560 metrics->y_scale = metrics->x_scale;
02561 goto Calculate_Ppem;
02562
02563 case FT_SIZE_REQUEST_TYPE_MAX:
02564 break;
02565 }
02566
02567
02568 if ( w < 0 )
02569 w = -w;
02570
02571 if ( h < 0 )
02572 h = -h;
02573
02574 scaled_w = FT_REQUEST_WIDTH ( req );
02575 scaled_h = FT_REQUEST_HEIGHT( req );
02576
02577
02578 if ( req->width )
02579 {
02580 metrics->x_scale = FT_DivFix( scaled_w, w );
02581
02582 if ( req->height )
02583 {
02584 metrics->y_scale = FT_DivFix( scaled_h, h );
02585
02586 if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
02587 {
02588 if ( metrics->y_scale > metrics->x_scale )
02589 metrics->y_scale = metrics->x_scale;
02590 else
02591 metrics->x_scale = metrics->y_scale;
02592 }
02593 }
02594 else
02595 {
02596 metrics->y_scale = metrics->x_scale;
02597 scaled_h = FT_MulDiv( scaled_w, h, w );
02598 }
02599 }
02600 else
02601 {
02602 metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
02603 scaled_w = FT_MulDiv( scaled_h, w, h );
02604 }
02605
02606 Calculate_Ppem:
02607
02608 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
02609 {
02610 scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
02611 scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
02612 }
02613
02614 metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
02615 metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
02616
02617 ft_recompute_scaled_metrics( face, metrics );
02618 }
02619 else
02620 {
02621 FT_ZERO( metrics );
02622 metrics->x_scale = 1L << 16;
02623 metrics->y_scale = 1L << 16;
02624 }
02625 }
02626
02627
02628
02629
02630 FT_EXPORT_DEF( FT_Error )
02631 FT_Select_Size( FT_Face face,
02632 FT_Int strike_index )
02633 {
02634 FT_Driver_Class clazz;
02635
02636
02637 if ( !face || !FT_HAS_FIXED_SIZES( face ) )
02638 return FT_Err_Invalid_Face_Handle;
02639
02640 if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
02641 return FT_Err_Invalid_Argument;
02642
02643 clazz = face->driver->clazz;
02644
02645 if ( clazz->select_size )
02646 return clazz->select_size( face->size, (FT_ULong)strike_index );
02647
02648 FT_Select_Metrics( face, (FT_ULong)strike_index );
02649
02650 return FT_Err_Ok;
02651 }
02652
02653
02654
02655
02656 FT_EXPORT_DEF( FT_Error )
02657 FT_Request_Size( FT_Face face,
02658 FT_Size_Request req )
02659 {
02660 FT_Driver_Class clazz;
02661 FT_ULong strike_index;
02662
02663
02664 if ( !face )
02665 return FT_Err_Invalid_Face_Handle;
02666
02667 if ( !req || req->width < 0 || req->height < 0 ||
02668 req->type >= FT_SIZE_REQUEST_TYPE_MAX )
02669 return FT_Err_Invalid_Argument;
02670
02671 clazz = face->driver->clazz;
02672
02673 if ( clazz->request_size )
02674 return clazz->request_size( face->size, req );
02675
02676
02677
02678
02679
02680
02681
02682
02683 if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
02684 {
02685 FT_Error error;
02686
02687
02688 error = FT_Match_Size( face, req, 0, &strike_index );
02689 if ( error )
02690 return error;
02691
02692 FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",
02693 strike_index ));
02694
02695 return FT_Select_Size( face, (FT_Int)strike_index );
02696 }
02697
02698 FT_Request_Metrics( face, req );
02699
02700 return FT_Err_Ok;
02701 }
02702
02703
02704
02705
02706 FT_EXPORT_DEF( FT_Error )
02707 FT_Set_Char_Size( FT_Face face,
02708 FT_F26Dot6 char_width,
02709 FT_F26Dot6 char_height,
02710 FT_UInt horz_resolution,
02711 FT_UInt vert_resolution )
02712 {
02713 FT_Size_RequestRec req;
02714
02715
02716 if ( !char_width )
02717 char_width = char_height;
02718 else if ( !char_height )
02719 char_height = char_width;
02720
02721 if ( !horz_resolution )
02722 horz_resolution = vert_resolution;
02723 else if ( !vert_resolution )
02724 vert_resolution = horz_resolution;
02725
02726 if ( char_width < 1 * 64 )
02727 char_width = 1 * 64;
02728 if ( char_height < 1 * 64 )
02729 char_height = 1 * 64;
02730
02731 if ( !horz_resolution )
02732 horz_resolution = vert_resolution = 72;
02733
02734 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
02735 req.width = char_width;
02736 req.height = char_height;
02737 req.horiResolution = horz_resolution;
02738 req.vertResolution = vert_resolution;
02739
02740 return FT_Request_Size( face, &req );
02741 }
02742
02743
02744
02745
02746 FT_EXPORT_DEF( FT_Error )
02747 FT_Set_Pixel_Sizes( FT_Face face,
02748 FT_UInt pixel_width,
02749 FT_UInt pixel_height )
02750 {
02751 FT_Size_RequestRec req;
02752
02753
02754 if ( pixel_width == 0 )
02755 pixel_width = pixel_height;
02756 else if ( pixel_height == 0 )
02757 pixel_height = pixel_width;
02758
02759 if ( pixel_width < 1 )
02760 pixel_width = 1;
02761 if ( pixel_height < 1 )
02762 pixel_height = 1;
02763
02764
02765 if ( pixel_width >= 0xFFFFU )
02766 pixel_width = 0xFFFFU;
02767 if ( pixel_height >= 0xFFFFU )
02768 pixel_height = 0xFFFFU;
02769
02770 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
02771 req.width = pixel_width << 6;
02772 req.height = pixel_height << 6;
02773 req.horiResolution = 0;
02774 req.vertResolution = 0;
02775
02776 return FT_Request_Size( face, &req );
02777 }
02778
02779
02780
02781
02782 FT_EXPORT_DEF( FT_Error )
02783 FT_Get_Kerning( FT_Face face,
02784 FT_UInt left_glyph,
02785 FT_UInt right_glyph,
02786 FT_UInt kern_mode,
02787 FT_Vector *akerning )
02788 {
02789 FT_Error error = FT_Err_Ok;
02790 FT_Driver driver;
02791
02792
02793 if ( !face )
02794 return FT_Err_Invalid_Face_Handle;
02795
02796 if ( !akerning )
02797 return FT_Err_Invalid_Argument;
02798
02799 driver = face->driver;
02800
02801 akerning->x = 0;
02802 akerning->y = 0;
02803
02804 if ( driver->clazz->get_kerning )
02805 {
02806 error = driver->clazz->get_kerning( face,
02807 left_glyph,
02808 right_glyph,
02809 akerning );
02810 if ( !error )
02811 {
02812 if ( kern_mode != FT_KERNING_UNSCALED )
02813 {
02814 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
02815 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
02816
02817 if ( kern_mode != FT_KERNING_UNFITTED )
02818 {
02819
02820
02821
02822 if ( face->size->metrics.x_ppem < 25 )
02823 akerning->x = FT_MulDiv( akerning->x,
02824 face->size->metrics.x_ppem, 25 );
02825 if ( face->size->metrics.y_ppem < 25 )
02826 akerning->y = FT_MulDiv( akerning->y,
02827 face->size->metrics.y_ppem, 25 );
02828
02829 akerning->x = FT_PIX_ROUND( akerning->x );
02830 akerning->y = FT_PIX_ROUND( akerning->y );
02831 }
02832 }
02833 }
02834 }
02835
02836 return error;
02837 }
02838
02839
02840
02841
02842 FT_EXPORT_DEF( FT_Error )
02843 FT_Get_Track_Kerning( FT_Face face,
02844 FT_Fixed point_size,
02845 FT_Int degree,
02846 FT_Fixed* akerning )
02847 {
02848 FT_Service_Kerning service;
02849 FT_Error error = FT_Err_Ok;
02850
02851
02852 if ( !face )
02853 return FT_Err_Invalid_Face_Handle;
02854
02855 if ( !akerning )
02856 return FT_Err_Invalid_Argument;
02857
02858 FT_FACE_FIND_SERVICE( face, service, KERNING );
02859 if ( !service )
02860 return FT_Err_Unimplemented_Feature;
02861
02862 error = service->get_track( face,
02863 point_size,
02864 degree,
02865 akerning );
02866
02867 return error;
02868 }
02869
02870
02871
02872
02873 FT_EXPORT_DEF( FT_Error )
02874 FT_Select_Charmap( FT_Face face,
02875 FT_Encoding encoding )
02876 {
02877 FT_CharMap* cur;
02878 FT_CharMap* limit;
02879
02880
02881 if ( !face )
02882 return FT_Err_Invalid_Face_Handle;
02883
02884 if ( encoding == FT_ENCODING_NONE )
02885 return FT_Err_Invalid_Argument;
02886
02887
02888
02889
02890
02891 if ( encoding == FT_ENCODING_UNICODE )
02892 return find_unicode_charmap( face );
02893
02894 cur = face->charmaps;
02895 if ( !cur )
02896 return FT_Err_Invalid_CharMap_Handle;
02897
02898 limit = cur + face->num_charmaps;
02899
02900 for ( ; cur < limit; cur++ )
02901 {
02902 if ( cur[0]->encoding == encoding )
02903 {
02904 face->charmap = cur[0];
02905 return 0;
02906 }
02907 }
02908
02909 return FT_Err_Invalid_Argument;
02910 }
02911
02912
02913
02914
02915 FT_EXPORT_DEF( FT_Error )
02916 FT_Set_Charmap( FT_Face face,
02917 FT_CharMap charmap )
02918 {
02919 FT_CharMap* cur;
02920 FT_CharMap* limit;
02921
02922
02923 if ( !face )
02924 return FT_Err_Invalid_Face_Handle;
02925
02926 cur = face->charmaps;
02927 if ( !cur )
02928 return FT_Err_Invalid_CharMap_Handle;
02929 if ( FT_Get_CMap_Format( charmap ) == 14 )
02930 return FT_Err_Invalid_Argument;
02931
02932 limit = cur + face->num_charmaps;
02933
02934 for ( ; cur < limit; cur++ )
02935 {
02936 if ( cur[0] == charmap )
02937 {
02938 face->charmap = cur[0];
02939 return 0;
02940 }
02941 }
02942 return FT_Err_Invalid_Argument;
02943 }
02944
02945
02946
02947
02948 FT_EXPORT_DEF( FT_Int )
02949 FT_Get_Charmap_Index( FT_CharMap charmap )
02950 {
02951 FT_Int i;
02952
02953
02954 for ( i = 0; i < charmap->face->num_charmaps; i++ )
02955 if ( charmap->face->charmaps[i] == charmap )
02956 break;
02957
02958 FT_ASSERT( i < charmap->face->num_charmaps );
02959
02960 return i;
02961 }
02962
02963
02964 static void
02965 ft_cmap_done_internal( FT_CMap cmap )
02966 {
02967 FT_CMap_Class clazz = cmap->clazz;
02968 FT_Face face = cmap->charmap.face;
02969 FT_Memory memory = FT_FACE_MEMORY(face);
02970
02971
02972 if ( clazz->done )
02973 clazz->done( cmap );
02974
02975 FT_FREE( cmap );
02976 }
02977
02978
02979 FT_BASE_DEF( void )
02980 FT_CMap_Done( FT_CMap cmap )
02981 {
02982 if ( cmap )
02983 {
02984 FT_Face face = cmap->charmap.face;
02985 FT_Memory memory = FT_FACE_MEMORY( face );
02986 FT_Error error;
02987 FT_Int i, j;
02988
02989
02990 for ( i = 0; i < face->num_charmaps; i++ )
02991 {
02992 if ( (FT_CMap)face->charmaps[i] == cmap )
02993 {
02994 FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1];
02995
02996
02997 if ( FT_RENEW_ARRAY( face->charmaps,
02998 face->num_charmaps,
02999 face->num_charmaps - 1 ) )
03000 return;
03001
03002
03003 for ( j = i + 1; j < face->num_charmaps; j++ )
03004 {
03005 if ( j == face->num_charmaps - 1 )
03006 face->charmaps[j - 1] = last_charmap;
03007 else
03008 face->charmaps[j - 1] = face->charmaps[j];
03009 }
03010
03011 face->num_charmaps--;
03012
03013 if ( (FT_CMap)face->charmap == cmap )
03014 face->charmap = NULL;
03015
03016 ft_cmap_done_internal( cmap );
03017
03018 break;
03019 }
03020 }
03021 }
03022 }
03023
03024
03025 FT_BASE_DEF( FT_Error )
03026 FT_CMap_New( FT_CMap_Class clazz,
03027 FT_Pointer init_data,
03028 FT_CharMap charmap,
03029 FT_CMap *acmap )
03030 {
03031 FT_Error error = FT_Err_Ok;
03032 FT_Face face;
03033 FT_Memory memory;
03034 FT_CMap cmap;
03035
03036
03037 if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
03038 return FT_Err_Invalid_Argument;
03039
03040 face = charmap->face;
03041 memory = FT_FACE_MEMORY( face );
03042
03043 if ( !FT_ALLOC( cmap, clazz->size ) )
03044 {
03045 cmap->charmap = *charmap;
03046 cmap->clazz = clazz;
03047
03048 if ( clazz->init )
03049 {
03050 error = clazz->init( cmap, init_data );
03051 if ( error )
03052 goto Fail;
03053 }
03054
03055
03056 if ( FT_RENEW_ARRAY( face->charmaps,
03057 face->num_charmaps,
03058 face->num_charmaps + 1 ) )
03059 goto Fail;
03060
03061 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
03062 }
03063
03064 Exit:
03065 if ( acmap )
03066 *acmap = cmap;
03067
03068 return error;
03069
03070 Fail:
03071 ft_cmap_done_internal( cmap );
03072 cmap = NULL;
03073 goto Exit;
03074 }
03075
03076
03077
03078
03079 FT_EXPORT_DEF( FT_UInt )
03080 FT_Get_Char_Index( FT_Face face,
03081 FT_ULong charcode )
03082 {
03083 FT_UInt result = 0;
03084
03085
03086 if ( face && face->charmap )
03087 {
03088 FT_CMap cmap = FT_CMAP( face->charmap );
03089
03090
03091 if ( charcode > 0xFFFFFFFFUL )
03092 {
03093 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
03094 FT_TRACE1(( " 0x%x is truncated\n", charcode ));
03095 }
03096 result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode );
03097 }
03098 return result;
03099 }
03100
03101
03102
03103
03104 FT_EXPORT_DEF( FT_ULong )
03105 FT_Get_First_Char( FT_Face face,
03106 FT_UInt *agindex )
03107 {
03108 FT_ULong result = 0;
03109 FT_UInt gindex = 0;
03110
03111
03112 if ( face && face->charmap )
03113 {
03114 gindex = FT_Get_Char_Index( face, 0 );
03115 if ( gindex == 0 )
03116 result = FT_Get_Next_Char( face, 0, &gindex );
03117 }
03118
03119 if ( agindex )
03120 *agindex = gindex;
03121
03122 return result;
03123 }
03124
03125
03126
03127
03128 FT_EXPORT_DEF( FT_ULong )
03129 FT_Get_Next_Char( FT_Face face,
03130 FT_ULong charcode,
03131 FT_UInt *agindex )
03132 {
03133 FT_ULong result = 0;
03134 FT_UInt gindex = 0;
03135
03136
03137 if ( face && face->charmap )
03138 {
03139 FT_UInt32 code = (FT_UInt32)charcode;
03140 FT_CMap cmap = FT_CMAP( face->charmap );
03141
03142
03143 gindex = cmap->clazz->char_next( cmap, &code );
03144 result = ( gindex == 0 ) ? 0 : code;
03145 }
03146
03147 if ( agindex )
03148 *agindex = gindex;
03149
03150 return result;
03151 }
03152
03153
03154
03155
03156 FT_EXPORT_DEF( FT_UInt )
03157 FT_Face_GetCharVariantIndex( FT_Face face,
03158 FT_ULong charcode,
03159 FT_ULong variantSelector )
03160 {
03161 FT_UInt result = 0;
03162
03163
03164 if ( face && face->charmap &&
03165 face->charmap->encoding == FT_ENCODING_UNICODE )
03166 {
03167 FT_CharMap charmap = find_variant_selector_charmap( face );
03168 FT_CMap ucmap = FT_CMAP( face->charmap );
03169
03170
03171 if ( charmap != NULL )
03172 {
03173 FT_CMap vcmap = FT_CMAP( charmap );
03174
03175
03176 if ( charcode > 0xFFFFFFFFUL )
03177 {
03178 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
03179 FT_TRACE1(( " 0x%x is truncated\n", charcode ));
03180 }
03181 if ( variantSelector > 0xFFFFFFFFUL )
03182 {
03183 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
03184 FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
03185 }
03186
03187 result = vcmap->clazz->char_var_index( vcmap, ucmap,
03188 (FT_UInt32)charcode,
03189 (FT_UInt32)variantSelector );
03190 }
03191 }
03192
03193 return result;
03194 }
03195
03196
03197
03198
03199 FT_EXPORT_DEF( FT_Int )
03200 FT_Face_GetCharVariantIsDefault( FT_Face face,
03201 FT_ULong charcode,
03202 FT_ULong variantSelector )
03203 {
03204 FT_Int result = -1;
03205
03206
03207 if ( face )
03208 {
03209 FT_CharMap charmap = find_variant_selector_charmap( face );
03210
03211
03212 if ( charmap != NULL )
03213 {
03214 FT_CMap vcmap = FT_CMAP( charmap );
03215
03216
03217 if ( charcode > 0xFFFFFFFFUL )
03218 {
03219 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
03220 FT_TRACE1(( " 0x%x is truncated\n", charcode ));
03221 }
03222 if ( variantSelector > 0xFFFFFFFFUL )
03223 {
03224 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
03225 FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
03226 }
03227
03228 result = vcmap->clazz->char_var_default( vcmap,
03229 (FT_UInt32)charcode,
03230 (FT_UInt32)variantSelector );
03231 }
03232 }
03233
03234 return result;
03235 }
03236
03237
03238
03239
03240 FT_EXPORT_DEF( FT_UInt32* )
03241 FT_Face_GetVariantSelectors( FT_Face face )
03242 {
03243 FT_UInt32 *result = NULL;
03244
03245
03246 if ( face )
03247 {
03248 FT_CharMap charmap = find_variant_selector_charmap( face );
03249
03250
03251 if ( charmap != NULL )
03252 {
03253 FT_CMap vcmap = FT_CMAP( charmap );
03254 FT_Memory memory = FT_FACE_MEMORY( face );
03255
03256
03257 result = vcmap->clazz->variant_list( vcmap, memory );
03258 }
03259 }
03260
03261 return result;
03262 }
03263
03264
03265
03266
03267 FT_EXPORT_DEF( FT_UInt32* )
03268 FT_Face_GetVariantsOfChar( FT_Face face,
03269 FT_ULong charcode )
03270 {
03271 FT_UInt32 *result = NULL;
03272
03273
03274 if ( face )
03275 {
03276 FT_CharMap charmap = find_variant_selector_charmap( face );
03277
03278
03279 if ( charmap != NULL )
03280 {
03281 FT_CMap vcmap = FT_CMAP( charmap );
03282 FT_Memory memory = FT_FACE_MEMORY( face );
03283
03284
03285 if ( charcode > 0xFFFFFFFFUL )
03286 {
03287 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
03288 FT_TRACE1(( " 0x%x is truncated\n", charcode ));
03289 }
03290
03291 result = vcmap->clazz->charvariant_list( vcmap, memory,
03292 (FT_UInt32)charcode );
03293 }
03294 }
03295 return result;
03296 }
03297
03298
03299
03300
03301 FT_EXPORT_DEF( FT_UInt32* )
03302 FT_Face_GetCharsOfVariant( FT_Face face,
03303 FT_ULong variantSelector )
03304 {
03305 FT_UInt32 *result = NULL;
03306
03307
03308 if ( face )
03309 {
03310 FT_CharMap charmap = find_variant_selector_charmap( face );
03311
03312
03313 if ( charmap != NULL )
03314 {
03315 FT_CMap vcmap = FT_CMAP( charmap );
03316 FT_Memory memory = FT_FACE_MEMORY( face );
03317
03318
03319 if ( variantSelector > 0xFFFFFFFFUL )
03320 {
03321 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
03322 FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
03323 }
03324
03325 result = vcmap->clazz->variantchar_list( vcmap, memory,
03326 (FT_UInt32)variantSelector );
03327 }
03328 }
03329
03330 return result;
03331 }
03332
03333
03334
03335
03336 FT_EXPORT_DEF( FT_UInt )
03337 FT_Get_Name_Index( FT_Face face,
03338 FT_String* glyph_name )
03339 {
03340 FT_UInt result = 0;
03341
03342
03343 if ( face && FT_HAS_GLYPH_NAMES( face ) )
03344 {
03345 FT_Service_GlyphDict service;
03346
03347
03348 FT_FACE_LOOKUP_SERVICE( face,
03349 service,
03350 GLYPH_DICT );
03351
03352 if ( service && service->name_index )
03353 result = service->name_index( face, glyph_name );
03354 }
03355
03356 return result;
03357 }
03358
03359
03360
03361
03362 FT_EXPORT_DEF( FT_Error )
03363 FT_Get_Glyph_Name( FT_Face face,
03364 FT_UInt glyph_index,
03365 FT_Pointer buffer,
03366 FT_UInt buffer_max )
03367 {
03368 FT_Error error = FT_Err_Invalid_Argument;
03369
03370
03371
03372 if ( buffer && buffer_max > 0 )
03373 ((FT_Byte*)buffer)[0] = 0;
03374
03375 if ( face &&
03376 (FT_Long)glyph_index <= face->num_glyphs &&
03377 FT_HAS_GLYPH_NAMES( face ) )
03378 {
03379 FT_Service_GlyphDict service;
03380
03381
03382 FT_FACE_LOOKUP_SERVICE( face,
03383 service,
03384 GLYPH_DICT );
03385
03386 if ( service && service->get_name )
03387 error = service->get_name( face, glyph_index, buffer, buffer_max );
03388 }
03389
03390 return error;
03391 }
03392
03393
03394
03395
03396 FT_EXPORT_DEF( const char* )
03397 FT_Get_Postscript_Name( FT_Face face )
03398 {
03399 const char* result = NULL;
03400
03401
03402 if ( !face )
03403 goto Exit;
03404
03405 if ( !result )
03406 {
03407 FT_Service_PsFontName service;
03408
03409
03410 FT_FACE_LOOKUP_SERVICE( face,
03411 service,
03412 POSTSCRIPT_FONT_NAME );
03413
03414 if ( service && service->get_ps_font_name )
03415 result = service->get_ps_font_name( face );
03416 }
03417
03418 Exit:
03419 return result;
03420 }
03421
03422
03423
03424
03425 FT_EXPORT_DEF( void* )
03426 FT_Get_Sfnt_Table( FT_Face face,
03427 FT_Sfnt_Tag tag )
03428 {
03429 void* table = 0;
03430 FT_Service_SFNT_Table service;
03431
03432
03433 if ( face && FT_IS_SFNT( face ) )
03434 {
03435 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
03436 if ( service != NULL )
03437 table = service->get_table( face, tag );
03438 }
03439
03440 return table;
03441 }
03442
03443
03444
03445
03446 FT_EXPORT_DEF( FT_Error )
03447 FT_Load_Sfnt_Table( FT_Face face,
03448 FT_ULong tag,
03449 FT_Long offset,
03450 FT_Byte* buffer,
03451 FT_ULong* length )
03452 {
03453 FT_Service_SFNT_Table service;
03454
03455
03456 if ( !face || !FT_IS_SFNT( face ) )
03457 return FT_Err_Invalid_Face_Handle;
03458
03459 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
03460 if ( service == NULL )
03461 return FT_Err_Unimplemented_Feature;
03462
03463 return service->load_table( face, tag, offset, buffer, length );
03464 }
03465
03466
03467
03468
03469 FT_EXPORT_DEF( FT_Error )
03470 FT_Sfnt_Table_Info( FT_Face face,
03471 FT_UInt table_index,
03472 FT_ULong *tag,
03473 FT_ULong *length )
03474 {
03475 FT_Service_SFNT_Table service;
03476 FT_ULong offset;
03477
03478
03479 if ( !face || !FT_IS_SFNT( face ) )
03480 return FT_Err_Invalid_Face_Handle;
03481
03482 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
03483 if ( service == NULL )
03484 return FT_Err_Unimplemented_Feature;
03485
03486 return service->table_info( face, table_index, tag, &offset, length );
03487 }
03488
03489
03490
03491
03492 FT_EXPORT_DEF( FT_ULong )
03493 FT_Get_CMap_Language_ID( FT_CharMap charmap )
03494 {
03495 FT_Service_TTCMaps service;
03496 FT_Face face;
03497 TT_CMapInfo cmap_info;
03498
03499
03500 if ( !charmap || !charmap->face )
03501 return 0;
03502
03503 face = charmap->face;
03504 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
03505 if ( service == NULL )
03506 return 0;
03507 if ( service->get_cmap_info( charmap, &cmap_info ))
03508 return 0;
03509
03510 return cmap_info.language;
03511 }
03512
03513
03514
03515
03516 FT_EXPORT_DEF( FT_Long )
03517 FT_Get_CMap_Format( FT_CharMap charmap )
03518 {
03519 FT_Service_TTCMaps service;
03520 FT_Face face;
03521 TT_CMapInfo cmap_info;
03522
03523
03524 if ( !charmap || !charmap->face )
03525 return -1;
03526
03527 face = charmap->face;
03528 FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
03529 if ( service == NULL )
03530 return -1;
03531 if ( service->get_cmap_info( charmap, &cmap_info ))
03532 return -1;
03533
03534 return cmap_info.format;
03535 }
03536
03537
03538
03539
03540 FT_EXPORT_DEF( FT_Error )
03541 FT_Activate_Size( FT_Size size )
03542 {
03543 FT_Face face;
03544
03545
03546 if ( size == NULL )
03547 return FT_Err_Invalid_Argument;
03548
03549 face = size->face;
03550 if ( face == NULL || face->driver == NULL )
03551 return FT_Err_Invalid_Argument;
03552
03553
03554
03555 face->size = size;
03556
03557 return FT_Err_Ok;
03558 }
03559
03560
03561
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574 FT_BASE_DEF( FT_Renderer )
03575 FT_Lookup_Renderer( FT_Library library,
03576 FT_Glyph_Format format,
03577 FT_ListNode* node )
03578 {
03579 FT_ListNode cur;
03580 FT_Renderer result = 0;
03581
03582
03583 if ( !library )
03584 goto Exit;
03585
03586 cur = library->renderers.head;
03587
03588 if ( node )
03589 {
03590 if ( *node )
03591 cur = (*node)->next;
03592 *node = 0;
03593 }
03594
03595 while ( cur )
03596 {
03597 FT_Renderer renderer = FT_RENDERER( cur->data );
03598
03599
03600 if ( renderer->glyph_format == format )
03601 {
03602 if ( node )
03603 *node = cur;
03604
03605 result = renderer;
03606 break;
03607 }
03608 cur = cur->next;
03609 }
03610
03611 Exit:
03612 return result;
03613 }
03614
03615
03616 static FT_Renderer
03617 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
03618 {
03619 FT_Face face = slot->face;
03620 FT_Library library = FT_FACE_LIBRARY( face );
03621 FT_Renderer result = library->cur_renderer;
03622
03623
03624 if ( !result || result->glyph_format != slot->format )
03625 result = FT_Lookup_Renderer( library, slot->format, 0 );
03626
03627 return result;
03628 }
03629
03630
03631 static void
03632 ft_set_current_renderer( FT_Library library )
03633 {
03634 FT_Renderer renderer;
03635
03636
03637 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
03638 library->cur_renderer = renderer;
03639 }
03640
03641
03642 static FT_Error
03643 ft_add_renderer( FT_Module module )
03644 {
03645 FT_Library library = module->library;
03646 FT_Memory memory = library->memory;
03647 FT_Error error;
03648 FT_ListNode node;
03649
03650
03651 if ( FT_NEW( node ) )
03652 goto Exit;
03653
03654 {
03655 FT_Renderer render = FT_RENDERER( module );
03656 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
03657
03658
03659 render->clazz = clazz;
03660 render->glyph_format = clazz->glyph_format;
03661
03662
03663 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
03664 clazz->raster_class->raster_new )
03665 {
03666 error = clazz->raster_class->raster_new( memory, &render->raster );
03667 if ( error )
03668 goto Fail;
03669
03670 render->raster_render = clazz->raster_class->raster_render;
03671 render->render = clazz->render_glyph;
03672 }
03673
03674
03675 node->data = module;
03676 FT_List_Add( &library->renderers, node );
03677
03678 ft_set_current_renderer( library );
03679 }
03680
03681 Fail:
03682 if ( error )
03683 FT_FREE( node );
03684
03685 Exit:
03686 return error;
03687 }
03688
03689
03690 static void
03691 ft_remove_renderer( FT_Module module )
03692 {
03693 FT_Library library = module->library;
03694 FT_Memory memory = library->memory;
03695 FT_ListNode node;
03696
03697
03698 node = FT_List_Find( &library->renderers, module );
03699 if ( node )
03700 {
03701 FT_Renderer render = FT_RENDERER( module );
03702
03703
03704
03705 if ( render->raster )
03706 render->clazz->raster_class->raster_done( render->raster );
03707
03708
03709 FT_List_Remove( &library->renderers, node );
03710 FT_FREE( node );
03711
03712 ft_set_current_renderer( library );
03713 }
03714 }
03715
03716
03717
03718
03719 FT_EXPORT_DEF( FT_Renderer )
03720 FT_Get_Renderer( FT_Library library,
03721 FT_Glyph_Format format )
03722 {
03723
03724
03725 return FT_Lookup_Renderer( library, format, 0 );
03726 }
03727
03728
03729
03730
03731 FT_EXPORT_DEF( FT_Error )
03732 FT_Set_Renderer( FT_Library library,
03733 FT_Renderer renderer,
03734 FT_UInt num_params,
03735 FT_Parameter* parameters )
03736 {
03737 FT_ListNode node;
03738 FT_Error error = FT_Err_Ok;
03739
03740
03741 if ( !library )
03742 return FT_Err_Invalid_Library_Handle;
03743
03744 if ( !renderer )
03745 return FT_Err_Invalid_Argument;
03746
03747 node = FT_List_Find( &library->renderers, renderer );
03748 if ( !node )
03749 {
03750 error = FT_Err_Invalid_Argument;
03751 goto Exit;
03752 }
03753
03754 FT_List_Up( &library->renderers, node );
03755
03756 if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
03757 library->cur_renderer = renderer;
03758
03759 if ( num_params > 0 )
03760 {
03761 FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;
03762
03763
03764 for ( ; num_params > 0; num_params-- )
03765 {
03766 error = set_mode( renderer, parameters->tag, parameters->data );
03767 if ( error )
03768 break;
03769 }
03770 }
03771
03772 Exit:
03773 return error;
03774 }
03775
03776
03777 FT_BASE_DEF( FT_Error )
03778 FT_Render_Glyph_Internal( FT_Library library,
03779 FT_GlyphSlot slot,
03780 FT_Render_Mode render_mode )
03781 {
03782 FT_Error error = FT_Err_Ok;
03783 FT_Renderer renderer;
03784
03785
03786
03787 switch ( slot->format )
03788 {
03789 case FT_GLYPH_FORMAT_BITMAP:
03790 break;
03791
03792 default:
03793 {
03794 FT_ListNode node = 0;
03795 FT_Bool update = 0;
03796
03797
03798
03799 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
03800 {
03801 renderer = library->cur_renderer;
03802 node = library->renderers.head;
03803 }
03804 else
03805 renderer = FT_Lookup_Renderer( library, slot->format, &node );
03806
03807 error = FT_Err_Unimplemented_Feature;
03808 while ( renderer )
03809 {
03810 error = renderer->render( renderer, slot, render_mode, NULL );
03811 if ( !error ||
03812 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
03813 break;
03814
03815
03816
03817
03818
03819
03820
03821 renderer = FT_Lookup_Renderer( library, slot->format, &node );
03822 update = 1;
03823 }
03824
03825
03826
03827 if ( !error && update && renderer )
03828 FT_Set_Renderer( library, renderer, 0, 0 );
03829 }
03830 }
03831
03832 return error;
03833 }
03834
03835
03836
03837
03838 FT_EXPORT_DEF( FT_Error )
03839 FT_Render_Glyph( FT_GlyphSlot slot,
03840 FT_Render_Mode render_mode )
03841 {
03842 FT_Library library;
03843
03844
03845 if ( !slot )
03846 return FT_Err_Invalid_Argument;
03847
03848 library = FT_FACE_LIBRARY( slot->face );
03849
03850 return FT_Render_Glyph_Internal( library, slot, render_mode );
03851 }
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871
03872
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882 static void
03883 Destroy_Module( FT_Module module )
03884 {
03885 FT_Memory memory = module->memory;
03886 FT_Module_Class* clazz = module->clazz;
03887 FT_Library library = module->library;
03888
03889
03890
03891 if ( module->generic.finalizer )
03892 module->generic.finalizer( module );
03893
03894 if ( library && library->auto_hinter == module )
03895 library->auto_hinter = 0;
03896
03897
03898 if ( FT_MODULE_IS_RENDERER( module ) )
03899 ft_remove_renderer( module );
03900
03901
03902 if ( FT_MODULE_IS_DRIVER( module ) )
03903 Destroy_Driver( FT_DRIVER( module ) );
03904
03905
03906 if ( clazz->module_done )
03907 clazz->module_done( module );
03908
03909
03910 FT_FREE( module );
03911 }
03912
03913
03914
03915
03916 FT_EXPORT_DEF( FT_Error )
03917 FT_Add_Module( FT_Library library,
03918 const FT_Module_Class* clazz )
03919 {
03920 FT_Error error;
03921 FT_Memory memory;
03922 FT_Module module;
03923 FT_UInt nn;
03924
03925
03926 #define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
03927 FREETYPE_MINOR )
03928
03929 if ( !library )
03930 return FT_Err_Invalid_Library_Handle;
03931
03932 if ( !clazz )
03933 return FT_Err_Invalid_Argument;
03934
03935
03936 if ( clazz->module_requires > FREETYPE_VER_FIXED )
03937 return FT_Err_Invalid_Version;
03938
03939
03940 for ( nn = 0; nn < library->num_modules; nn++ )
03941 {
03942 module = library->modules[nn];
03943 if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
03944 {
03945
03946 if ( clazz->module_version <= module->clazz->module_version )
03947 return FT_Err_Lower_Module_Version;
03948
03949
03950
03951 FT_Remove_Module( library, module );
03952 break;
03953 }
03954 }
03955
03956 memory = library->memory;
03957 error = FT_Err_Ok;
03958
03959 if ( library->num_modules >= FT_MAX_MODULES )
03960 {
03961 error = FT_Err_Too_Many_Drivers;
03962 goto Exit;
03963 }
03964
03965
03966 if ( FT_ALLOC( module, clazz->module_size ) )
03967 goto Exit;
03968
03969
03970 module->library = library;
03971 module->memory = memory;
03972 module->clazz = (FT_Module_Class*)clazz;
03973
03974
03975
03976 if ( FT_MODULE_IS_RENDERER( module ) )
03977 {
03978
03979 error = ft_add_renderer( module );
03980 if ( error )
03981 goto Fail;
03982 }
03983
03984
03985 if ( FT_MODULE_IS_HINTER( module ) )
03986 library->auto_hinter = module;
03987
03988
03989 if ( FT_MODULE_IS_DRIVER( module ) )
03990 {
03991
03992 FT_Driver driver = FT_DRIVER( module );
03993
03994
03995 driver->clazz = (FT_Driver_Class)module->clazz;
03996 if ( FT_DRIVER_USES_OUTLINES( driver ) )
03997 {
03998 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
03999 if ( error )
04000 goto Fail;
04001 }
04002 }
04003
04004 if ( clazz->module_init )
04005 {
04006 error = clazz->module_init( module );
04007 if ( error )
04008 goto Fail;
04009 }
04010
04011
04012 library->modules[library->num_modules++] = module;
04013
04014 Exit:
04015 return error;
04016
04017 Fail:
04018 if ( FT_MODULE_IS_DRIVER( module ) )
04019 {
04020 FT_Driver driver = FT_DRIVER( module );
04021
04022
04023 if ( FT_DRIVER_USES_OUTLINES( driver ) )
04024 FT_GlyphLoader_Done( driver->glyph_loader );
04025 }
04026
04027 if ( FT_MODULE_IS_RENDERER( module ) )
04028 {
04029 FT_Renderer renderer = FT_RENDERER( module );
04030
04031
04032 if ( renderer->raster )
04033 renderer->clazz->raster_class->raster_done( renderer->raster );
04034 }
04035
04036 FT_FREE( module );
04037 goto Exit;
04038 }
04039
04040
04041
04042
04043 FT_EXPORT_DEF( FT_Module )
04044 FT_Get_Module( FT_Library library,
04045 const char* module_name )
04046 {
04047 FT_Module result = 0;
04048 FT_Module* cur;
04049 FT_Module* limit;
04050
04051
04052 if ( !library || !module_name )
04053 return result;
04054
04055 cur = library->modules;
04056 limit = cur + library->num_modules;
04057
04058 for ( ; cur < limit; cur++ )
04059 if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
04060 {
04061 result = cur[0];
04062 break;
04063 }
04064
04065 return result;
04066 }
04067
04068
04069
04070
04071 FT_BASE_DEF( const void* )
04072 FT_Get_Module_Interface( FT_Library library,
04073 const char* mod_name )
04074 {
04075 FT_Module module;
04076
04077
04078
04079
04080 module = FT_Get_Module( library, mod_name );
04081
04082 return module ? module->clazz->module_interface : 0;
04083 }
04084
04085
04086 FT_BASE_DEF( FT_Pointer )
04087 ft_module_get_service( FT_Module module,
04088 const char* service_id )
04089 {
04090 FT_Pointer result = NULL;
04091
04092 if ( module )
04093 {
04094 FT_ASSERT( module->clazz && module->clazz->get_interface );
04095
04096
04097
04098 if ( module->clazz->get_interface )
04099 result = module->clazz->get_interface( module, service_id );
04100
04101 if ( result == NULL )
04102 {
04103
04104
04105 FT_Library library = module->library;
04106 FT_Module* cur = library->modules;
04107 FT_Module* limit = cur + library->num_modules;
04108
04109 for ( ; cur < limit; cur++ )
04110 {
04111 if ( cur[0] != module )
04112 {
04113 FT_ASSERT( cur[0]->clazz );
04114
04115 if ( cur[0]->clazz->get_interface )
04116 {
04117 result = cur[0]->clazz->get_interface( cur[0], service_id );
04118 if ( result != NULL )
04119 break;
04120 }
04121 }
04122 }
04123 }
04124 }
04125
04126 return result;
04127 }
04128
04129
04130
04131
04132 FT_EXPORT_DEF( FT_Error )
04133 FT_Remove_Module( FT_Library library,
04134 FT_Module module )
04135 {
04136
04137
04138 if ( !library )
04139 return FT_Err_Invalid_Library_Handle;
04140
04141 if ( module )
04142 {
04143 FT_Module* cur = library->modules;
04144 FT_Module* limit = cur + library->num_modules;
04145
04146
04147 for ( ; cur < limit; cur++ )
04148 {
04149 if ( cur[0] == module )
04150 {
04151
04152 library->num_modules--;
04153 limit--;
04154 while ( cur < limit )
04155 {
04156 cur[0] = cur[1];
04157 cur++;
04158 }
04159 limit[0] = 0;
04160
04161
04162 Destroy_Module( module );
04163
04164 return FT_Err_Ok;
04165 }
04166 }
04167 }
04168 return FT_Err_Invalid_Driver_Handle;
04169 }
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187 FT_EXPORT_DEF( FT_Error )
04188 FT_New_Library( FT_Memory memory,
04189 FT_Library *alibrary )
04190 {
04191 FT_Library library = 0;
04192 FT_Error error;
04193
04194
04195 if ( !memory )
04196 return FT_Err_Invalid_Argument;
04197
04198 #ifdef FT_DEBUG_LEVEL_ERROR
04199
04200 ft_debug_init();
04201 #endif
04202
04203
04204 if ( FT_NEW( library ) )
04205 return error;
04206
04207 library->memory = memory;
04208
04209 #ifdef FT_CONFIG_OPTION_PIC
04210
04211 error = ft_pic_container_init( library );
04212 if ( error )
04213 goto Fail;
04214 #endif
04215
04216
04217 library->raster_pool_size = FT_RENDER_POOL_SIZE;
04218 #if FT_RENDER_POOL_SIZE > 0
04219 if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
04220 goto Fail;
04221 #endif
04222
04223 library->version_major = FREETYPE_MAJOR;
04224 library->version_minor = FREETYPE_MINOR;
04225 library->version_patch = FREETYPE_PATCH;
04226
04227
04228 *alibrary = library;
04229
04230 return FT_Err_Ok;
04231
04232 Fail:
04233 #ifdef FT_CONFIG_OPTION_PIC
04234 ft_pic_container_destroy( library );
04235 #endif
04236 FT_FREE( library );
04237 return error;
04238 }
04239
04240
04241
04242
04243 FT_EXPORT_DEF( void )
04244 FT_Library_Version( FT_Library library,
04245 FT_Int *amajor,
04246 FT_Int *aminor,
04247 FT_Int *apatch )
04248 {
04249 FT_Int major = 0;
04250 FT_Int minor = 0;
04251 FT_Int patch = 0;
04252
04253
04254 if ( library )
04255 {
04256 major = library->version_major;
04257 minor = library->version_minor;
04258 patch = library->version_patch;
04259 }
04260
04261 if ( amajor )
04262 *amajor = major;
04263
04264 if ( aminor )
04265 *aminor = minor;
04266
04267 if ( apatch )
04268 *apatch = patch;
04269 }
04270
04271
04272
04273
04274 FT_EXPORT_DEF( FT_Error )
04275 FT_Done_Library( FT_Library library )
04276 {
04277 FT_Memory memory;
04278
04279
04280 if ( !library )
04281 return FT_Err_Invalid_Library_Handle;
04282
04283 memory = library->memory;
04284
04285
04286 if ( library->generic.finalizer )
04287 library->generic.finalizer( library );
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298 {
04299 FT_UInt n;
04300
04301
04302 for ( n = 0; n < library->num_modules; n++ )
04303 {
04304 FT_Module module = library->modules[n];
04305 FT_List faces;
04306
04307
04308 if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 )
04309 continue;
04310
04311 faces = &FT_DRIVER(module)->faces_list;
04312 while ( faces->head )
04313 {
04314 FT_Done_Face( FT_FACE( faces->head->data ) );
04315 if ( faces->head )
04316 FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" ));
04317 }
04318 }
04319 }
04320
04321
04322 #if 1
04323
04324
04325
04326 while ( library->num_modules > 0 )
04327 FT_Remove_Module( library,
04328 library->modules[library->num_modules - 1] );
04329 #else
04330 {
04331 FT_UInt n;
04332
04333
04334 for ( n = 0; n < library->num_modules; n++ )
04335 {
04336 FT_Module module = library->modules[n];
04337
04338
04339 if ( module )
04340 {
04341 Destroy_Module( module );
04342 library->modules[n] = 0;
04343 }
04344 }
04345 }
04346 #endif
04347
04348
04349 FT_FREE( library->raster_pool );
04350 library->raster_pool_size = 0;
04351
04352 #ifdef FT_CONFIG_OPTION_PIC
04353
04354 ft_pic_container_destroy( library );
04355 #endif
04356
04357 FT_FREE( library );
04358 return FT_Err_Ok;
04359 }
04360
04361
04362
04363
04364 FT_EXPORT_DEF( void )
04365 FT_Set_Debug_Hook( FT_Library library,
04366 FT_UInt hook_index,
04367 FT_DebugHook_Func debug_hook )
04368 {
04369 if ( library && debug_hook &&
04370 hook_index <
04371 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
04372 library->debug_hooks[hook_index] = debug_hook;
04373 }
04374
04375
04376
04377
04378 FT_EXPORT_DEF( FT_TrueTypeEngineType )
04379 FT_Get_TrueType_Engine_Type( FT_Library library )
04380 {
04381 FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE;
04382
04383
04384 if ( library )
04385 {
04386 FT_Module module = FT_Get_Module( library, "truetype" );
04387
04388
04389 if ( module )
04390 {
04391 FT_Service_TrueTypeEngine service;
04392
04393
04394 service = (FT_Service_TrueTypeEngine)
04395 ft_module_get_service( module,
04396 FT_SERVICE_ID_TRUETYPE_ENGINE );
04397 if ( service )
04398 result = service->engine_type;
04399 }
04400 }
04401
04402 return result;
04403 }
04404
04405
04406 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
04407
04408 FT_BASE_DEF( FT_Error )
04409 ft_stub_set_char_sizes( FT_Size size,
04410 FT_F26Dot6 width,
04411 FT_F26Dot6 height,
04412 FT_UInt horz_res,
04413 FT_UInt vert_res )
04414 {
04415 FT_Size_RequestRec req;
04416 FT_Driver driver = size->face->driver;
04417
04418
04419 if ( driver->clazz->request_size )
04420 {
04421 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
04422 req.width = width;
04423 req.height = height;
04424
04425 if ( horz_res == 0 )
04426 horz_res = vert_res;
04427
04428 if ( vert_res == 0 )
04429 vert_res = horz_res;
04430
04431 if ( horz_res == 0 )
04432 horz_res = vert_res = 72;
04433
04434 req.horiResolution = horz_res;
04435 req.vertResolution = vert_res;
04436
04437 return driver->clazz->request_size( size, &req );
04438 }
04439
04440 return 0;
04441 }
04442
04443
04444 FT_BASE_DEF( FT_Error )
04445 ft_stub_set_pixel_sizes( FT_Size size,
04446 FT_UInt width,
04447 FT_UInt height )
04448 {
04449 FT_Size_RequestRec req;
04450 FT_Driver driver = size->face->driver;
04451
04452
04453 if ( driver->clazz->request_size )
04454 {
04455 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
04456 req.width = width << 6;
04457 req.height = height << 6;
04458 req.horiResolution = 0;
04459 req.vertResolution = 0;
04460
04461 return driver->clazz->request_size( size, &req );
04462 }
04463
04464 return 0;
04465 }
04466
04467 #endif
04468
04469
04470 FT_EXPORT_DEF( FT_Error )
04471 FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,
04472 FT_UInt sub_index,
04473 FT_Int *p_index,
04474 FT_UInt *p_flags,
04475 FT_Int *p_arg1,
04476 FT_Int *p_arg2,
04477 FT_Matrix *p_transform )
04478 {
04479 FT_Error error = FT_Err_Invalid_Argument;
04480
04481
04482 if ( glyph != NULL &&
04483 glyph->format == FT_GLYPH_FORMAT_COMPOSITE &&
04484 sub_index < glyph->num_subglyphs )
04485 {
04486 FT_SubGlyph subg = glyph->subglyphs + sub_index;
04487
04488
04489 *p_index = subg->index;
04490 *p_flags = subg->flags;
04491 *p_arg1 = subg->arg1;
04492 *p_arg2 = subg->arg2;
04493 *p_transform = subg->transform;
04494 }
04495
04496 return error;
04497 }
04498
04499
04500