From f5aa47beb077998675f5adc38c94aaf7ee8a447e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wu=2C=20Chia-I=20=28=E5=90=B3=E4=BD=B3=E4=B8=80=29?= Date: Tue, 14 Feb 2006 06:40:10 +0000 Subject: [PATCH] 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. --- ChangeLog | 32 + include/freetype/internal/fttrace.h | 1 + include/freetype/internal/sfnt.h | 62 +- src/cff/cffgload.c | 119 +-- src/cff/cffobjs.c | 2 +- src/sfnt/rules.mk | 1 + src/sfnt/sfdriver.c | 25 +- src/sfnt/sfnt.c | 1 + src/sfnt/sfobjs.c | 32 +- src/sfnt/ttload.c | 557 +------------- src/sfnt/ttload.h | 36 +- src/sfnt/ttmtx.c | 1038 +++++++++++++++++++++++++++ src/sfnt/ttmtx.h | 98 +++ src/sfnt/ttsbit.c | 6 +- src/sfnt/ttsbit.h | 6 +- src/sfnt/ttsbit0.c | 6 +- src/truetype/ttgload.c | 181 +---- src/truetype/ttobjs.c | 17 +- src/truetype/ttpload.c | 272 ++++++- src/truetype/ttpload.h | 23 +- 20 files changed, 1588 insertions(+), 927 deletions(-) create mode 100644 src/sfnt/ttmtx.c create mode 100644 src/sfnt/ttmtx.h 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__ */