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.
This commit is contained in:
Wu, Chia-I (吳佳一) 2006-02-14 06:40:10 +00:00
parent d39fda2b55
commit f5aa47beb0
20 changed files with 1588 additions and 927 deletions

View File

@ -1,3 +1,35 @@
2006-02-13 Chia-I Wu <b90201047@ntu.edu.tw>
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 <b90201047@ntu.edu.tw>
* src/autofit/afcjk.c (af_cjk_metrics_init): Fix a stupid bug...

View File

@ -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) */

View File

@ -442,6 +442,31 @@ FT_BEGIN_HEADER
/* TT_Load_Metrics_Func */
/* */
/* <Description> */
/* Load a metrics table, which is a table comes with a horizontal */
/* and a vertical version. */
/* */
/* <Input> */
/* face :: A handle to the target face object. */
/* */
/* stream :: The input stream. */
/* */
/* vertical :: A boolean flag. If set, load the vertical one. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
typedef FT_Error
(*TT_Load_Metrics_Func)( TT_Face face,
FT_Stream stream,
FT_Bool vertical );
/*************************************************************************/
/* */
/* <FuncType> */
/* TT_Get_Metrics_Func */
/* */
/* <Description> */
/* Load the horizontal or vertical header in a face object. */
/* */
/* <Input> */
@ -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;

View File

@ -569,117 +569,6 @@
}
/*************************************************************************/
/* */
/* <Function> */
/* cff_face_get_vertical_metrics */
/* */
/* <Description> */
/* Return the vertical metrics in font units for a given glyph. The */
/* metrics are the top side bearing and advance height. */
/* */
/* <Input> */
/* header :: A pointer to the vertical metrics structure. */
/* */
/* idx :: The glyph index. */
/* */
/* <Output> */
/* bearing :: The top side bearing. */
/* */
/* advance :: The advance height. */
/* */
/* <Note> */
/* 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;
}

View File

@ -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;

View File

@ -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 \

View File

@ -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' */

View File

@ -20,6 +20,7 @@
#include <ft2build.h>
#include "ttload.c"
#include "ttmtx.c"
#include "ttcmap.c"
#include "ttkern.c"
#include "sfobjs.c"

View File

@ -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 );

View File

@ -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 @@
}
/*************************************************************************/
/* */
/* <Function> */
/* tt_face_load_metrics */
/* */
/* <Description> */
/* Loads the horizontal or vertical metrics table into a face object. */
/* */
/* <Input> */
/* face :: A handle to the target face object. */
/* */
/* stream :: The input stream. */
/* */
/* vertical :: A boolean flag. If set, load vertical metrics. */
/* */
/* <Return> */
/* 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 */
/*************************************************************************/
/* */
/* <Function> */
/* tt_face_load_metrics_header */
/* */
/* <Description> */
/* Loads the horizontal or vertical header in a face object. */
/* */
/* <Input> */
/* face :: A handle to the target face object. */
/* */
/* stream :: The input stream. */
/* */
/* vertical :: A boolean flag. If set, load vertical metrics. */
/* */
/* <Return> */
/* 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;
}
/*************************************************************************/
/* */
/* <Function> */
@ -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 @@
}
/*************************************************************************/
/* */
/* <Function> */
/* tt_face_load_hdmx */
/* */
/* <Description> */
/* Loads the horizontal device metrics table. */
/* */
/* <Input> */
/* face :: A handle to the target face object. */
/* */
/* stream :: A handle to the input stream. */
/* */
/* <Return> */
/* 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 */

View File

@ -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 */

1038
src/sfnt/ttmtx.c Normal file

File diff suppressed because it is too large Load Diff

98
src/sfnt/ttmtx.h Normal file
View File

@ -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 <ft2build.h>
#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 <ft2build.h>
#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 */

View File

@ -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;

View File

@ -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 )

View File

@ -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;

View File

@ -63,131 +63,6 @@
#define UNSCALED_COMPONENT_OFFSET 0x1000
/*************************************************************************/
/* */
/* <Function> */
/* tt_face_get_metrics */
/* */
/* <Description> */
/* 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). */
/* */
/* <Input> */
/* header :: A pointer to either the horizontal or vertical metrics */
/* structure. */
/* */
/* idx :: The glyph index. */
/* */
/* <Output> */
/* bearing :: The bearing, either left side or top side. */
/* */
/* advance :: The advance width resp. advance height. */
/* */
/* <Note> */
/* 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;
}

View File

@ -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;

View File

@ -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 */
/* */
/* <Description> */
/* Loads the font program and the cvt program. */
/* Loads the font program. */
/* */
/* <InOut> */
/* 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
}
/*************************************************************************/
/* */
/* <Function> */
/* tt_face_load_prep */
/* */
/* <Description> */
/* Loads the cvt program. */
/* */
/* <InOut> */
/* face :: A handle to the target face object. */
/* */
/* <Input> */
/* stream :: A handle to the input stream. */
/* */
/* <Return> */
/* 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 @@
}
/*************************************************************************/
/* */
/* <Function> */
/* tt_face_load_hdmx */
/* */
/* <Description> */
/* Loads the `hdmx' table into the face object. */
/* */
/* <Input> */
/* face :: A handle to the target face object. */
/* */
/* stream :: A handle to the input stream. */
/* */
/* <Return> */
/* 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 */

View File

@ -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__ */