diff --git a/ChangeLog b/ChangeLog index f43832dd1..3f5877fb7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2006-02-13 Chia-I Wu + + Clean up the SFNT_Interface. Table loading functions are now named + after the tables' tags; `hdmx' is TrueType-specific and thus the code + is moved to the truetype module; `get_metrics' is moved here from the + truetype module so that the code can be shared with the cff module. + + This pass involves no real changes. That is, the code is moved + verbatim mostly. The only exception is the return value of + `tt_face_get_metrics'. + + * include/freetype/internal/sfnt.h, src/sfnt/rules.mk, + src/sfnt/sfdriver.c, src/sfnt/sfnt.c, src/sfnt/sfobjs.c, + src/sfnt/ttload.c, src/sfnt/ttload.h, src/sfnt/ttsbit.c, + src/sfnt/ttsbit.h, src/sfnt/ttsbit0.c: Clean up the SFNT_Interface. + + * src/sfnt/ttmtx.c, src/sfnt/ttmtx.h: Metrics-related tables' loading + and parsing code is moved here. + Move `tt_face_get_metrics' here from the truetype module. The return + value is changed from `void' to `FT_Error'. + + * include/freetype/internal/fttrace.h: New trace: ttmtx. + + * src/truetype/ttpload.c, src/truetype/ttpload.h: `hdmx' loading and + parsing code is moved here. + New function `tt_face_load_prep' splitted from `tt_face_load_fpgm'. + `tt_face_load_fpgm' returns `FT_Err_Ok' if `fpgm' doesn't exist. + + * src/cff/cffgload.c, src/cff/cffobjs.c: Update. + + * src/truetype/ttgload.c, src/truetype/ttobjs.c: Update. + 2006-02-11 Chia-I Wu * src/autofit/afcjk.c (af_cjk_metrics_init): Fix a stupid bug... diff --git a/include/freetype/internal/fttrace.h b/include/freetype/internal/fttrace.h index 20019b54d..b5ebd92cc 100644 --- a/include/freetype/internal/fttrace.h +++ b/include/freetype/internal/fttrace.h @@ -45,6 +45,7 @@ FT_TRACE_DEF( sfobjs ) /* SFNT object handler (sfobjs.c) */ FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */ FT_TRACE_DEF( ttkern ) /* kerning handler (ttkern.c) */ FT_TRACE_DEF( ttload ) /* basic TrueType tables (ttload.c) */ +FT_TRACE_DEF( ttmtx ) /* metrics-related tables (ttmtx.c) */ FT_TRACE_DEF( ttpost ) /* PS table processing (ttpost.c) */ FT_TRACE_DEF( ttsbit ) /* TrueType sbit handling (ttsbit.c) */ diff --git a/include/freetype/internal/sfnt.h b/include/freetype/internal/sfnt.h index 808dd9835..5753a0620 100644 --- a/include/freetype/internal/sfnt.h +++ b/include/freetype/internal/sfnt.h @@ -442,6 +442,31 @@ FT_BEGIN_HEADER /* TT_Load_Metrics_Func */ /* */ /* */ + /* Load a metrics table, which is a table comes with a horizontal */ + /* and a vertical version. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* vertical :: A boolean flag. If set, load the vertical one. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef FT_Error + (*TT_Load_Metrics_Func)( TT_Face face, + FT_Stream stream, + FT_Bool vertical ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_Metrics_Func */ + /* */ + /* */ /* Load the horizontal or vertical header in a face object. */ /* */ /* */ @@ -455,9 +480,11 @@ FT_BEGIN_HEADER /* FreeType error code. 0 means success. */ /* */ typedef FT_Error - (*TT_Load_Metrics_Func)( TT_Face face, - FT_Stream stream, - FT_Bool vertical ); + (*TT_Get_Metrics_Func)( TT_Face face, + FT_Bool vertical, + FT_UInt gindex, + FT_Short* abearing, + FT_UShort* aadvance ); /*************************************************************************/ @@ -548,39 +575,38 @@ FT_BEGIN_HEADER /* these functions are called by `load_face' but they can also */ /* be called from external modules, if there is a need to do so */ - TT_Load_Table_Func load_header; - TT_Load_Metrics_Func load_metrics; - TT_Load_Table_Func load_charmaps; - TT_Load_Table_Func load_max_profile; + TT_Load_Table_Func load_head; + TT_Load_Metrics_Func load_hhea; + TT_Load_Table_Func load_cmap; + TT_Load_Table_Func load_maxp; TT_Load_Table_Func load_os2; - TT_Load_Table_Func load_psnames; - - TT_Load_Table_Func load_names; - TT_Free_Table_Func free_names; + TT_Load_Table_Func load_post; + TT_Load_Table_Func load_name; + TT_Free_Table_Func free_name; /* optional tables */ - TT_Load_Table_Func load_hdmx; - TT_Free_Table_Func free_hdmx; - - TT_Load_Table_Func load_kerning; + TT_Load_Table_Func load_kern; TT_Load_Table_Func load_gasp; TT_Load_Table_Func load_pclt; /* see `ttload.h' */ - TT_Load_Table_Func load_bitmap_header; + TT_Load_Table_Func load_bhed; /* see `ttsbit.h' */ + TT_Load_Table_Func load_eblc; + TT_Free_Table_Func free_eblc; + TT_Set_SBit_Strike_Func set_sbit_strike; TT_Load_Strike_Metrics_Func load_strike_metrics; - TT_Load_Table_Func load_sbits; TT_Find_SBit_Image_Func find_sbit_image; TT_Load_SBit_Metrics_Func load_sbit_metrics; TT_Load_SBit_Image_Func load_sbit_image; - TT_Free_Table_Func free_sbits; /* see `ttkern.h' */ TT_Face_GetKerningFunc get_kerning; + TT_Get_Metrics_Func get_metrics; + /* see `ttpost.h' */ TT_Get_PS_Name_Func get_psname; TT_Free_Table_Func free_psnames; diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index 3b848e31d..f7f0c9a81 100644 --- a/src/cff/cffgload.c +++ b/src/cff/cffgload.c @@ -569,117 +569,6 @@ } - /*************************************************************************/ - /* */ - /* */ - /* cff_face_get_vertical_metrics */ - /* */ - /* */ - /* Return the vertical metrics in font units for a given glyph. The */ - /* metrics are the top side bearing and advance height. */ - /* */ - /* */ - /* header :: A pointer to the vertical metrics structure. */ - /* */ - /* idx :: The glyph index. */ - /* */ - /* */ - /* bearing :: The top side bearing. */ - /* */ - /* advance :: The advance height. */ - /* */ - /* */ - /* Horizontal metric values are directly computed from the CFF data, */ - /* bypassing the `hmtx' table completely. */ - /* */ -#ifdef FT_OPTIMIZE_MEMORY - - static void - cff_face_get_vertical_metrics( TT_Face face, - FT_UInt idx, - FT_Short *abearing, - FT_UShort *aadvance ) - { - TT_VertHeader* header; - FT_Byte* p; - FT_Byte* limit; - FT_UShort k; - - - header = &face->vertical; - p = face->vert_metrics; - limit = p + face->vert_metrics_size; - - k = header->number_Of_VMetrics; - - if ( k > 0 ) - { - if ( idx < (FT_UInt)k ) - { - p += 4 * idx; - if ( p + 4 > limit ) - goto NoData; - - *aadvance = FT_NEXT_USHORT( p ); - *abearing = FT_NEXT_SHORT( p ); - } - else - { - p += 4 * ( k - 1 ); - if ( p + 4 > limit ) - goto NoData; - - *aadvance = FT_NEXT_USHORT( p ); - p += 2 + 2 * ( idx - k ); - if ( p + 2 > limit ) - *abearing = 0; - else - *abearing = FT_PEEK_SHORT( p ); - } - } - else - { - NoData: - *abearing = 0; - *aadvance = 0; - } - } - -#else /* !FT_OPTIMIZE_MEMORY */ - - static void - cff_face_get_vertical_metrics( TT_Face face, - FT_UInt idx, - FT_Short *abearing, - FT_UShort *aadvance ) - { - TT_VertHeader* header = &face->vertical; - TT_LongMetrics longs_m; - FT_UShort k = header->number_Of_VMetrics; - - - if ( k == 0 ) - { - *abearing = *aadvance = 0; - return; - } - - if ( idx < (FT_UInt)k ) - { - longs_m = (TT_LongMetrics)header->long_metrics + idx; - *abearing = longs_m->bearing; - *aadvance = longs_m->advance; - } - else - { - *abearing = ((TT_ShortMetrics*)header->short_metrics)[idx - k]; - *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance; - } - } - -#endif /* !FT_OPTIMIZE_MEMORY */ - - static FT_Error cff_get_glyph_data( TT_Face face, FT_UInt glyph_index, @@ -2421,7 +2310,7 @@ if ( size->strike_index != 0xFFFFFFFFUL && - sfnt->load_sbits && + sfnt->load_eblc && ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) { TT_SBit_MetricsRec metrics; @@ -2621,8 +2510,10 @@ FT_UShort vertAdvance = 0; - cff_face_get_vertical_metrics( face, glyph_index, - &vertBearingY, &vertAdvance ); + ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, + glyph_index, + &vertBearingY, + &vertAdvance ); metrics->vertBearingY = vertBearingY; metrics->vertAdvance = vertAdvance; } diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c index a90afb4bb..08a165bc3 100644 --- a/src/cff/cffobjs.c +++ b/src/cff/cffobjs.c @@ -380,7 +380,7 @@ else { /* load the `cmap' table explicitly */ - error = sfnt->load_charmaps( face, stream ); + error = sfnt->load_cmap( face, stream ); if ( error ) goto Exit; diff --git a/src/sfnt/rules.mk b/src/sfnt/rules.mk index 6fa3f5570..24f38cbb6 100644 --- a/src/sfnt/rules.mk +++ b/src/sfnt/rules.mk @@ -26,6 +26,7 @@ SFNT_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(SFNT_DIR)) # SFNT driver sources (i.e., C files) # SFNT_DRV_SRC := $(SFNT_DIR)/ttload.c \ + $(SFNT_DIR)/ttmtx.c \ $(SFNT_DIR)/ttcmap.c \ $(SFNT_DIR)/ttsbit.c \ $(SFNT_DIR)/ttpost.c \ diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index 12529a2a2..a43ac01ed 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -389,18 +389,15 @@ tt_face_load_sfnt_header, tt_face_load_directory, - tt_face_load_header, - tt_face_load_metrics_header, + tt_face_load_head, + tt_face_load_hhea, tt_face_load_cmap, - tt_face_load_max_profile, + tt_face_load_maxp, tt_face_load_os2, - tt_face_load_postscript, + tt_face_load_post, - tt_face_load_names, - tt_face_free_names, - - tt_face_load_hdmx, - tt_face_free_hdmx, + tt_face_load_name, + tt_face_free_name, tt_face_load_kern, tt_face_load_gasp, @@ -409,12 +406,15 @@ #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS /* see `ttload.h' */ - tt_face_load_bitmap_header, + tt_face_load_bhed, + /* see `ttsbit.h' and `sfnt.h' */ + tt_face_load_eblc, + tt_face_free_eblc, + tt_face_set_sbit_strike, tt_face_load_strike_metrics, - tt_face_load_sbit_strikes, #ifdef FT_OPTIMIZE_MEMORY 0, 0, @@ -423,7 +423,6 @@ tt_load_sbit_metrics, #endif tt_face_load_sbit_image, - tt_face_free_sbit_strikes, #else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ @@ -440,6 +439,8 @@ /* see `ttkern.h' */ tt_face_get_kerning, + tt_face_get_metrics, + #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES /* see `ttpost.h' */ diff --git a/src/sfnt/sfnt.c b/src/sfnt/sfnt.c index a7b14a7a7..bba25ca65 100644 --- a/src/sfnt/sfnt.c +++ b/src/sfnt/sfnt.c @@ -20,6 +20,7 @@ #include #include "ttload.c" +#include "ttmtx.c" #include "ttcmap.c" #include "ttkern.c" #include "sfobjs.c" diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index 66196dadf..da466ae9c 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -457,36 +457,36 @@ /* if this font doesn't contain outlines, we try to load */ /* a `bhed' table */ if ( !has_outline ) - is_apple_sbit = FT_BOOL( !LOAD_( bitmap_header ) ); + is_apple_sbit = FT_BOOL( !LOAD_( bhed ) ); #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ /* load the font header (`head' table) if this isn't an Apple */ /* sbit font file */ - if ( !is_apple_sbit && LOAD_( header ) ) + if ( !is_apple_sbit && LOAD_( head ) ) goto Exit; /* the following tables are often not present in embedded TrueType */ /* fonts within PDF documents, so don't check for them. */ - (void)LOAD_( max_profile ); - (void)LOAD_( charmaps ); + (void)LOAD_( maxp ); + (void)LOAD_( cmap ); /* the following tables are optional in PCL fonts -- */ /* don't check for errors */ - (void)LOAD_( names ); - psnames_error = LOAD_( psnames ); + (void)LOAD_( name ); + psnames_error = LOAD_( post ); /* do not load the metrics headers and tables if this is an Apple */ /* sbit font file */ if ( !is_apple_sbit ) { /* load the `hhea' and `hmtx' tables at once */ - error = sfnt->load_metrics( face, stream, 0 ); + error = sfnt->load_hhea( face, stream, 0 ); if ( error ) goto Exit; /* try to load the `vhea' and `vmtx' tables at once */ - error = sfnt->load_metrics( face, stream, 1 ); + error = sfnt->load_hhea( face, stream, 1 ); if ( error ) goto Exit; @@ -499,7 +499,7 @@ #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS /* embedded bitmap support. */ - if ( sfnt->load_sbits && LOAD_( sbits ) ) + if ( sfnt->load_eblc && LOAD_( eblc ) ) { /* return an error if this font file has no outlines */ if ( error == SFNT_Err_Table_Missing && has_outline ) @@ -510,13 +510,12 @@ #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - if ( LOAD_( hdmx ) || - LOAD_( pclt ) ) + if ( LOAD_( pclt ) ) goto Exit; /* consider the kerning and gasp tables as optional */ (void)LOAD_( gasp ); - (void)LOAD_( kerning ); + (void)LOAD_( kern ); error = SFNT_Err_Ok; @@ -755,8 +754,8 @@ sfnt->free_psnames( face ); /* destroy the embedded bitmaps table if it is loaded */ - if ( sfnt->free_sbits ) - sfnt->free_sbits( face ); + if ( sfnt->free_eblc ) + sfnt->free_eblc( face ); } #ifdef TT_CONFIG_OPTION_BDF @@ -813,10 +812,7 @@ face->gasp.numRanges = 0; /* freeing the name table */ - sfnt->free_names( face ); - - /* freeing the hdmx table */ - sfnt->free_hdmx( face ); + sfnt->free_name( face ); /* freeing family and style name */ FT_FREE( face->root.family_name ); diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c index 2f0af79da..9877b9e1a 100644 --- a/src/sfnt/ttload.c +++ b/src/sfnt/ttload.c @@ -657,8 +657,8 @@ FT_LOCAL_DEF( FT_Error ) - tt_face_load_header( TT_Face face, - FT_Stream stream ) + tt_face_load_head( TT_Face face, + FT_Stream stream ) { return tt_face_load_generic_header( face, stream, TTAG_head ); } @@ -667,8 +667,8 @@ #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS FT_LOCAL_DEF( FT_Error ) - tt_face_load_bitmap_header( TT_Face face, - FT_Stream stream ) + tt_face_load_bhed( TT_Face face, + FT_Stream stream ) { return tt_face_load_generic_header( face, stream, TTAG_bhed ); } @@ -693,8 +693,8 @@ /* FreeType error code. 0 means success. */ /* */ FT_LOCAL_DEF( FT_Error ) - tt_face_load_max_profile( TT_Face face, - FT_Stream stream ) + tt_face_load_maxp( TT_Face face, + FT_Stream stream ) { FT_Error error; TT_MaxProfile* maxProfile = &face->max_profile; @@ -798,358 +798,6 @@ } - /*************************************************************************/ - /* */ - /* */ - /* tt_face_load_metrics */ - /* */ - /* */ - /* Loads the horizontal or vertical metrics table into a face object. */ - /* */ - /* */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* vertical :: A boolean flag. If set, load vertical metrics. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ -#ifdef FT_OPTIMIZE_MEMORY - - static FT_Error - tt_face_load_metrics( TT_Face face, - FT_Stream stream, - FT_Bool vertical ) - { - FT_Error error; - FT_ULong table_size; - FT_Byte** ptable; - FT_ULong* ptable_size; - - - FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical" - : "Horizontal", - face )); - - if ( vertical ) - { - ptable = &face->vert_metrics; - ptable_size = &face->vert_metrics_size; - - /* The table is optional, quit silently if it wasn't found. */ - /* */ - /* XXX: Some fonts have a valid vertical header with a non-null */ - /* `number_of_VMetrics' fields, but no corresponding `vmtx' */ - /* table to get the metrics from (e.g. mingliu). */ - /* */ - /* For safety, we set the field to 0! */ - /* */ - error = face->goto_table( face, TTAG_vmtx, stream, &table_size ); - if ( error ) - { - /* Set number_Of_VMetrics to 0! */ - FT_TRACE2(( " no vertical header in file.\n" )); - error = SFNT_Err_Ok; - goto Exit; - } - } - else - { - ptable = &face->horz_metrics; - ptable_size = &face->horz_metrics_size; - - error = face->goto_table( face, TTAG_hmtx, stream, &table_size ); - if ( error ) - { -#ifdef FT_CONFIG_OPTION_INCREMENTAL - /* If this is an incrementally loaded font and there are */ - /* overriding metrics, tolerate a missing `hmtx' table. */ - if ( face->root.internal->incremental_interface && - face->root.internal->incremental_interface->funcs-> - get_glyph_metrics ) - { - face->horizontal.number_Of_HMetrics = 0; - error = SFNT_Err_Ok; - goto Exit; - } -#endif - - FT_ERROR(( " no horizontal metrics in file!\n" )); - error = SFNT_Err_Hmtx_Table_Missing; - goto Exit; - } - } - - if ( FT_FRAME_EXTRACT( table_size, *ptable ) ) - goto Exit; - - *ptable_size = table_size; - - Exit: - return error; - } - -#else /* !OPTIMIZE_MEMORY */ - - static FT_Error - tt_face_load_metrics( TT_Face face, - FT_Stream stream, - FT_Bool vertical ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_ULong table_len; - FT_Long num_shorts, num_longs, num_shorts_checked; - - TT_LongMetrics * longs; - TT_ShortMetrics** shorts; - - - FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical" - : "Horizontal", - face )); - - if ( vertical ) - { - /* The table is optional, quit silently if it wasn't found. */ - /* */ - /* XXX: Some fonts have a valid vertical header with a non-null */ - /* `number_of_VMetrics' fields, but no corresponding `vmtx' */ - /* table to get the metrics from (e.g. mingliu). */ - /* */ - /* For safety, we set the field to 0! */ - /* */ - error = face->goto_table( face, TTAG_vmtx, stream, &table_len ); - if ( error ) - { - /* Set number_Of_VMetrics to 0! */ - FT_TRACE2(( " no vertical header in file.\n" )); - face->vertical.number_Of_VMetrics = 0; - error = SFNT_Err_Ok; - goto Exit; - } - - num_longs = face->vertical.number_Of_VMetrics; - longs = (TT_LongMetrics *)&face->vertical.long_metrics; - shorts = (TT_ShortMetrics**)&face->vertical.short_metrics; - } - else - { - error = face->goto_table( face, TTAG_hmtx, stream, &table_len ); - if ( error ) - { - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - /* If this is an incrementally loaded font and there are */ - /* overriding metrics, tolerate a missing `hmtx' table. */ - if ( face->root.internal->incremental_interface && - face->root.internal->incremental_interface->funcs-> - get_glyph_metrics ) - { - face->horizontal.number_Of_HMetrics = 0; - error = SFNT_Err_Ok; - goto Exit; - } -#endif - - FT_ERROR(( " no horizontal metrics in file!\n" )); - error = SFNT_Err_Hmtx_Table_Missing; - goto Exit; - } - - num_longs = face->horizontal.number_Of_HMetrics; - longs = (TT_LongMetrics *)&face->horizontal.long_metrics; - shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics; - } - - /* never trust derived values */ - - num_shorts = face->max_profile.numGlyphs - num_longs; - num_shorts_checked = ( table_len - num_longs * 4L ) / 2; - - if ( num_shorts < 0 ) - { - FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n", - vertical ? "Vertical" - : "Horizontal" )); - - /* Adobe simply ignores this problem. So we shall do the same. */ -#if 0 - error = vertical ? SFNT_Err_Invalid_Vert_Metrics - : SFNT_Err_Invalid_Horiz_Metrics; - goto Exit; -#else - num_shorts = 0; -#endif - } - - if ( FT_QNEW_ARRAY( *longs, num_longs ) || - FT_QNEW_ARRAY( *shorts, num_shorts ) ) - goto Exit; - - if ( FT_FRAME_ENTER( table_len ) ) - goto Exit; - - { - TT_LongMetrics cur = *longs; - TT_LongMetrics limit = cur + num_longs; - - - for ( ; cur < limit; cur++ ) - { - cur->advance = FT_GET_USHORT(); - cur->bearing = FT_GET_SHORT(); - } - } - - /* do we have an inconsistent number of metric values? */ - { - TT_ShortMetrics* cur = *shorts; - TT_ShortMetrics* limit = cur + - FT_MIN( num_shorts, num_shorts_checked ); - - - for ( ; cur < limit; cur++ ) - *cur = FT_GET_SHORT(); - - /* We fill up the missing left side bearings with the */ - /* last valid value. Since this will occur for buggy CJK */ - /* fonts usually only, nothing serious will happen. */ - if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 ) - { - FT_Short val = (*shorts)[num_shorts_checked - 1]; - - - limit = *shorts + num_shorts; - for ( ; cur < limit; cur++ ) - *cur = val; - } - } - - FT_FRAME_EXIT(); - - FT_TRACE2(( "loaded\n" )); - - Exit: - return error; - } - -#endif /* !FT_OPTIMIZE_METRICS */ - - - /*************************************************************************/ - /* */ - /* */ - /* tt_face_load_metrics_header */ - /* */ - /* */ - /* Loads the horizontal or vertical header in a face object. */ - /* */ - /* */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* vertical :: A boolean flag. If set, load vertical metrics. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_metrics_header( TT_Face face, - FT_Stream stream, - FT_Bool vertical ) - { - FT_Error error; - TT_HoriHeader* header; - - const FT_Frame_Field metrics_header_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_HoriHeader - - FT_FRAME_START( 36 ), - FT_FRAME_ULONG ( Version ), - FT_FRAME_SHORT ( Ascender ), - FT_FRAME_SHORT ( Descender ), - FT_FRAME_SHORT ( Line_Gap ), - FT_FRAME_USHORT( advance_Width_Max ), - FT_FRAME_SHORT ( min_Left_Side_Bearing ), - FT_FRAME_SHORT ( min_Right_Side_Bearing ), - FT_FRAME_SHORT ( xMax_Extent ), - FT_FRAME_SHORT ( caret_Slope_Rise ), - FT_FRAME_SHORT ( caret_Slope_Run ), - FT_FRAME_SHORT ( caret_Offset ), - FT_FRAME_SHORT ( Reserved[0] ), - FT_FRAME_SHORT ( Reserved[1] ), - FT_FRAME_SHORT ( Reserved[2] ), - FT_FRAME_SHORT ( Reserved[3] ), - FT_FRAME_SHORT ( metric_Data_Format ), - FT_FRAME_USHORT( number_Of_HMetrics ), - FT_FRAME_END - }; - - - FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " )); - - if ( vertical ) - { - face->vertical_info = 0; - - /* The vertical header table is optional, so return quietly if */ - /* we don't find it. */ - error = face->goto_table( face, TTAG_vhea, stream, 0 ); - if ( error ) - { - error = SFNT_Err_Ok; - goto Exit; - } - - face->vertical_info = 1; - header = (TT_HoriHeader*)&face->vertical; - } - else - { - /* The horizontal header is mandatory for most fonts; return */ - /* an error if we don't find it. */ - error = face->goto_table( face, TTAG_hhea, stream, 0 ); - if ( error ) - { - error = SFNT_Err_Horiz_Header_Missing; - - /* No `hhea' table necessary for SFNT Mac fonts. */ - if ( face->format_tag == TTAG_true ) - { - FT_TRACE2(( "missing. This is an SFNT Mac font.\n")); - error = SFNT_Err_Ok; - } - - goto Exit; - } - - header = &face->horizontal; - } - - if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) ) - goto Exit; - - header->long_metrics = NULL; - header->short_metrics = NULL; - - FT_TRACE2(( "loaded\n" )); - - /* Now try to load the corresponding metrics */ - - error = tt_face_load_metrics( face, stream, vertical ); - - Exit: - return error; - } - - /*************************************************************************/ /* */ /* */ @@ -1167,8 +815,8 @@ /* FreeType error code. 0 means success. */ /* */ FT_LOCAL_DEF( FT_Error ) - tt_face_load_names( TT_Face face, - FT_Stream stream ) + tt_face_load_name( TT_Face face, + FT_Stream stream ) { FT_Error error; FT_Memory memory = stream->memory; @@ -1306,7 +954,7 @@ /* face :: A handle to the target face object. */ /* */ FT_LOCAL_DEF( void ) - tt_face_free_names( TT_Face face ) + tt_face_free_name( TT_Face face ) { FT_Memory memory = face->root.driver->root.memory; TT_NameTable table = &face->name_table; @@ -1539,8 +1187,8 @@ /* FreeType error code. 0 means success. */ /* */ FT_LOCAL_DEF( FT_Error ) - tt_face_load_postscript( TT_Face face, - FT_Stream stream ) + tt_face_load_post( TT_Face face, + FT_Stream stream ) { FT_Error error; TT_Postscript* post = &face->postscript; @@ -1719,187 +1367,4 @@ } - /*************************************************************************/ - /* */ - /* */ - /* tt_face_load_hdmx */ - /* */ - /* */ - /* Loads the horizontal device metrics table. */ - /* */ - /* */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: A handle to the input stream. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ -#ifdef FT_OPTIMIZE_MEMORY - - FT_LOCAL_DEF( FT_Error ) - tt_face_load_hdmx( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - FT_UInt version, nn, num_records; - FT_ULong table_size, record_size; - FT_Byte* p; - FT_Byte* limit; - - - /* this table is optional */ - error = face->goto_table( face, TTAG_hdmx, stream, &table_size ); - if ( error || table_size < 8 ) - return SFNT_Err_Ok; - - if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) ) - goto Exit; - - p = face->hdmx_table; - limit = p + table_size; - - version = FT_NEXT_USHORT( p ); - num_records = FT_NEXT_USHORT( p ); - record_size = FT_NEXT_ULONG( p ); - - if ( version != 0 || num_records > 255 || record_size > 0x40000 ) - { - error = SFNT_Err_Invalid_File_Format; - goto Fail; - } - - if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) ) - goto Fail; - - for ( nn = 0; nn < num_records; nn++ ) - { - if ( p + record_size > limit ) - break; - - face->hdmx_record_sizes[nn] = p[0]; - p += record_size; - } - - face->hdmx_record_count = nn; - face->hdmx_table_size = table_size; - - Exit: - return error; - - Fail: - FT_FRAME_RELEASE( face->hdmx_table ); - face->hdmx_table_size = 0; - goto Exit; - } - - - FT_LOCAL_DEF( void ) - tt_face_free_hdmx( TT_Face face ) - { - FT_Stream stream = face->root.stream; - FT_Memory memory = stream->memory; - - - FT_FREE( face->hdmx_record_sizes ); - FT_FRAME_RELEASE( face->hdmx_table ); - } - -#else /* !FT_OPTIMIZE_MEMORY */ - - FT_LOCAL_DEF( FT_Error ) - tt_face_load_hdmx( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - TT_Hdmx hdmx = &face->hdmx; - FT_Short num_records; - FT_Long num_glyphs; - FT_Long record_size; - - - hdmx->version = 0; - hdmx->num_records = 0; - hdmx->records = 0; - - /* this table is optional */ - error = face->goto_table( face, TTAG_hdmx, stream, 0 ); - if ( error ) - return SFNT_Err_Ok; - - if ( FT_FRAME_ENTER( 8L ) ) - goto Exit; - - hdmx->version = FT_GET_USHORT(); - num_records = FT_GET_SHORT(); - record_size = FT_GET_LONG(); - - FT_FRAME_EXIT(); - - if ( record_size < 0 || num_records < 0 ) - return SFNT_Err_Invalid_File_Format; - - /* Only recognize format 0 */ - if ( hdmx->version != 0 ) - goto Exit; - - /* we can't use FT_QNEW_ARRAY here; otherwise tt_face_free_hdmx */ - /* could fail during deallocation */ - if ( FT_NEW_ARRAY( hdmx->records, num_records ) ) - goto Exit; - - hdmx->num_records = num_records; - num_glyphs = face->root.num_glyphs; - record_size -= num_glyphs + 2; - - { - TT_HdmxEntry cur = hdmx->records; - TT_HdmxEntry limit = cur + hdmx->num_records; - - - for ( ; cur < limit; cur++ ) - { - /* read record */ - if ( FT_READ_BYTE( cur->ppem ) || - FT_READ_BYTE( cur->max_width ) ) - goto Exit; - - if ( FT_QALLOC( cur->widths, num_glyphs ) || - FT_STREAM_READ( cur->widths, num_glyphs ) ) - goto Exit; - - /* skip padding bytes */ - if ( record_size > 0 && FT_STREAM_SKIP( record_size ) ) - goto Exit; - } - } - - Exit: - return error; - } - - - FT_LOCAL_DEF( void ) - tt_face_free_hdmx( TT_Face face ) - { - if ( face ) - { - FT_Int n; - FT_Memory memory = face->root.driver->root.memory; - - - for ( n = 0; n < face->hdmx.num_records; n++ ) - FT_FREE( face->hdmx.records[n].widths ); - - FT_FREE( face->hdmx.records ); - face->hdmx.num_records = 0; - } - } - -#endif /* !OPTIMIZE_MEMORY */ - - /* END */ diff --git a/src/sfnt/ttload.h b/src/sfnt/ttload.h index d1a61ca7f..68b50ea27 100644 --- a/src/sfnt/ttload.h +++ b/src/sfnt/ttload.h @@ -60,14 +60,8 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - tt_face_load_header( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - tt_face_load_metrics_header( TT_Face face, - FT_Stream stream, - FT_Bool vertical ); + tt_face_load_head( TT_Face face, + FT_Stream stream ); FT_LOCAL( FT_Error ) @@ -76,13 +70,13 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - tt_face_load_max_profile( TT_Face face, - FT_Stream stream ); + tt_face_load_maxp( TT_Face face, + FT_Stream stream ); FT_LOCAL( FT_Error ) - tt_face_load_names( TT_Face face, - FT_Stream stream ); + tt_face_load_name( TT_Face face, + FT_Stream stream ); FT_LOCAL( FT_Error ) @@ -91,24 +85,16 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - tt_face_load_postscript( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - tt_face_load_hdmx( TT_Face face, + tt_face_load_post( TT_Face face, FT_Stream stream ); + FT_LOCAL( FT_Error ) tt_face_load_pclt( TT_Face face, FT_Stream stream ); FT_LOCAL( void ) - tt_face_free_names( TT_Face face ); - - - FT_LOCAL( void ) - tt_face_free_hdmx ( TT_Face face ); + tt_face_free_name( TT_Face face ); FT_LOCAL( FT_Error ) @@ -118,8 +104,8 @@ FT_BEGIN_HEADER #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS FT_LOCAL( FT_Error ) - tt_face_load_bitmap_header( TT_Face face, - FT_Stream stream ); + tt_face_load_bhed( TT_Face face, + FT_Stream stream ); #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c new file mode 100644 index 000000000..f8354869e --- /dev/null +++ b/src/sfnt/ttmtx.c @@ -0,0 +1,1038 @@ +/***************************************************************************/ +/* */ +/* ttmtx.c */ +/* */ +/* Load the metrics tables common to TTF and OTF fonts (body). */ +/* */ +/* Copyright 2006 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_TRUETYPE_TAGS_H +#include "ttmtx.h" + +#include "sferrors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttmtx + + + /*************************************************************************/ + /* */ + /* */ + /* tt_face_load_hmtx */ + /* */ + /* */ + /* Load the `hmtx' or `vmtx' table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* vertical :: A boolean flag. If set, load `vmtx'. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ +#ifdef FT_OPTIMIZE_MEMORY + + static FT_Error + tt_face_load_hmtx( TT_Face face, + FT_Stream stream, + FT_Bool vertical ) + { + FT_Error error; + FT_ULong table_size; + FT_Byte** ptable; + FT_ULong* ptable_size; + + + FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical" + : "Horizontal", + face )); + + if ( vertical ) + { + ptable = &face->vert_metrics; + ptable_size = &face->vert_metrics_size; + + /* The table is optional, quit silently if it wasn't found. */ + /* */ + /* XXX: Some fonts have a valid vertical header with a non-null */ + /* `number_of_VMetrics' fields, but no corresponding `vmtx' */ + /* table to get the metrics from (e.g. mingliu). */ + /* */ + /* For safety, we set the field to 0! */ + /* */ + error = face->goto_table( face, TTAG_vmtx, stream, &table_size ); + if ( error ) + { + /* Set number_Of_VMetrics to 0! */ + FT_TRACE2(( " no vertical header in file.\n" )); + error = SFNT_Err_Ok; + goto Exit; + } + } + else + { + ptable = &face->horz_metrics; + ptable_size = &face->horz_metrics_size; + + error = face->goto_table( face, TTAG_hmtx, stream, &table_size ); + if ( error ) + { +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* If this is an incrementally loaded font and there are */ + /* overriding metrics, tolerate a missing `hmtx' table. */ + if ( face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs-> + get_glyph_metrics ) + { + face->horizontal.number_Of_HMetrics = 0; + error = SFNT_Err_Ok; + goto Exit; + } +#endif + + FT_ERROR(( " no horizontal metrics in file!\n" )); + error = SFNT_Err_Hmtx_Table_Missing; + goto Exit; + } + } + + if ( FT_FRAME_EXTRACT( table_size, *ptable ) ) + goto Exit; + + *ptable_size = table_size; + + Exit: + return error; + } + +#else /* !OPTIMIZE_MEMORY */ + + static FT_Error + tt_face_load_hmtx( TT_Face face, + FT_Stream stream, + FT_Bool vertical ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + FT_ULong table_len; + FT_Long num_shorts, num_longs, num_shorts_checked; + + TT_LongMetrics * longs; + TT_ShortMetrics** shorts; + + + FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical" + : "Horizontal", + face )); + + if ( vertical ) + { + /* The table is optional, quit silently if it wasn't found. */ + /* */ + /* XXX: Some fonts have a valid vertical header with a non-null */ + /* `number_of_VMetrics' fields, but no corresponding `vmtx' */ + /* table to get the metrics from (e.g. mingliu). */ + /* */ + /* For safety, we set the field to 0! */ + /* */ + error = face->goto_table( face, TTAG_vmtx, stream, &table_len ); + if ( error ) + { + /* Set number_Of_VMetrics to 0! */ + FT_TRACE2(( " no vertical header in file.\n" )); + face->vertical.number_Of_VMetrics = 0; + error = SFNT_Err_Ok; + goto Exit; + } + + num_longs = face->vertical.number_Of_VMetrics; + longs = (TT_LongMetrics *)&face->vertical.long_metrics; + shorts = (TT_ShortMetrics**)&face->vertical.short_metrics; + } + else + { + error = face->goto_table( face, TTAG_hmtx, stream, &table_len ); + if ( error ) + { + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* If this is an incrementally loaded font and there are */ + /* overriding metrics, tolerate a missing `hmtx' table. */ + if ( face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs-> + get_glyph_metrics ) + { + face->horizontal.number_Of_HMetrics = 0; + error = SFNT_Err_Ok; + goto Exit; + } +#endif + + FT_ERROR(( " no horizontal metrics in file!\n" )); + error = SFNT_Err_Hmtx_Table_Missing; + goto Exit; + } + + num_longs = face->horizontal.number_Of_HMetrics; + longs = (TT_LongMetrics *)&face->horizontal.long_metrics; + shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics; + } + + /* never trust derived values */ + + num_shorts = face->max_profile.numGlyphs - num_longs; + num_shorts_checked = ( table_len - num_longs * 4L ) / 2; + + if ( num_shorts < 0 ) + { + FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n", + vertical ? "Vertical" + : "Horizontal" )); + + /* Adobe simply ignores this problem. So we shall do the same. */ +#if 0 + error = vertical ? SFNT_Err_Invalid_Vert_Metrics + : SFNT_Err_Invalid_Horiz_Metrics; + goto Exit; +#else + num_shorts = 0; +#endif + } + + if ( FT_QNEW_ARRAY( *longs, num_longs ) || + FT_QNEW_ARRAY( *shorts, num_shorts ) ) + goto Exit; + + if ( FT_FRAME_ENTER( table_len ) ) + goto Exit; + + { + TT_LongMetrics cur = *longs; + TT_LongMetrics limit = cur + num_longs; + + + for ( ; cur < limit; cur++ ) + { + cur->advance = FT_GET_USHORT(); + cur->bearing = FT_GET_SHORT(); + } + } + + /* do we have an inconsistent number of metric values? */ + { + TT_ShortMetrics* cur = *shorts; + TT_ShortMetrics* limit = cur + + FT_MIN( num_shorts, num_shorts_checked ); + + + for ( ; cur < limit; cur++ ) + *cur = FT_GET_SHORT(); + + /* We fill up the missing left side bearings with the */ + /* last valid value. Since this will occur for buggy CJK */ + /* fonts usually only, nothing serious will happen. */ + if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 ) + { + FT_Short val = (*shorts)[num_shorts_checked - 1]; + + + limit = *shorts + num_shorts; + for ( ; cur < limit; cur++ ) + *cur = val; + } + } + + FT_FRAME_EXIT(); + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + +#endif /* !FT_OPTIMIZE_METRICS */ + + + /*************************************************************************/ + /* */ + /* */ + /* tt_face_load_hhea */ + /* */ + /* */ + /* Load the `hhea' or 'vhea' table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* vertical :: A boolean flag. If set, load `vhea'. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_hhea( TT_Face face, + FT_Stream stream, + FT_Bool vertical ) + { + FT_Error error; + TT_HoriHeader* header; + + const FT_Frame_Field metrics_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_HoriHeader + + FT_FRAME_START( 36 ), + FT_FRAME_ULONG ( Version ), + FT_FRAME_SHORT ( Ascender ), + FT_FRAME_SHORT ( Descender ), + FT_FRAME_SHORT ( Line_Gap ), + FT_FRAME_USHORT( advance_Width_Max ), + FT_FRAME_SHORT ( min_Left_Side_Bearing ), + FT_FRAME_SHORT ( min_Right_Side_Bearing ), + FT_FRAME_SHORT ( xMax_Extent ), + FT_FRAME_SHORT ( caret_Slope_Rise ), + FT_FRAME_SHORT ( caret_Slope_Run ), + FT_FRAME_SHORT ( caret_Offset ), + FT_FRAME_SHORT ( Reserved[0] ), + FT_FRAME_SHORT ( Reserved[1] ), + FT_FRAME_SHORT ( Reserved[2] ), + FT_FRAME_SHORT ( Reserved[3] ), + FT_FRAME_SHORT ( metric_Data_Format ), + FT_FRAME_USHORT( number_Of_HMetrics ), + FT_FRAME_END + }; + + + FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " )); + + if ( vertical ) + { + face->vertical_info = 0; + + /* The vertical header table is optional, so return quietly if */ + /* we don't find it. */ + error = face->goto_table( face, TTAG_vhea, stream, 0 ); + if ( error ) + { + error = SFNT_Err_Ok; + goto Exit; + } + + face->vertical_info = 1; + header = (TT_HoriHeader*)&face->vertical; + } + else + { + /* The horizontal header is mandatory for most fonts; return */ + /* an error if we don't find it. */ + error = face->goto_table( face, TTAG_hhea, stream, 0 ); + if ( error ) + { + error = SFNT_Err_Horiz_Header_Missing; + + /* No `hhea' table necessary for SFNT Mac fonts. */ + if ( face->format_tag == TTAG_true ) + { + FT_TRACE2(( "missing. This is an SFNT Mac font.\n")); + error = SFNT_Err_Ok; + } + + goto Exit; + } + + header = &face->horizontal; + } + + if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) ) + goto Exit; + + header->long_metrics = NULL; + header->short_metrics = NULL; + + FT_TRACE2(( "loaded\n" )); + + /* Now try to load the corresponding metrics */ + + error = tt_face_load_hmtx( face, stream, vertical ); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* tt_face_get_metrics */ + /* */ + /* */ + /* Returns the horizontal or vertical metrics in font units for a */ + /* given glyph. The metrics are the left side bearing (resp. top */ + /* side bearing) and advance width (resp. advance height). */ + /* */ + /* */ + /* header :: A pointer to either the horizontal or vertical metrics */ + /* structure. */ + /* */ + /* idx :: The glyph index. */ + /* */ + /* */ + /* bearing :: The bearing, either left side or top side. */ + /* */ + /* advance :: The advance width resp. advance height. */ + /* */ + /* */ + /* This function will much probably move to another component in the */ + /* near future, but I haven't decided which yet. */ + /* */ +#ifdef FT_OPTIMIZE_MEMORY + + FT_LOCAL_DEF( FT_Error ) + tt_face_get_metrics( TT_Face face, + FT_Bool vertical, + FT_UInt gindex, + FT_Short *abearing, + FT_UShort *aadvance ) + { + TT_HoriHeader* header; + FT_Byte* p; + FT_Byte* limit; + FT_UShort k; + + + if ( vertical ) + { + header = (TT_HoriHeader*)&face->vertical; + p = face->vert_metrics; + limit = p + face->vert_metrics_size; + } + else + { + header = &face->horizontal; + p = face->horz_metrics; + limit = p + face->horz_metrics_size; + } + + k = header->number_Of_HMetrics; + + if ( k > 0 ) + { + if ( gindex < (FT_UInt)k ) + { + p += 4 * gindex; + if ( p + 4 > limit ) + goto NoData; + + *aadvance = FT_NEXT_USHORT( p ); + *abearing = FT_NEXT_SHORT( p ); + } + else + { + p += 4 * ( k - 1 ); + if ( p + 4 > limit ) + goto NoData; + + *aadvance = FT_NEXT_USHORT( p ); + p += 2 + 2 * ( gindex - k ); + if ( p + 2 > limit ) + *abearing = 0; + else + *abearing = FT_PEEK_SHORT( p ); + } + } + else + { + NoData: + *abearing = 0; + *aadvance = 0; + } + + return SFNT_Err_Ok; + } + +#else /* !FT_OPTIMIZE_MEMORY */ + + FT_LOCAL_DEF( FT_Error ) + tt_face_get_metrics( TT_Face face, + FT_Bool vertical, + FT_UInt gindex, + FT_Short* abearing, + FT_UShort* aadvance ) + { + TT_HoriHeader* header = vertical ? (TT_HoriHeader*)&face->vertical + : &face->horizontal; + TT_LongMetrics longs_m; + FT_UShort k = header->number_Of_HMetrics; + + + if ( k == 0 ) + { + *abearing = *aadvance = 0; + return SFNT_Err_Ok; + } + + if ( gindex < (FT_UInt)k ) + { + longs_m = (TT_LongMetrics)header->long_metrics + gindex; + *abearing = longs_m->bearing; + *aadvance = longs_m->advance; + } + else + { + *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k]; + *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance; + } + + return SFNT_Err_Ok; + } + +#endif /* !FT_OPTIMIZE_MEMORY */ + + +/* END */ +/***************************************************************************/ +/* */ +/* ttmtx.c */ +/* */ +/* Load the metrics tables common to TTF and OTF fonts (body). */ +/* */ +/* Copyright 2006 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_TRUETYPE_TAGS_H +#include "ttmtx.h" + +#include "sferrors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttmtx + + + /*************************************************************************/ + /* */ + /* */ + /* tt_face_load_hmtx */ + /* */ + /* */ + /* Load the `hmtx' or `vmtx' table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* vertical :: A boolean flag. If set, load `vmtx'. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ +#ifdef FT_OPTIMIZE_MEMORY + + static FT_Error + tt_face_load_hmtx( TT_Face face, + FT_Stream stream, + FT_Bool vertical ) + { + FT_Error error; + FT_ULong table_size; + FT_Byte** ptable; + FT_ULong* ptable_size; + + + FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical" + : "Horizontal", + face )); + + if ( vertical ) + { + ptable = &face->vert_metrics; + ptable_size = &face->vert_metrics_size; + + /* The table is optional, quit silently if it wasn't found. */ + /* */ + /* XXX: Some fonts have a valid vertical header with a non-null */ + /* `number_of_VMetrics' fields, but no corresponding `vmtx' */ + /* table to get the metrics from (e.g. mingliu). */ + /* */ + /* For safety, we set the field to 0! */ + /* */ + error = face->goto_table( face, TTAG_vmtx, stream, &table_size ); + if ( error ) + { + /* Set number_Of_VMetrics to 0! */ + FT_TRACE2(( " no vertical header in file.\n" )); + error = SFNT_Err_Ok; + goto Exit; + } + } + else + { + ptable = &face->horz_metrics; + ptable_size = &face->horz_metrics_size; + + error = face->goto_table( face, TTAG_hmtx, stream, &table_size ); + if ( error ) + { +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* If this is an incrementally loaded font and there are */ + /* overriding metrics, tolerate a missing `hmtx' table. */ + if ( face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs-> + get_glyph_metrics ) + { + face->horizontal.number_Of_HMetrics = 0; + error = SFNT_Err_Ok; + goto Exit; + } +#endif + + FT_ERROR(( " no horizontal metrics in file!\n" )); + error = SFNT_Err_Hmtx_Table_Missing; + goto Exit; + } + } + + if ( FT_FRAME_EXTRACT( table_size, *ptable ) ) + goto Exit; + + *ptable_size = table_size; + + Exit: + return error; + } + +#else /* !OPTIMIZE_MEMORY */ + + static FT_Error + tt_face_load_hmtx( TT_Face face, + FT_Stream stream, + FT_Bool vertical ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + FT_ULong table_len; + FT_Long num_shorts, num_longs, num_shorts_checked; + + TT_LongMetrics * longs; + TT_ShortMetrics** shorts; + + + FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical" + : "Horizontal", + face )); + + if ( vertical ) + { + /* The table is optional, quit silently if it wasn't found. */ + /* */ + /* XXX: Some fonts have a valid vertical header with a non-null */ + /* `number_of_VMetrics' fields, but no corresponding `vmtx' */ + /* table to get the metrics from (e.g. mingliu). */ + /* */ + /* For safety, we set the field to 0! */ + /* */ + error = face->goto_table( face, TTAG_vmtx, stream, &table_len ); + if ( error ) + { + /* Set number_Of_VMetrics to 0! */ + FT_TRACE2(( " no vertical header in file.\n" )); + face->vertical.number_Of_VMetrics = 0; + error = SFNT_Err_Ok; + goto Exit; + } + + num_longs = face->vertical.number_Of_VMetrics; + longs = (TT_LongMetrics *)&face->vertical.long_metrics; + shorts = (TT_ShortMetrics**)&face->vertical.short_metrics; + } + else + { + error = face->goto_table( face, TTAG_hmtx, stream, &table_len ); + if ( error ) + { + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* If this is an incrementally loaded font and there are */ + /* overriding metrics, tolerate a missing `hmtx' table. */ + if ( face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs-> + get_glyph_metrics ) + { + face->horizontal.number_Of_HMetrics = 0; + error = SFNT_Err_Ok; + goto Exit; + } +#endif + + FT_ERROR(( " no horizontal metrics in file!\n" )); + error = SFNT_Err_Hmtx_Table_Missing; + goto Exit; + } + + num_longs = face->horizontal.number_Of_HMetrics; + longs = (TT_LongMetrics *)&face->horizontal.long_metrics; + shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics; + } + + /* never trust derived values */ + + num_shorts = face->max_profile.numGlyphs - num_longs; + num_shorts_checked = ( table_len - num_longs * 4L ) / 2; + + if ( num_shorts < 0 ) + { + FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n", + vertical ? "Vertical" + : "Horizontal" )); + + /* Adobe simply ignores this problem. So we shall do the same. */ +#if 0 + error = vertical ? SFNT_Err_Invalid_Vert_Metrics + : SFNT_Err_Invalid_Horiz_Metrics; + goto Exit; +#else + num_shorts = 0; +#endif + } + + if ( FT_QNEW_ARRAY( *longs, num_longs ) || + FT_QNEW_ARRAY( *shorts, num_shorts ) ) + goto Exit; + + if ( FT_FRAME_ENTER( table_len ) ) + goto Exit; + + { + TT_LongMetrics cur = *longs; + TT_LongMetrics limit = cur + num_longs; + + + for ( ; cur < limit; cur++ ) + { + cur->advance = FT_GET_USHORT(); + cur->bearing = FT_GET_SHORT(); + } + } + + /* do we have an inconsistent number of metric values? */ + { + TT_ShortMetrics* cur = *shorts; + TT_ShortMetrics* limit = cur + + FT_MIN( num_shorts, num_shorts_checked ); + + + for ( ; cur < limit; cur++ ) + *cur = FT_GET_SHORT(); + + /* We fill up the missing left side bearings with the */ + /* last valid value. Since this will occur for buggy CJK */ + /* fonts usually only, nothing serious will happen. */ + if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 ) + { + FT_Short val = (*shorts)[num_shorts_checked - 1]; + + + limit = *shorts + num_shorts; + for ( ; cur < limit; cur++ ) + *cur = val; + } + } + + FT_FRAME_EXIT(); + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + +#endif /* !FT_OPTIMIZE_METRICS */ + + + /*************************************************************************/ + /* */ + /* */ + /* tt_face_load_hhea */ + /* */ + /* */ + /* Load the `hhea' or 'vhea' table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* vertical :: A boolean flag. If set, load `vhea'. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_hhea( TT_Face face, + FT_Stream stream, + FT_Bool vertical ) + { + FT_Error error; + TT_HoriHeader* header; + + const FT_Frame_Field metrics_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_HoriHeader + + FT_FRAME_START( 36 ), + FT_FRAME_ULONG ( Version ), + FT_FRAME_SHORT ( Ascender ), + FT_FRAME_SHORT ( Descender ), + FT_FRAME_SHORT ( Line_Gap ), + FT_FRAME_USHORT( advance_Width_Max ), + FT_FRAME_SHORT ( min_Left_Side_Bearing ), + FT_FRAME_SHORT ( min_Right_Side_Bearing ), + FT_FRAME_SHORT ( xMax_Extent ), + FT_FRAME_SHORT ( caret_Slope_Rise ), + FT_FRAME_SHORT ( caret_Slope_Run ), + FT_FRAME_SHORT ( caret_Offset ), + FT_FRAME_SHORT ( Reserved[0] ), + FT_FRAME_SHORT ( Reserved[1] ), + FT_FRAME_SHORT ( Reserved[2] ), + FT_FRAME_SHORT ( Reserved[3] ), + FT_FRAME_SHORT ( metric_Data_Format ), + FT_FRAME_USHORT( number_Of_HMetrics ), + FT_FRAME_END + }; + + + FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " )); + + if ( vertical ) + { + face->vertical_info = 0; + + /* The vertical header table is optional, so return quietly if */ + /* we don't find it. */ + error = face->goto_table( face, TTAG_vhea, stream, 0 ); + if ( error ) + { + error = SFNT_Err_Ok; + goto Exit; + } + + face->vertical_info = 1; + header = (TT_HoriHeader*)&face->vertical; + } + else + { + /* The horizontal header is mandatory for most fonts; return */ + /* an error if we don't find it. */ + error = face->goto_table( face, TTAG_hhea, stream, 0 ); + if ( error ) + { + error = SFNT_Err_Horiz_Header_Missing; + + /* No `hhea' table necessary for SFNT Mac fonts. */ + if ( face->format_tag == TTAG_true ) + { + FT_TRACE2(( "missing. This is an SFNT Mac font.\n")); + error = SFNT_Err_Ok; + } + + goto Exit; + } + + header = &face->horizontal; + } + + if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) ) + goto Exit; + + header->long_metrics = NULL; + header->short_metrics = NULL; + + FT_TRACE2(( "loaded\n" )); + + /* Now try to load the corresponding metrics */ + + error = tt_face_load_hmtx( face, stream, vertical ); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* tt_face_get_metrics */ + /* */ + /* */ + /* Returns the horizontal or vertical metrics in font units for a */ + /* given glyph. The metrics are the left side bearing (resp. top */ + /* side bearing) and advance width (resp. advance height). */ + /* */ + /* */ + /* header :: A pointer to either the horizontal or vertical metrics */ + /* structure. */ + /* */ + /* idx :: The glyph index. */ + /* */ + /* */ + /* bearing :: The bearing, either left side or top side. */ + /* */ + /* advance :: The advance width resp. advance height. */ + /* */ + /* */ + /* This function will much probably move to another component in the */ + /* near future, but I haven't decided which yet. */ + /* */ +#ifdef FT_OPTIMIZE_MEMORY + + FT_LOCAL_DEF( FT_Error ) + tt_face_get_metrics( TT_Face face, + FT_Bool vertical, + FT_UInt gindex, + FT_Short *abearing, + FT_UShort *aadvance ) + { + TT_HoriHeader* header; + FT_Byte* p; + FT_Byte* limit; + FT_UShort k; + + + if ( vertical ) + { + header = (TT_HoriHeader*)&face->vertical; + p = face->vert_metrics; + limit = p + face->vert_metrics_size; + } + else + { + header = &face->horizontal; + p = face->horz_metrics; + limit = p + face->horz_metrics_size; + } + + k = header->number_Of_HMetrics; + + if ( k > 0 ) + { + if ( gindex < (FT_UInt)k ) + { + p += 4 * gindex; + if ( p + 4 > limit ) + goto NoData; + + *aadvance = FT_NEXT_USHORT( p ); + *abearing = FT_NEXT_SHORT( p ); + } + else + { + p += 4 * ( k - 1 ); + if ( p + 4 > limit ) + goto NoData; + + *aadvance = FT_NEXT_USHORT( p ); + p += 2 + 2 * ( gindex - k ); + if ( p + 2 > limit ) + *abearing = 0; + else + *abearing = FT_PEEK_SHORT( p ); + } + } + else + { + NoData: + *abearing = 0; + *aadvance = 0; + } + + return SFNT_Err_Ok; + } + +#else /* !FT_OPTIMIZE_MEMORY */ + + FT_LOCAL_DEF( FT_Error ) + tt_face_get_metrics( TT_Face face, + FT_Bool vertical, + FT_UInt gindex, + FT_Short* abearing, + FT_UShort* aadvance ) + { + TT_HoriHeader* header = vertical ? (TT_HoriHeader*)&face->vertical + : &face->horizontal; + TT_LongMetrics longs_m; + FT_UShort k = header->number_Of_HMetrics; + + + if ( k == 0 ) + { + *abearing = *aadvance = 0; + return SFNT_Err_Ok; + } + + if ( gindex < (FT_UInt)k ) + { + longs_m = (TT_LongMetrics)header->long_metrics + gindex; + *abearing = longs_m->bearing; + *aadvance = longs_m->advance; + } + else + { + *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k]; + *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance; + } + + return SFNT_Err_Ok; + } + +#endif /* !FT_OPTIMIZE_MEMORY */ + + +/* END */ diff --git a/src/sfnt/ttmtx.h b/src/sfnt/ttmtx.h new file mode 100644 index 000000000..cee5af7a5 --- /dev/null +++ b/src/sfnt/ttmtx.h @@ -0,0 +1,98 @@ +/***************************************************************************/ +/* */ +/* ttmtx.h */ +/* */ +/* Load the metrics tables common to TTF and OTF fonts (specification). */ +/* */ +/* Copyright 2006 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTMTX_H__ +#define __TTMTX_H__ + + +#include +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_TRUETYPE_TYPES_H + + +FT_BEGIN_HEADER + + + FT_LOCAL( FT_Error ) + tt_face_load_hhea( TT_Face face, + FT_Stream stream, + FT_Bool vertical ); + + + FT_LOCAL( FT_Error ) + tt_face_get_metrics( TT_Face face, + FT_Bool vertical, + FT_UInt gindex, + FT_Short* abearing, + FT_UShort* aadvance ); + +FT_END_HEADER + +#endif /* __TTMTX_H__ */ + + +/* END */ +/***************************************************************************/ +/* */ +/* ttmtx.h */ +/* */ +/* Load the metrics tables common to TTF and OTF fonts (specification). */ +/* */ +/* Copyright 2006 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTMTX_H__ +#define __TTMTX_H__ + + +#include +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_TRUETYPE_TYPES_H + + +FT_BEGIN_HEADER + + + FT_LOCAL( FT_Error ) + tt_face_load_hhea( TT_Face face, + FT_Stream stream, + FT_Bool vertical ); + + + FT_LOCAL( FT_Error ) + tt_face_get_metrics( TT_Face face, + FT_Bool vertical, + FT_UInt gindex, + FT_Short* abearing, + FT_UShort* aadvance ); + +FT_END_HEADER + +#endif /* __TTMTX_H__ */ + + +/* END */ diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c index 56b5f45a5..407c1bdba 100644 --- a/src/sfnt/ttsbit.c +++ b/src/sfnt/ttsbit.c @@ -406,8 +406,8 @@ /* FreeType error code. 0 means success. */ /* */ FT_LOCAL_DEF( FT_Error ) - tt_face_load_sbit_strikes( TT_Face face, - FT_Stream stream ) + tt_face_load_eblc( TT_Face face, + FT_Stream stream ) { FT_Error error = 0; FT_Memory memory = stream->memory; @@ -635,7 +635,7 @@ /* face :: The target face object. */ /* */ FT_LOCAL_DEF( void ) - tt_face_free_sbit_strikes( TT_Face face ) + tt_face_free_eblc( TT_Face face ) { FT_Memory memory = face->root.memory; TT_SBit_Strike strike = face->sbit_strikes; diff --git a/src/sfnt/ttsbit.h b/src/sfnt/ttsbit.h index cfb5fb5f7..1e8f3d501 100644 --- a/src/sfnt/ttsbit.h +++ b/src/sfnt/ttsbit.h @@ -28,11 +28,11 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - tt_face_load_sbit_strikes( TT_Face face, - FT_Stream stream ); + tt_face_load_eblc( TT_Face face, + FT_Stream stream ); FT_LOCAL( void ) - tt_face_free_sbit_strikes( TT_Face face ); + tt_face_free_eblc( TT_Face face ); FT_LOCAL( FT_Error ) diff --git a/src/sfnt/ttsbit0.c b/src/sfnt/ttsbit0.c index 0a8d98b3d..12d5d7a89 100644 --- a/src/sfnt/ttsbit0.c +++ b/src/sfnt/ttsbit0.c @@ -86,8 +86,8 @@ FT_LOCAL_DEF( FT_Error ) - tt_face_load_sbit_strikes( TT_Face face, - FT_Stream stream ) + tt_face_load_eblc( TT_Face face, + FT_Stream stream ) { FT_Error error = SFNT_Err_Ok; FT_Fixed version; @@ -197,7 +197,7 @@ FT_LOCAL_DEF( void ) - tt_face_free_sbit_strikes( TT_Face face ) + tt_face_free_eblc( TT_Face face ) { FT_Stream stream = face->root.stream; diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c index feca62495..deca965da 100644 --- a/src/truetype/ttgload.c +++ b/src/truetype/ttgload.c @@ -63,131 +63,6 @@ #define UNSCALED_COMPONENT_OFFSET 0x1000 - /*************************************************************************/ - /* */ - /* */ - /* tt_face_get_metrics */ - /* */ - /* */ - /* Returns the horizontal or vertical metrics in font units for a */ - /* given glyph. The metrics are the left side bearing (resp. top */ - /* side bearing) and advance width (resp. advance height). */ - /* */ - /* */ - /* header :: A pointer to either the horizontal or vertical metrics */ - /* structure. */ - /* */ - /* idx :: The glyph index. */ - /* */ - /* */ - /* bearing :: The bearing, either left side or top side. */ - /* */ - /* advance :: The advance width resp. advance height. */ - /* */ - /* */ - /* This function will much probably move to another component in the */ - /* near future, but I haven't decided which yet. */ - /* */ -#ifdef FT_OPTIMIZE_MEMORY - - static void - tt_face_get_metrics( TT_Face face, - FT_Bool vertical, - FT_UInt idx, - FT_Short *abearing, - FT_UShort *aadvance ) - { - TT_HoriHeader* header; - FT_Byte* p; - FT_Byte* limit; - FT_UShort k; - - - if ( vertical ) - { - header = (TT_HoriHeader*)&face->vertical; - p = face->vert_metrics; - limit = p + face->vert_metrics_size; - } - else - { - header = &face->horizontal; - p = face->horz_metrics; - limit = p + face->horz_metrics_size; - } - - k = header->number_Of_HMetrics; - - if ( k > 0 ) - { - if ( idx < (FT_UInt)k ) - { - p += 4 * idx; - if ( p + 4 > limit ) - goto NoData; - - *aadvance = FT_NEXT_USHORT( p ); - *abearing = FT_NEXT_SHORT( p ); - } - else - { - p += 4 * ( k - 1 ); - if ( p + 4 > limit ) - goto NoData; - - *aadvance = FT_NEXT_USHORT( p ); - p += 2 + 2 * ( idx - k ); - if ( p + 2 > limit ) - *abearing = 0; - else - *abearing = FT_PEEK_SHORT( p ); - } - } - else - { - NoData: - *abearing = 0; - *aadvance = 0; - } - } - -#else /* !FT_OPTIMIZE_MEMORY */ - - static void - tt_face_get_metrics( TT_Face face, - FT_Bool vertical, - FT_UInt idx, - FT_Short *abearing, - FT_UShort *aadvance ) - { - TT_HoriHeader* header = vertical ? (TT_HoriHeader*)&face->vertical - : &face->horizontal; - TT_LongMetrics longs_m; - FT_UShort k = header->number_Of_HMetrics; - - - if ( k == 0 ) - { - *abearing = *aadvance = 0; - return; - } - - if ( idx < (FT_UInt)k ) - { - longs_m = (TT_LongMetrics)header->long_metrics + idx; - *abearing = longs_m->bearing; - *aadvance = longs_m->advance; - } - else - { - *abearing = ((TT_ShortMetrics*)header->short_metrics)[idx - k]; - *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance; - } - } - -#endif /* !FT_OPTIMIZE_MEMORY */ - - /*************************************************************************/ /* */ /* Returns the horizontal metrics in font units for a given glyph. If */ @@ -201,57 +76,13 @@ FT_Short* lsb, FT_UShort* aw ) { - tt_face_get_metrics( face, 0, idx, lsb, aw ); + ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw ); if ( check && face->postscript.isFixedPitch ) *aw = face->horizontal.advance_Width_Max; } - /*************************************************************************/ - /* */ - /* Returns the advance width table for a given pixel size if it is found */ - /* in the font's `hdmx' table (if any). */ - /* */ - static FT_Byte* - Get_Advance_WidthPtr( TT_Face face, - FT_Int ppem, - FT_UInt gindex ) - { -#ifdef FT_OPTIMIZE_MEMORY - - FT_UInt nn; - FT_Byte* result = NULL; - FT_ULong record_size = face->hdmx_record_size; - FT_Byte* record = face->hdmx_table + 8; - - - for ( nn = 0; nn < face->hdmx_record_count; nn++ ) - if ( face->hdmx_record_sizes[nn] == ppem ) - { - gindex += 2; - if ( gindex < record_size ) - result = record + gindex; - break; - } - - return result; - -#else - - FT_UShort n; - - - for ( n = 0; n < face->hdmx.num_records; n++ ) - if ( face->hdmx.records[n].ppem == ppem ) - return &face->hdmx.records[n].widths[gindex]; - - return NULL; - -#endif - } - - /*************************************************************************/ /* */ /* Returns the vertical metrics in font units for a given glyph. */ @@ -275,7 +106,7 @@ FT_UNUSED( check ); if ( face->vertical_info ) - tt_face_get_metrics( face, 1, idx, tsb, ah ); + ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah ); #if 1 /* Emperically determined, at variance with what MS said */ @@ -1769,11 +1600,13 @@ if ( !face->postscript.isFixedPitch && IS_HINTED( loader->load_flags ) ) { - FT_Byte* widthp = Get_Advance_WidthPtr( face, - size->root.metrics.x_ppem, - glyph_index ); + FT_Byte* widthp; + widthp = tt_face_get_device_metrics( face, + size->root.metrics.x_ppem, + glyph_index ); + if ( widthp ) glyph->metrics.horiAdvance = *widthp << 6; } diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c index d94d56e36..89ef75d91 100644 --- a/src/truetype/ttobjs.c +++ b/src/truetype/ttobjs.c @@ -216,6 +216,10 @@ if ( error ) goto Exit; + error = tt_face_load_hdmx( face, stream ); + if ( error ) + goto Exit; + if ( face->root.face_flags & FT_FACE_FLAG_SCALABLE ) { @@ -224,18 +228,17 @@ if ( !face->root.internal->incremental_interface ) error = tt_face_load_loca( face, stream ); if ( !error ) - { - error = tt_face_load_cvt( face, stream ); - if ( !error ) - error = tt_face_load_fpgm( face, stream ); - } + error = tt_face_load_cvt( face, stream ) || + tt_face_load_fpgm( face, stream ) || + tt_face_load_prep( face, stream ); #else if ( !error ) error = tt_face_load_loca( face, stream ) || tt_face_load_cvt( face, stream ) || - tt_face_load_fpgm( face, stream ); + tt_face_load_fpgm( face, stream ) || + tt_face_load_prep( face, stream ); #endif @@ -301,6 +304,8 @@ /* freeing the locations table */ tt_face_done_loca( face ); + tt_face_free_hdmx( face ); + /* freeing the CVT */ FT_FREE( face->cvt ); face->cvt_size = 0; diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c index 72b25f394..a7b393cdc 100644 --- a/src/truetype/ttpload.c +++ b/src/truetype/ttpload.c @@ -2,7 +2,7 @@ /* */ /* ttpload.c */ /* */ -/* TrueType glyph data/program tables loader (body). */ +/* TrueType-specific tables loader (body). */ /* */ /* Copyright 1996-2001, 2002, 2004, 2005, 2006 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ @@ -400,7 +400,7 @@ /* tt_face_load_fpgm */ /* */ /* */ - /* Loads the font program and the cvt program. */ + /* Loads the font program. */ /* */ /* */ /* face :: A handle to the target face object. */ @@ -429,6 +429,7 @@ { face->font_program = NULL; face->font_program_size = 0; + error = TT_Err_Ok; FT_TRACE2(( "is missing!\n" )); } @@ -441,6 +442,47 @@ FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size )); } + Exit: + return error; + +#else /* !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + FT_UNUSED( face ); + FT_UNUSED( stream ); + + return TT_Err_Ok; + +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* tt_face_load_prep */ + /* */ + /* */ + /* Loads the cvt program. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_prep( TT_Face face, + FT_Stream stream ) + { +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + FT_Error error; + FT_ULong table_len; + + FT_TRACE2(( "Prep program " )); error = face->goto_table( face, TTAG_prep, stream, &table_len ); @@ -475,4 +517,230 @@ } + /*************************************************************************/ + /* */ + /* */ + /* tt_face_load_hdmx */ + /* */ + /* */ + /* Loads the `hdmx' table into the face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ +#ifdef FT_OPTIMIZE_MEMORY + + FT_LOCAL_DEF( FT_Error ) + tt_face_load_hdmx( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_UInt version, nn, num_records; + FT_ULong table_size, record_size; + FT_Byte* p; + FT_Byte* limit; + + + /* this table is optional */ + error = face->goto_table( face, TTAG_hdmx, stream, &table_size ); + if ( error || table_size < 8 ) + return TT_Err_Ok; + + if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) ) + goto Exit; + + p = face->hdmx_table; + limit = p + table_size; + + version = FT_NEXT_USHORT( p ); + num_records = FT_NEXT_USHORT( p ); + record_size = FT_NEXT_ULONG( p ); + + if ( version != 0 || num_records > 255 || record_size > 0x40000 ) + { + error = TT_Err_Invalid_File_Format; + goto Fail; + } + + if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) ) + goto Fail; + + for ( nn = 0; nn < num_records; nn++ ) + { + if ( p + record_size > limit ) + break; + + face->hdmx_record_sizes[nn] = p[0]; + p += record_size; + } + + face->hdmx_record_count = nn; + face->hdmx_table_size = table_size; + + Exit: + return error; + + Fail: + FT_FRAME_RELEASE( face->hdmx_table ); + face->hdmx_table_size = 0; + goto Exit; + } + + + FT_LOCAL_DEF( void ) + tt_face_free_hdmx( TT_Face face ) + { + FT_Stream stream = face->root.stream; + FT_Memory memory = stream->memory; + + + FT_FREE( face->hdmx_record_sizes ); + FT_FRAME_RELEASE( face->hdmx_table ); + } + +#else /* !FT_OPTIMIZE_MEMORY */ + + FT_LOCAL_DEF( FT_Error ) + tt_face_load_hdmx( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + TT_Hdmx hdmx = &face->hdmx; + FT_Short num_records; + FT_Long num_glyphs; + FT_Long record_size; + + + hdmx->version = 0; + hdmx->num_records = 0; + hdmx->records = 0; + + /* this table is optional */ + error = face->goto_table( face, TTAG_hdmx, stream, 0 ); + if ( error ) + return TT_Err_Ok; + + if ( FT_FRAME_ENTER( 8L ) ) + goto Exit; + + hdmx->version = FT_GET_USHORT(); + num_records = FT_GET_SHORT(); + record_size = FT_GET_LONG(); + + FT_FRAME_EXIT(); + + if ( record_size < 0 || num_records < 0 ) + return TT_Err_Invalid_File_Format; + + /* Only recognize format 0 */ + if ( hdmx->version != 0 ) + goto Exit; + + /* we can't use FT_QNEW_ARRAY here; otherwise tt_face_free_hdmx */ + /* could fail during deallocation */ + if ( FT_NEW_ARRAY( hdmx->records, num_records ) ) + goto Exit; + + hdmx->num_records = num_records; + num_glyphs = face->root.num_glyphs; + record_size -= num_glyphs + 2; + + { + TT_HdmxEntry cur = hdmx->records; + TT_HdmxEntry limit = cur + hdmx->num_records; + + + for ( ; cur < limit; cur++ ) + { + /* read record */ + if ( FT_READ_BYTE( cur->ppem ) || + FT_READ_BYTE( cur->max_width ) ) + goto Exit; + + if ( FT_QALLOC( cur->widths, num_glyphs ) || + FT_STREAM_READ( cur->widths, num_glyphs ) ) + goto Exit; + + /* skip padding bytes */ + if ( record_size > 0 && FT_STREAM_SKIP( record_size ) ) + goto Exit; + } + } + + Exit: + return error; + } + + + FT_LOCAL_DEF( void ) + tt_face_free_hdmx( TT_Face face ) + { + if ( face ) + { + FT_Int n; + FT_Memory memory = face->root.driver->root.memory; + + + for ( n = 0; n < face->hdmx.num_records; n++ ) + FT_FREE( face->hdmx.records[n].widths ); + + FT_FREE( face->hdmx.records ); + face->hdmx.num_records = 0; + } + } + +#endif /* !OPTIMIZE_MEMORY */ + + /*************************************************************************/ + /* */ + /* Returns the advance width table for a given pixel size if it is found */ + /* in the font's `hdmx' table (if any). */ + /* */ + FT_LOCAL_DEF( FT_Byte* ) + tt_face_get_device_metrics( TT_Face face, + FT_Byte ppem, + FT_UInt gindex ) + { +#ifdef FT_OPTIMIZE_MEMORY + + FT_UInt nn; + FT_Byte* result = NULL; + FT_ULong record_size = face->hdmx_record_size; + FT_Byte* record = face->hdmx_table + 8; + + + for ( nn = 0; nn < face->hdmx_record_count; nn++ ) + if ( face->hdmx_record_sizes[nn] == ppem ) + { + gindex += 2; + if ( gindex < record_size ) + result = record + gindex; + break; + } + + return result; + +#else + + FT_UShort n; + + + for ( n = 0; n < face->hdmx.num_records; n++ ) + if ( face->hdmx.records[n].ppem == ppem ) + return &face->hdmx.records[n].widths[gindex]; + + return NULL; + +#endif + } + + /* END */ diff --git a/src/truetype/ttpload.h b/src/truetype/ttpload.h index 2acb4b360..b484f02a1 100644 --- a/src/truetype/ttpload.h +++ b/src/truetype/ttpload.h @@ -2,9 +2,9 @@ /* */ /* ttpload.h */ /* */ -/* TrueType glyph data/program tables loader (specification). */ +/* TrueType-specific tables loader (specification). */ /* */ -/* Copyright 1996-2001, 2002, 2005 by */ +/* Copyright 1996-2001, 2002, 2005, 2006 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -48,6 +48,25 @@ FT_BEGIN_HEADER FT_Stream stream ); + FT_LOCAL( FT_Error ) + tt_face_load_prep( TT_Face face, + FT_Stream stream ); + + + FT_LOCAL( FT_Error ) + tt_face_load_hdmx( TT_Face face, + FT_Stream stream ); + + + FT_LOCAL( void ) + tt_face_free_hdmx( TT_Face face ); + + + FT_LOCAL( FT_Byte* ) + tt_face_get_device_metrics( TT_Face face, + FT_Byte ppem, + FT_UInt gindex ); + FT_END_HEADER #endif /* __TTPLOAD_H__ */