diff options
author | David 'Digit' Turner <digit@google.com> | 2009-06-08 15:18:21 +0200 |
---|---|---|
committer | David 'Digit' Turner <digit@google.com> | 2009-06-08 15:18:21 +0200 |
commit | 77f63d23f7d380b0ff02c18fd6a154ab9063128a (patch) | |
tree | 14b8437e23a816c57512fe472fdef4c7875c2eba /src/sfnt | |
parent | d04869994887b14ee43c9f8a9a8597193b5a7107 (diff) | |
download | android_external_freetype-77f63d23f7d380b0ff02c18fd6a154ab9063128a.tar.gz android_external_freetype-77f63d23f7d380b0ff02c18fd6a154ab9063128a.tar.bz2 android_external_freetype-77f63d23f7d380b0ff02c18fd6a154ab9063128a.zip |
Integrate FreeType 2.3.9 into the donut tree.
This is done to get fixes for a few security-related issues.
NOTE: the auto-hinter hasn't been changed to avoid modifying the rendering
of characters. The 2.3.9 code contains minor fixes (not security-related)
that could in theory do that (though extensive testing is needed to
evaluate its real impact on Android).
Diffstat (limited to 'src/sfnt')
-rw-r--r-- | src/sfnt/sfdriver.c | 29 | ||||
-rw-r--r-- | src/sfnt/sfobjs.c | 278 | ||||
-rw-r--r-- | src/sfnt/ttcmap.c | 160 | ||||
-rw-r--r-- | src/sfnt/ttkern.c | 29 | ||||
-rw-r--r-- | src/sfnt/ttload.c | 181 | ||||
-rw-r--r-- | src/sfnt/ttmtx.c | 14 | ||||
-rw-r--r-- | src/sfnt/ttpost.c | 15 | ||||
-rw-r--r-- | src/sfnt/ttsbit.c | 23 | ||||
-rw-r--r-- | src/sfnt/ttsbit.h | 4 | ||||
-rw-r--r-- | src/sfnt/ttsbit0.c | 129 |
10 files changed, 510 insertions, 352 deletions
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index 5ba22a6..142ef76 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -4,7 +4,7 @@ /* */ /* High-level SFNT driver interface (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -151,10 +151,35 @@ } + static FT_UInt + sfnt_get_name_index( TT_Face face, + FT_String* glyph_name ) + { + FT_Face root = &face->root; + FT_Long i; + + + for ( i = 0; i < root->num_glyphs; i++ ) + { + FT_String* gname; + FT_Error error = tt_face_get_ps_name( face, i, &gname ); + + + if ( error ) + continue; + + if ( !ft_strcmp( glyph_name, gname ) ) + return (FT_UInt)i; + } + + return 0; + } + + static const FT_Service_GlyphDictRec sfnt_service_glyph_dict = { (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, - (FT_GlyphDict_NameIndexFunc)NULL + (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index }; #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index c25b87d..c826b92 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -123,14 +123,20 @@ /* */ /* nameid :: The name id of the name record to return. */ /* */ + /* <InOut> */ + /* name :: The address of a string pointer. NULL if no name is */ + /* present. */ + /* */ /* <Return> */ - /* Character string. NULL if no name is present. */ + /* FreeType error code. 0 means success. */ /* */ - static FT_String* - tt_face_get_name( TT_Face face, - FT_UShort nameid ) + static FT_Error + tt_face_get_name( TT_Face face, + FT_UShort nameid, + FT_String** name ) { FT_Memory memory = face->root.memory; + FT_Error error = SFNT_Err_Ok; FT_String* result = NULL; FT_UShort n; TT_NameEntryRec* rec; @@ -145,6 +151,8 @@ TT_NameEntry_ConvertFunc convert; + FT_ASSERT( name ); + rec = face->name_table.names; for ( n = 0; n < face->num_names; n++, rec++ ) { @@ -256,11 +264,8 @@ { if ( rec->string == NULL ) { - FT_Error error = SFNT_Err_Ok; FT_Stream stream = face->name_table.stream; - FT_UNUSED( error ); - if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) || FT_STREAM_SEEK( rec->stringOffset ) || @@ -277,7 +282,8 @@ } Exit: - return result; + *name = result; + return error; } @@ -363,11 +369,12 @@ if ( FT_READ_ULONG( tag ) ) return error; - if ( tag != 0x00010000UL && - tag != TTAG_ttcf && - tag != FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) && - tag != TTAG_true && - tag != 0x00020000UL ) + if ( tag != 0x00010000UL && + tag != TTAG_ttcf && + tag != TTAG_OTTO && + tag != TTAG_true && + tag != TTAG_typ1 && + tag != 0x00020000UL ) return SFNT_Err_Unknown_File_Format; face->ttc_header.tag = TTAG_ttcf; @@ -401,7 +408,7 @@ face->ttc_header.version = 1 << 16; face->ttc_header.count = 1; - if ( FT_NEW( face->ttc_header.offsets) ) + if ( FT_NEW( face->ttc_header.offsets ) ) return error; face->ttc_header.offsets[0] = offset; @@ -451,7 +458,7 @@ face_index = 0; if ( face_index >= face->ttc_header.count ) - return SFNT_Err_Bad_Argument; + return SFNT_Err_Invalid_Argument; if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) return error; @@ -461,7 +468,8 @@ if ( error ) return error; - face->root.num_faces = face->ttc_header.count; + face->root.num_faces = face->ttc_header.count; + face->root.face_index = face_index; return error; } @@ -498,6 +506,13 @@ FT_TRACE3(( "\n" )); \ } while ( 0 ) +#define GET_NAME( id, field ) \ + do { \ + error = tt_face_get_name( face, TT_NAME_ID_##id, field ); \ + if ( error ) \ + goto Exit; \ + } while ( 0 ) + FT_LOCAL_DEF( FT_Error ) sfnt_load_face( FT_Stream stream, @@ -506,7 +521,10 @@ FT_Int num_params, FT_Parameter* params ) { - FT_Error error, psnames_error; + FT_Error error; +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + FT_Error psnames_error; +#endif FT_Bool has_outline; FT_Bool is_apple_sbit; @@ -581,7 +599,10 @@ /* don't check for errors */ LOAD_( name ); LOAD_( post ); + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES psnames_error = error; +#endif /* do not load the metrics headers and tables if this is an Apple */ /* sbit font file */ @@ -660,19 +681,20 @@ face->os2.version = 0xFFFFU; } - } /* the optional tables */ - /* embedded bitmap support. */ + /* embedded bitmap support */ if ( sfnt->load_eblc ) { LOAD_( eblc ); if ( error ) { - /* return an error if this font file has no outlines */ - if ( error == SFNT_Err_Table_Missing && has_outline ) + /* a font which contains neither bitmaps nor outlines is */ + /* still valid (although rather useless in most cases); */ + /* however, you can find such stripped fonts in PDFs */ + if ( error == SFNT_Err_Table_Missing ) error = SFNT_Err_Ok; else goto Exit; @@ -692,59 +714,38 @@ LOAD_( gasp ); LOAD_( kern ); - error = SFNT_Err_Ok; - face->root.num_glyphs = face->max_profile.numGlyphs; -#if 0 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ /* a WWS-only font face. `WWS' stands for `weight', width', and */ /* `slope', a term used by Microsoft's Windows Presentation */ - /* Foundation (WPF). This flag will be introduced in version */ - /* 1.5 of the OpenType specification (but is already in use). */ + /* Foundation (WPF). This flag has been introduced in version */ + /* 1.5 of the OpenType specification (May 2008). */ if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) -#endif { - face->root.family_name = - tt_face_get_name( face, TT_NAME_ID_PREFERRED_FAMILY ); + GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); if ( !face->root.family_name ) - face->root.family_name = - tt_face_get_name( face, TT_NAME_ID_FONT_FAMILY ); + GET_NAME( FONT_FAMILY, &face->root.family_name ); - face->root.style_name = - tt_face_get_name( face, TT_NAME_ID_PREFERRED_SUBFAMILY ); + GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); if ( !face->root.style_name ) - face->root.style_name = - tt_face_get_name( face, TT_NAME_ID_FONT_SUBFAMILY ); + GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } -#if 0 else { - /* Support for `name' table ID 21 (WWS family) and 22 (WWS */ - /* subfamily) is still under consideration by Microsoft and */ - /* not implemented in the current version of WPF. */ - - face->root.family_name = - tt_face_get_name( face, TT_NAME_ID_WWS_FAMILY ); + GET_NAME( WWS_FAMILY, &face->root.family_name ); if ( !face->root.family_name ) - face->root.family_name = - tt_face_get_name( face, TT_NAME_ID_PREFERRED_FAMILY ); + GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); if ( !face->root.family_name ) - face->root.family_name = - tt_face_get_name( face, TT_NAME_ID_FONT_FAMILY ); + GET_NAME( FONT_FAMILY, &face->root.family_name ); - face->root.style_name = - tt_face_get_name( face, TT_NAME_ID_WWS_SUBFAMILY ); + GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); if ( !face->root.style_name ) - face->root.style_name = - tt_face_get_name( face, TT_NAME_ID_PREFERRED_SUBFAMILY ); + GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); if ( !face->root.style_name ) - face->root.style_name = - tt_face_get_name( face, TT_NAME_ID_FONT_SUBFAMILY ); + GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } -#endif - /* now set up root fields */ { @@ -801,10 +802,9 @@ flags = 0; if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) { - /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ - /* indicates an oblique font face. This flag will be */ - /* introduced in version 1.5 of the OpenType specification (but */ - /* is already in use). */ + /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ + /* indicates an oblique font face. This flag has been */ + /* introduced in version 1.5 of the OpenType specification. */ if ( face->os2.fsSelection & 512 ) /* bit 9 */ flags |= FT_STYLE_FLAG_ITALIC; @@ -817,6 +817,7 @@ else { /* this is an old Mac font, use the header field */ + if ( face->header.Mac_Style & 1 ) flags |= FT_STYLE_FLAG_BOLD; @@ -861,12 +862,78 @@ } } +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /* + * Now allocate the root array of FT_Bitmap_Size records and + * populate them. Unfortunately, it isn't possible to indicate bit + * depths in the FT_Bitmap_Size record. This is a design error. + */ + { + FT_UInt i, count; + + +#ifndef FT_CONFIG_OPTION_OLD_INTERNALS + count = face->sbit_num_strikes; +#else + count = (FT_UInt)face->num_sbit_strikes; +#endif + + if ( count > 0 ) + { + FT_Memory memory = face->root.stream->memory; + FT_UShort em_size = face->header.Units_Per_EM; + FT_Short avgwidth = face->os2.xAvgCharWidth; + FT_Size_Metrics metrics; + + + if ( em_size == 0 || face->os2.version == 0xFFFFU ) + { + avgwidth = 0; + em_size = 1; + } + + if ( FT_NEW_ARRAY( root->available_sizes, count ) ) + goto Exit; + + for ( i = 0; i < count; i++ ) + { + FT_Bitmap_Size* bsize = root->available_sizes + i; + + + error = sfnt->load_strike_metrics( face, i, &metrics ); + if ( error ) + goto Exit; + + bsize->height = (FT_Short)( metrics.height >> 6 ); + bsize->width = (FT_Short)( + ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); + + bsize->x_ppem = metrics.x_ppem << 6; + bsize->y_ppem = metrics.y_ppem << 6; + + /* assume 72dpi */ + bsize->size = metrics.y_ppem << 6; + } + + root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; + root->num_fixed_sizes = (FT_Int)count; + } + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /* a font with no bitmaps and no outlines is scalable; */ + /* it has only empty glyphs then */ + if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) ) + root->face_flags |= FT_FACE_FLAG_SCALABLE; + /*********************************************************************/ /* */ /* Set up metrics. */ /* */ - if ( has_outline == TRUE ) + if ( FT_IS_SCALABLE( root ) ) { /* XXX What about if outline header is missing */ /* (e.g. sfnt wrapped bitmap)? */ @@ -919,10 +986,9 @@ /* this computation is based on various versions of Times New Roman */ if ( face->horizontal.Line_Gap == 0 ) root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 ); -#endif +#endif /* 0 */ #if 0 - /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */ /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */ if ( face->os2.version != 0xFFFFU && root->ascender ) @@ -937,80 +1003,21 @@ if ( height > root->height ) root->height = height; } - #endif /* 0 */ - root->max_advance_width = face->horizontal.advance_Width_Max; + root->max_advance_width = face->horizontal.advance_Width_Max; + root->max_advance_height = (FT_Short)( face->vertical_info + ? face->vertical.advance_Height_Max + : root->height ); - root->max_advance_height = (FT_Short)( face->vertical_info - ? face->vertical.advance_Height_Max - : root->height ); - - root->underline_position = face->postscript.underlinePosition; + /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */ + /* Adjust underline position from top edge to centre of */ + /* stroke to convert TrueType meaning to FreeType meaning. */ + root->underline_position = face->postscript.underlinePosition - + face->postscript.underlineThickness / 2; root->underline_thickness = face->postscript.underlineThickness; } -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - /* - * Now allocate the root array of FT_Bitmap_Size records and - * populate them. Unfortunately, it isn't possible to indicate bit - * depths in the FT_Bitmap_Size record. This is a design error. - */ - { - FT_UInt i, count; - - -#if !defined FT_CONFIG_OPTION_OLD_INTERNALS - count = face->sbit_num_strikes; -#else - count = (FT_UInt)face->num_sbit_strikes; -#endif - - if ( count > 0 ) - { - FT_Memory memory = face->root.stream->memory; - FT_UShort em_size = face->header.Units_Per_EM; - FT_Short avgwidth = face->os2.xAvgCharWidth; - FT_Size_Metrics metrics; - - - if ( em_size == 0 || face->os2.version == 0xFFFFU ) - { - avgwidth = 0; - em_size = 1; - } - - if ( FT_NEW_ARRAY( root->available_sizes, count ) ) - goto Exit; - - for ( i = 0; i < count; i++ ) - { - FT_Bitmap_Size* bsize = root->available_sizes + i; - - - error = sfnt->load_strike_metrics( face, i, &metrics ); - if ( error ) - goto Exit; - - bsize->height = (FT_Short)( metrics.height >> 6 ); - bsize->width = (FT_Short)( - ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); - - bsize->x_ppem = metrics.x_ppem << 6; - bsize->y_ppem = metrics.y_ppem << 6; - - /* assume 72dpi */ - bsize->size = metrics.y_ppem << 6; - } - - root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; - root->num_fixed_sizes = (FT_Int)count; - } - } - -#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - } Exit: @@ -1022,14 +1029,21 @@ #undef LOAD_ #undef LOADM_ +#undef GET_NAME FT_LOCAL_DEF( void ) sfnt_done_face( TT_Face face ) { - FT_Memory memory = face->root.memory; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + FT_Memory memory; + SFNT_Service sfnt; + + + if ( !face ) + return; + memory = face->root.memory; + sfnt = (SFNT_Service)face->sfnt; if ( sfnt ) { @@ -1068,7 +1082,7 @@ } /* freeing the horizontal metrics */ -#if !defined FT_CONFIG_OPTION_OLD_INTERNALS +#ifndef FT_CONFIG_OPTION_OLD_INTERNALS { FT_Stream stream = FT_FACE_STREAM( face ); diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c index b70b64c..6830391 100644 --- a/src/sfnt/ttcmap.c +++ b/src/sfnt/ttcmap.c @@ -4,7 +4,7 @@ /* */ /* TrueType character mapping table (cmap) support (body). */ /* */ -/* Copyright 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -134,7 +134,7 @@ FT_UInt gindex = 0; - table += 6; /* go to glyph ids */ + table += 6; /* go to glyph IDs */ while ( ++charcode < 256 ) { gindex = table[charcode]; @@ -231,7 +231,7 @@ /* language 4 USHORT Mac language code */ /* keys 6 USHORT[256] sub-header keys */ /* subs 518 SUBHEAD[NSUBS] sub-headers array */ - /* glyph_ids 518+NSUB*8 USHORT[] glyph id array */ + /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */ /* */ /* The `keys' table is used to map charcode high-bytes to sub-headers. */ /* The value of `NSUBS' is the number of sub-headers defined in the */ @@ -260,14 +260,14 @@ /* */ /* * The value of `offset' is read. This is a _byte_ distance from the */ /* location of the `offset' field itself into a slice of the */ - /* `glyph_ids' table. Let's call it `slice' (it's a USHORT[] too). */ + /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[] too). */ /* */ /* * The value `slice[char.lo - first]' is read. If it is 0, there is */ /* no glyph for the charcode. Otherwise, the value of `delta' is */ /* added to it (modulo 65536) to form a new glyph index. */ /* */ /* It is up to the validation routine to check that all offsets fall */ - /* within the glyph ids table (and not within the `subs' table itself or */ + /* within the glyph IDs table (and not within the `subs' table itself or */ /* outside of the CMap). */ /* */ @@ -282,7 +282,7 @@ FT_UInt n, max_subs; FT_Byte* keys; /* keys table */ FT_Byte* subs; /* sub-headers */ - FT_Byte* glyph_ids; /* glyph id array */ + FT_Byte* glyph_ids; /* glyph ID array */ if ( table + length > valid->limit || length < 6 + 512 ) @@ -328,6 +328,10 @@ delta = TT_NEXT_SHORT( p ); offset = TT_NEXT_USHORT( p ); + /* many Dynalab fonts have empty sub-headers */ + if ( code_count == 0 ) + continue; + /* check range within 0..255 */ if ( valid->level >= FT_VALIDATE_PARANOID ) { @@ -342,7 +346,7 @@ if ( ids < glyph_ids || ids + code_count*2 > table + length ) FT_INVALID_OFFSET; - /* check glyph ids */ + /* check glyph IDs */ if ( valid->level >= FT_VALIDATE_TIGHT ) { FT_Byte* limit = p + code_count * 2; @@ -393,7 +397,7 @@ sub = subs; /* jump to first sub-header */ /* check that the sub-header for this byte is 0, which */ - /* indicates that it's really a valid one-byte value */ + /* indicates that it is really a valid one-byte value */ /* Otherwise, return 0 */ /* */ p += char_lo * 2; @@ -601,14 +605,14 @@ /* each segment; can be */ /* zero */ /* */ - /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph id */ + /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */ /* ranges */ /* */ /* Character codes are modelled by a series of ordered (increasing) */ /* intervals called segments. Each segment has start and end codes, */ /* provided by the `startCount' and `endCount' arrays. Segments must */ - /* not be overlapping and the last segment should always contain the */ - /* `0xFFFF' endCount. */ + /* not overlap, and the last segment should always contain the value */ + /* 0xFFFF for `endCount'. */ /* */ /* The fields `searchRange', `entrySelector' and `rangeShift' are better */ /* ignored (they are traces of over-engineering in the TrueType */ @@ -621,14 +625,14 @@ /* charcode within the segment is obtained by adding the value of */ /* `idDelta' directly to the charcode, modulo 65536. */ /* */ - /* Otherwise, a glyph index is taken from the glyph ids sub-array for */ + /* Otherwise, a glyph index is taken from the glyph IDs sub-array for */ /* the segment, and the value of `idDelta' is added to it. */ /* */ /* */ - /* Finally, note that certain fonts contain invalid charmaps that */ - /* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the */ - /* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */ - /* we need special code to deal with them correctly... */ + /* Finally, note that a lot of fonts contain an invalid last segment, */ + /* where `start' and `end' are correctly set to 0xFFFF but both `delta' */ + /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */ + /* OpenOffice.org). We need special code to deal with them correctly. */ /* */ #ifdef TT_CONFIG_CMAP_FORMAT_4 @@ -693,6 +697,23 @@ p += num_ranges * 2; offset = FT_PEEK_USHORT( p ); + /* some fonts have an incorrect last segment; */ + /* we have to catch it */ + if ( range_index >= num_ranges - 1 && + cmap->cur_start == 0xFFFFU && + cmap->cur_end == 0xFFFFU ) + { + TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; + FT_Byte* limit = face->cmap_table + face->cmap_size; + + + if ( offset && p + offset + 2 > limit ) + { + cmap->cur_delta = 1; + offset = 0; + } + } + if ( offset != 0xFFFFU ) { cmap->cur_values = offset ? p + offset : NULL; @@ -831,7 +852,7 @@ /* */ if ( valid->level >= FT_VALIDATE_PARANOID ) { - /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */ + /* check the values of `searchRange', `entrySelector', `rangeShift' */ FT_UInt search_range = TT_NEXT_USHORT( p ); FT_UInt entry_selector = TT_NEXT_USHORT( p ); FT_UInt range_shift = TT_NEXT_USHORT( p ); @@ -858,7 +879,7 @@ offsets = deltas + num_segs * 2; glyph_ids = offsets + num_segs * 2; - /* check last segment, its end count must be FFFF */ + /* check last segment; its end count value must be 0xFFFF */ if ( valid->level >= FT_VALIDATE_PARANOID ) { p = ends + ( num_segs - 1 ) * 2; @@ -867,9 +888,9 @@ } { - FT_UInt start, end, offset, n; - FT_UInt last_start = 0, last_end = 0; - FT_Int delta; + FT_UInt start, end, offset, n; + FT_UInt last_start = 0, last_end = 0; + FT_Int delta; FT_Byte* p_start = starts; FT_Byte* p_end = ends; FT_Byte* p_delta = deltas; @@ -887,10 +908,10 @@ if ( start > end ) FT_INVALID_DATA; - /* this test should be performed at default validation level; */ - /* unfortunately, some popular Asian fonts present overlapping */ - /* ranges in their charmaps */ - /* */ + /* this test should be performed at default validation level; */ + /* unfortunately, some popular Asian fonts have overlapping */ + /* ranges in their charmaps */ + /* */ if ( start <= last_end && n > 0 ) { if ( valid->level >= FT_VALIDATE_TIGHT ) @@ -898,7 +919,7 @@ else { /* allow overlapping segments, provided their start points */ - /* and end points, respectively, are in ascending order. */ + /* and end points, respectively, are in ascending order */ /* */ if ( last_start > start || last_end > end ) error |= TT_CMAP_FLAG_UNSORTED; @@ -909,16 +930,27 @@ if ( offset && offset != 0xFFFFU ) { - p += offset; /* start of glyph id array */ + p += offset; /* start of glyph ID array */ - /* check that we point within the glyph ids table only */ + /* check that we point within the glyph IDs table only */ if ( valid->level >= FT_VALIDATE_TIGHT ) { if ( p < glyph_ids || p + ( end - start + 1 ) * 2 > table + length ) FT_INVALID_DATA; } - else + /* Some fonts handle the last segment incorrectly. In */ + /* theory, 0xFFFF might point to an ordinary glyph -- */ + /* a cmap 4 is versatile and could be used for any */ + /* encoding, not only Unicode. However, reality shows */ + /* that far too many fonts are sloppy and incorrectly */ + /* set all fields but `start' and `end' for the last */ + /* segment if it contains only a single character. */ + /* */ + /* We thus omit the test here, delaying it to the */ + /* routines which actually access the cmap. */ + else if ( n != num_segs - 1 || + !( start == 0xFFFFU && end == 0xFFFFU ) ) { if ( p < glyph_ids || p + ( end - start + 1 ) * 2 > valid->limit ) @@ -946,12 +978,12 @@ } else if ( offset == 0xFFFFU ) { - /* Some fonts (erroneously?) use a range offset of 0xFFFF */ + /* some fonts (erroneously?) use a range offset of 0xFFFF */ /* to mean missing glyph in cmap table */ /* */ - if ( valid->level >= FT_VALIDATE_PARANOID || - n != num_segs - 1 || - !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) ) + if ( valid->level >= FT_VALIDATE_PARANOID || + n != num_segs - 1 || + !( start == 0xFFFFU && end == 0xFFFFU ) ) FT_INVALID_DATA; } @@ -965,9 +997,9 @@ static FT_UInt - tt_cmap4_char_map_linear( TT_CMap cmap, - FT_UInt* pcharcode, - FT_Bool next ) + tt_cmap4_char_map_linear( TT_CMap cmap, + FT_UInt32* pcharcode, + FT_Bool next ) { FT_UInt num_segs2, start, end, offset; FT_Int delta; @@ -1009,6 +1041,22 @@ p += num_segs2; offset = TT_PEEK_USHORT( p ); + /* some fonts have an incorrect last segment; */ + /* we have to catch it */ + if ( i >= num_segs - 1 && + start == 0xFFFFU && end == 0xFFFFU ) + { + TT_Face face = (TT_Face)cmap->cmap.charmap.face; + FT_Byte* limit = face->cmap_table + face->cmap_size; + + + if ( offset && p + offset + 2 > limit ) + { + delta = 1; + offset = 0; + } + } + if ( offset == 0xFFFFU ) continue; @@ -1038,9 +1086,9 @@ static FT_UInt - tt_cmap4_char_map_binary( TT_CMap cmap, - FT_UInt* pcharcode, - FT_Bool next ) + tt_cmap4_char_map_binary( TT_CMap cmap, + FT_UInt32* pcharcode, + FT_Bool next ) { FT_UInt num_segs2, start, end, offset; FT_Int delta; @@ -1088,6 +1136,22 @@ p += num_segs2; offset = TT_PEEK_USHORT( p ); + /* some fonts have an incorrect last segment; */ + /* we have to catch it */ + if ( mid >= num_segs - 1 && + start == 0xFFFFU && end == 0xFFFFU ) + { + TT_Face face = (TT_Face)cmap->cmap.charmap.face; + FT_Byte* limit = face->cmap_table + face->cmap_size; + + + if ( offset && p + offset + 2 > limit ) + { + delta = 1; + offset = 0; + } + } + /* search the first segment containing `charcode' */ if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING ) { @@ -1359,7 +1423,7 @@ /* */ /* first 6 USHORT first segment code */ /* count 8 USHORT segment size in chars */ - /* glyphIds 10 USHORT[count] glyph ids */ + /* glyphIds 10 USHORT[count] glyph IDs */ /* */ /* A very simplified segment mapping. */ /* */ @@ -1506,7 +1570,7 @@ /***** *****/ /***** FORMAT 8 *****/ /***** *****/ - /***** It's hard to completely understand what the OpenType spec *****/ + /***** It is hard to completely understand what the OpenType spec *****/ /***** says about this format, but here is my conclusion. *****/ /***** *****/ /***** The purpose of this format is to easily map UTF-16 text to *****/ @@ -1521,7 +1585,7 @@ /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/ /***** Area. *****/ /***** *****/ - /***** The 'is32' table embedded in the charmap indicates whether a *****/ + /***** The `is32' table embedded in the charmap indicates whether a *****/ /***** given 16-bit value is in the surrogates area or not. *****/ /***** *****/ /***** So, for any given `char_code', we can assert the following: *****/ @@ -1548,11 +1612,11 @@ /* is32 12 BYTE[8192] 32-bitness bitmap */ /* count 8204 ULONG number of groups */ /* */ - /* This header is followed by 'count' groups of the following format: */ + /* This header is followed by `count' groups of the following format: */ /* */ /* start 0 ULONG first charcode */ /* end 4 ULONG last charcode */ - /* startId 8 ULONG start glyph id for the group */ + /* startId 8 ULONG start glyph ID for the group */ /* */ #ifdef TT_CONFIG_CMAP_FORMAT_8 @@ -1934,7 +1998,7 @@ /* */ /* start 0 ULONG first charcode */ /* end 4 ULONG last charcode */ - /* startId 8 ULONG start glyph id for the group */ + /* startId 8 ULONG start glyph ID for the group */ /* */ #ifdef TT_CONFIG_CMAP_FORMAT_12 @@ -2727,7 +2791,7 @@ FT_UInt tot = 0; - p += 3; /* point to the first 'cnt' field */ + p += 3; /* point to the first `cnt' field */ for ( ; numRanges > 0; numRanges-- ) { tot += 1 + p[0]; @@ -2774,7 +2838,7 @@ } - static FT_UInt* + static FT_UInt32* tt_cmap14_get_nondef_chars( TT_CMap cmap, FT_Byte *p, FT_Memory memory ) @@ -2962,7 +3026,7 @@ (TT_CMap_Info_GetFunc)tt_cmap14_get_info }; -#endif /* TT_CONFIG_CMAP_FORMAT_0 */ +#endif /* TT_CONFIG_CMAP_FORMAT_14 */ static const TT_CMap_Class tt_cmap_classes[] = diff --git a/src/sfnt/ttkern.c b/src/sfnt/ttkern.c index 28e52c3..67d5115 100644 --- a/src/sfnt/ttkern.c +++ b/src/sfnt/ttkern.c @@ -5,7 +5,7 @@ /* Load the basic TrueType kerning table. This doesn't handle */ /* kerning data within the GPOS table at the moment. */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -103,6 +103,9 @@ p_next += length; + if ( p_next > p_limit ) /* handle broken table */ + p_next = p_limit; + /* only use horizontal kerning tables */ if ( ( coverage & ~8 ) != 0x0001 || p + 8 > p_limit ) @@ -111,8 +114,8 @@ num_pairs = FT_NEXT_USHORT( p ); p += 6; - if ( p + 6 * num_pairs > p_limit ) - goto NextTable; + if ( ( p_next - p ) / 6 < (int)num_pairs ) /* handle broken count */ + num_pairs = (FT_UInt)( ( p_next - p ) / 6 ); avail |= mask; @@ -181,18 +184,22 @@ FT_Int result = 0; FT_UInt count, mask = 1; FT_Byte* p = face->kern_table; + FT_Byte* p_limit = p + face->kern_table_size; p += 4; mask = 0x0001; - for ( count = face->num_kern_tables; count > 0; count--, mask <<= 1 ) + for ( count = face->num_kern_tables; + count > 0 && p + 6 <= p_limit; + count--, mask <<= 1 ) { FT_Byte* base = p; FT_Byte* next = base; FT_UInt version = FT_NEXT_USHORT( p ); FT_UInt length = FT_NEXT_USHORT( p ); FT_UInt coverage = FT_NEXT_USHORT( p ); + FT_UInt num_pairs; FT_Int value = 0; FT_UNUSED( version ); @@ -200,21 +207,27 @@ next = base + length; + if ( next > p_limit ) /* handle broken table */ + next = p_limit; + if ( ( face->kern_avail_bits & mask ) == 0 ) goto NextTable; if ( p + 8 > next ) goto NextTable; + num_pairs = FT_NEXT_USHORT( p ); + p += 6; + + if ( ( next - p ) / 6 < (int)num_pairs ) /* handle broken count */ + num_pairs = (FT_UInt)( ( next - p ) / 6 ); + switch ( coverage >> 8 ) { case 0: { - FT_UInt num_pairs = FT_NEXT_USHORT( p ); - FT_ULong key0 = TT_KERN_INDEX( left_glyph, right_glyph ); - + FT_ULong key0 = TT_KERN_INDEX( left_glyph, right_glyph ); - p += 6; if ( face->kern_order_bits & mask ) /* binary search */ { diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c index 6b7c342..c45a1ed 100644 --- a/src/sfnt/ttload.c +++ b/src/sfnt/ttload.c @@ -58,6 +58,9 @@ { TT_Table entry; TT_Table limit; +#ifdef FT_DEBUG_LEVEL_TRACE + FT_Bool zero_length = FALSE; +#endif FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ", @@ -72,17 +75,28 @@ for ( ; entry < limit; entry++ ) { - /* For compatibility with Windows, we consider 0-length */ - /* tables the same as missing tables. */ - if ( entry->Tag == tag && entry->Length != 0 ) - { - FT_TRACE4(( "found table.\n" )); - return entry; + /* For compatibility with Windows, we consider */ + /* zero-length tables the same as missing tables. */ + if ( entry->Tag == tag ) { + if ( entry->Length != 0 ) + { + FT_TRACE4(( "found table.\n" )); + return entry; + } +#ifdef FT_DEBUG_LEVEL_TRACE + zero_length = TRUE; +#endif } } - FT_TRACE4(( "could not find table!\n" )); - return 0; +#ifdef FT_DEBUG_LEVEL_TRACE + if ( zero_length ) + FT_TRACE4(( "ignoring empty table!\n" )); + else + FT_TRACE4(( "could not find table!\n" )); +#endif + + return NULL; } @@ -124,7 +138,7 @@ *length = table->Length; if ( FT_STREAM_SEEK( table->Offset ) ) - goto Exit; + goto Exit; } else error = SFNT_Err_Table_Missing; @@ -134,27 +148,30 @@ } - /* Here, we */ - /* */ - /* - check that `num_tables' is valid */ - /* - look for a `head' table, check its size, and parse it to check */ - /* whether its `magic' field is correctly set */ - /* */ - /* When checking directory entries, ignore the tables `glyx' and `locx' */ - /* which are hacked-out versions of `glyf' and `loca' in some PostScript */ - /* Type 42 fonts, and which are generally invalid. */ - /* */ + /* Here, we */ + /* */ + /* - check that `num_tables' is valid (and adjust it if necessary) */ + /* */ + /* - look for a `head' table, check its size, and parse it to check */ + /* whether its `magic' field is correctly set */ + /* */ + /* - errors (except errors returned by stream handling) */ + /* */ + /* SFNT_Err_Unknown_File_Format: */ + /* no table is defined in directory, it is not sfnt-wrapped */ + /* data */ + /* SFNT_Err_Table_Missing: */ + /* table directory is valid, but essential tables */ + /* (head/bhed/SING) are missing */ + /* */ static FT_Error check_table_dir( SFNT_Header sfnt, FT_Stream stream ) { - FT_Error error; - FT_UInt nn; - FT_UInt has_head = 0, has_sing = 0, has_meta = 0; - FT_ULong offset = sfnt->offset + 12; - - const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' ); - const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' ); + FT_Error error; + FT_UInt nn, valid_entries = 0; + FT_UInt has_head = 0, has_sing = 0, has_meta = 0; + FT_ULong offset = sfnt->offset + 12; static const FT_Frame_Field table_dir_entry_fields[] = { @@ -170,12 +187,8 @@ }; - if ( sfnt->num_tables == 0 || - offset + sfnt->num_tables * 16 > stream->size ) - return SFNT_Err_Unknown_File_Format; - if ( FT_STREAM_SEEK( offset ) ) - return error; + goto Exit; for ( nn = 0; nn < sfnt->num_tables; nn++ ) { @@ -183,12 +196,23 @@ if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) ) - return error; + { + nn--; + FT_TRACE2(( "check_table_dir:" + " can read only %d table%s in font (instead of %d)\n", + nn, nn == 1 ? "" : "s", sfnt->num_tables )); + sfnt->num_tables = nn; + break; + } - if ( table.Offset + table.Length > stream->size && - table.Tag != glyx_tag && - table.Tag != locx_tag ) - return SFNT_Err_Unknown_File_Format; + /* we ignore invalid tables */ + if ( table.Offset + table.Length > stream->size ) + { + FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn )); + continue; + } + else + valid_entries++; if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed ) { @@ -210,17 +234,26 @@ * */ if ( table.Length < 0x36 ) - return SFNT_Err_Unknown_File_Format; + { + FT_TRACE2(( "check_table_dir: `head' table too small\n" )); + error = SFNT_Err_Table_Missing; + goto Exit; + } if ( FT_STREAM_SEEK( table.Offset + 12 ) || FT_READ_ULONG( magic ) ) - return error; + goto Exit; if ( magic != 0x5F0F3CF5UL ) - return SFNT_Err_Unknown_File_Format; + { + FT_TRACE2(( "check_table_dir:" + " no magic number found in `head' table\n")); + error = SFNT_Err_Table_Missing; + goto Exit; + } if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) ) - return error; + goto Exit; } else if ( table.Tag == TTAG_SING ) has_sing = 1; @@ -228,11 +261,34 @@ has_meta = 1; } + sfnt->num_tables = valid_entries; + + if ( sfnt->num_tables == 0 ) + { + FT_TRACE2(( "check_table_dir: no tables found\n" )); + error = SFNT_Err_Unknown_File_Format; + goto Exit; + } + /* if `sing' and `meta' tables are present, there is no `head' table */ if ( has_head || ( has_sing && has_meta ) ) - return SFNT_Err_Ok; + { + error = SFNT_Err_Ok; + goto Exit; + } else - return SFNT_Err_Unknown_File_Format; + { + FT_TRACE2(( "check_table_dir:" )); +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" )); +#else + FT_TRACE2(( " neither `head' nor `sing' table found\n" )); +#endif + error = SFNT_Err_Table_Missing; + } + + Exit: + return error; } @@ -266,7 +322,7 @@ FT_Error error; FT_Memory memory = stream->memory; TT_TableRec* entry; - TT_TableRec* limit; + FT_Int nn; static const FT_Frame_Field offset_table_fields[] = { @@ -290,7 +346,7 @@ if ( FT_READ_ULONG( sfnt.format_tag ) || FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) ) - return error; + goto Exit; /* many fonts don't have these fields set correctly */ #if 0 @@ -301,51 +357,58 @@ /* load the table directory */ - FT_TRACE2(( "-- Tables count: %12u\n", sfnt.num_tables )); - FT_TRACE2(( "-- Format version: %08lx\n", sfnt.format_tag )); + FT_TRACE2(( "-- Number of tables: %10u\n", sfnt.num_tables )); + FT_TRACE2(( "-- Format version: 0x%08lx\n", sfnt.format_tag )); /* check first */ error = check_table_dir( &sfnt, stream ); if ( error ) { - FT_TRACE2(( "tt_face_load_font_dir: invalid table directory!\n" )); + FT_TRACE2(( "tt_face_load_font_dir: invalid table directory for TrueType!\n" )); - return error; + goto Exit; } face->num_tables = sfnt.num_tables; face->format_tag = sfnt.format_tag; if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) ) - return error; + goto Exit; if ( FT_STREAM_SEEK( sfnt.offset + 12 ) || FT_FRAME_ENTER( face->num_tables * 16L ) ) - return error; + goto Exit; entry = face->dir_tables; - limit = entry + face->num_tables; - for ( ; entry < limit; entry++ ) + for ( nn = 0; nn < sfnt.num_tables; nn++ ) { entry->Tag = FT_GET_TAG4(); entry->CheckSum = FT_GET_ULONG(); entry->Offset = FT_GET_LONG(); entry->Length = FT_GET_LONG(); - FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n", - (FT_Char)( entry->Tag >> 24 ), - (FT_Char)( entry->Tag >> 16 ), - (FT_Char)( entry->Tag >> 8 ), - (FT_Char)( entry->Tag ), - entry->Offset, - entry->Length )); + /* ignore invalid tables */ + if ( entry->Offset + entry->Length > stream->size ) + continue; + else + { + FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n", + (FT_Char)( entry->Tag >> 24 ), + (FT_Char)( entry->Tag >> 16 ), + (FT_Char)( entry->Tag >> 8 ), + (FT_Char)( entry->Tag ), + entry->Offset, + entry->Length )); + entry++; + } } FT_FRAME_EXIT(); FT_TRACE2(( "table directory loaded\n\n" )); + Exit: return error; } diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c index 55f681a..2a7d22c 100644 --- a/src/sfnt/ttmtx.c +++ b/src/sfnt/ttmtx.c @@ -4,7 +4,7 @@ /* */ /* Load the metrics tables common to TTF and OTF fonts (body). */ /* */ -/* Copyright 2006, 2007 by */ +/* Copyright 2006, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -60,7 +60,7 @@ /* <Return> */ /* FreeType error code. 0 means success. */ /* */ -#if !defined FT_CONFIG_OPTION_OLD_INTERNALS +#ifndef FT_CONFIG_OPTION_OLD_INTERNALS FT_LOCAL_DEF( FT_Error ) tt_face_load_hmtx( TT_Face face, @@ -97,7 +97,7 @@ return error; } -#else /* !OPTIMIZE_MEMORY || OLD_INTERNALS */ +#else /* !FT_CONFIG_OPTION_OLD_INTERNALS */ FT_LOCAL_DEF( FT_Error ) tt_face_load_hmtx( TT_Face face, @@ -229,7 +229,7 @@ return error; } -#endif /* !OPTIMIZE_MEMORY || OLD_INTERNALS */ +#endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */ /*************************************************************************/ @@ -341,7 +341,7 @@ /* */ /* advance :: The advance width resp. advance height. */ /* */ -#if !defined FT_CONFIG_OPTION_OLD_INTERNALS +#ifndef FT_CONFIG_OPTION_OLD_INTERNALS FT_LOCAL_DEF( FT_Error ) tt_face_get_metrics( TT_Face face, @@ -420,7 +420,7 @@ return SFNT_Err_Ok; } -#else /* OLD_INTERNALS */ +#else /* !FT_CONFIG_OPTION_OLD_INTERNALS */ FT_LOCAL_DEF( FT_Error ) tt_face_get_metrics( TT_Face face, @@ -460,7 +460,7 @@ return SFNT_Err_Ok; } -#endif /* !OPTIMIZE_MEMORY || OLD_INTERNALS */ +#endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */ /* END */ diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c index 1e61636..ce628e2 100644 --- a/src/sfnt/ttpost.c +++ b/src/sfnt/ttpost.c @@ -5,7 +5,7 @@ /* Postcript name table processing for TrueType and OpenType fonts */ /* (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -62,11 +62,11 @@ /* table of Mac names. Thus, it is possible to build a version of */ /* FreeType without the Type 1 driver & PSNames module. */ -#define MAC_NAME( x ) tt_post_default_names[x] +#define MAC_NAME( x ) ( (FT_String*)tt_post_default_names[x] ) /* the 258 default Mac PS glyph names */ - static const FT_String* tt_post_default_names[258] = + static const FT_String* const tt_post_default_names[258] = { /* 0 */ ".notdef", ".null", "CR", "space", "exclam", @@ -416,13 +416,14 @@ /* tt_face_get_ps_name */ /* */ /* <Description> */ - /* Gets the PostScript glyph name of a glyph. */ + /* Get the PostScript glyph name of a glyph. */ /* */ /* <Input> */ /* face :: A handle to the parent face. */ /* */ /* idx :: The glyph index. */ /* */ + /* <InOut> */ /* PSname :: The address of a string pointer. Will be NULL in case */ /* of error, otherwise it is a pointer to the glyph name. */ /* */ @@ -436,9 +437,9 @@ FT_UInt idx, FT_String** PSname ) { - FT_Error error; - TT_Post_Names names; - FT_Fixed format; + FT_Error error; + TT_Post_Names names; + FT_Fixed format; #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES FT_Service_PsCMaps psnames; diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c index 8261ba5..eadaade 100644 --- a/src/sfnt/ttsbit.c +++ b/src/sfnt/ttsbit.c @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded bitmap support (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -24,11 +24,11 @@ * Alas, the memory-optimized sbit loader can't be used when implementing * the `old internals' hack */ -#if !defined FT_CONFIG_OPTION_OLD_INTERNALS +#ifndef FT_CONFIG_OPTION_OLD_INTERNALS #include "ttsbit0.c" -#else /* !FT_CONFIG_OPTION_OLD_INTERNALS */ +#else /* FT_CONFIG_OPTION_OLD_INTERNALS */ #include <ft2build.h> #include FT_INTERNAL_DEBUG_H @@ -83,7 +83,8 @@ FT_Int line_bits, FT_Bool byte_padded, FT_Int x_offset, - FT_Int y_offset ) + FT_Int y_offset, + FT_Int source_height ) { FT_Byte* line_buff; FT_Int line_incr; @@ -116,7 +117,7 @@ acc = 0; /* clear accumulator */ loaded = 0; /* no bits were loaded */ - for ( height = target->rows; height > 0; height-- ) + for ( height = source_height; height > 0; height-- ) { FT_Byte* cur = line_buff; /* current write cursor */ FT_Int count = line_bits; /* # of bits to extract per line */ @@ -772,7 +773,7 @@ Found: /* return successfully! */ *arange = range; - return 0; + return SFNT_Err_Ok; } } @@ -1230,7 +1231,7 @@ /* the sbit blitter doesn't make a difference between pixmap */ /* depths. */ blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes, - x_offset * pix_bits, y_offset ); + x_offset * pix_bits, y_offset, metrics->height ); FT_FRAME_EXIT(); } @@ -1324,7 +1325,11 @@ range->image_format, metrics, stream ); case 8: /* compound format */ - FT_Stream_Skip( stream, 1L ); + if ( FT_STREAM_SKIP( 1L ) ) + { + error = SFNT_Err_Invalid_Stream_Skip; + goto Exit; + } /* fallthrough */ case 9: @@ -1496,7 +1501,7 @@ return error; } -#endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */ +#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ /* END */ diff --git a/src/sfnt/ttsbit.h b/src/sfnt/ttsbit.h index c6067c0..7ea2af1 100644 --- a/src/sfnt/ttsbit.h +++ b/src/sfnt/ttsbit.h @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded bitmap support (specification). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -45,7 +45,7 @@ FT_BEGIN_HEADER FT_ULong strike_index, FT_Size_Metrics* metrics ); -#if defined FT_CONFIG_OPTION_OLD_INTERNALS +#ifdef FT_CONFIG_OPTION_OLD_INTERNALS FT_LOCAL( FT_Error ) tt_find_sbit_image( TT_Face face, FT_UInt glyph_index, diff --git a/src/sfnt/ttsbit0.c b/src/sfnt/ttsbit0.c index 37c7a9b..3ebcbbd 100644 --- a/src/sfnt/ttsbit0.c +++ b/src/sfnt/ttsbit0.c @@ -5,7 +5,7 @@ /* TrueType and OpenType embedded bitmap support (body). */ /* This is a heap-optimized version. */ /* */ -/* Copyright 2005, 2006, 2007, 2008 by */ +/* Copyright 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -39,65 +39,16 @@ #define FT_COMPONENT trace_ttsbit - static const FT_Frame_Field tt_sbit_line_metrics_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_SBit_LineMetricsRec - - /* no FT_FRAME_START */ - FT_FRAME_CHAR( ascender ), - FT_FRAME_CHAR( descender ), - FT_FRAME_BYTE( max_width ), - - FT_FRAME_CHAR( caret_slope_numerator ), - FT_FRAME_CHAR( caret_slope_denominator ), - FT_FRAME_CHAR( caret_offset ), - - FT_FRAME_CHAR( min_origin_SB ), - FT_FRAME_CHAR( min_advance_SB ), - FT_FRAME_CHAR( max_before_BL ), - FT_FRAME_CHAR( min_after_BL ), - FT_FRAME_CHAR( pads[0] ), - FT_FRAME_CHAR( pads[1] ), - FT_FRAME_END - }; - - static const FT_Frame_Field tt_strike_start_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_SBit_StrikeRec - - /* no FT_FRAME_START */ - FT_FRAME_ULONG( ranges_offset ), - FT_FRAME_SKIP_LONG, - FT_FRAME_ULONG( num_ranges ), - FT_FRAME_ULONG( color_ref ), - FT_FRAME_END - }; - - static const FT_Frame_Field tt_strike_end_fields[] = - { - /* no FT_FRAME_START */ - FT_FRAME_USHORT( start_glyph ), - FT_FRAME_USHORT( end_glyph ), - FT_FRAME_BYTE ( x_ppem ), - FT_FRAME_BYTE ( y_ppem ), - FT_FRAME_BYTE ( bit_depth ), - FT_FRAME_CHAR ( flags ), - FT_FRAME_END - }; - - FT_LOCAL_DEF( FT_Error ) tt_face_load_eblc( TT_Face face, FT_Stream stream ) { - FT_Error error = SFNT_Err_Ok; - FT_Fixed version; - FT_ULong num_strikes, table_size; - FT_Byte* p; - FT_Byte* p_limit; - FT_UInt count; + FT_Error error = SFNT_Err_Ok; + FT_Fixed version; + FT_ULong num_strikes, table_size; + FT_Byte* p; + FT_Byte* p_limit; + FT_UInt count; face->sbit_num_strikes = 0; @@ -111,7 +62,7 @@ if ( table_size < 8 ) { - FT_ERROR(( "%s: table too short!\n", "tt_face_load_sbit_strikes" )); + FT_ERROR(( "tt_face_load_sbit_strikes: table too short!\n" )); error = SFNT_Err_Invalid_File_Format; goto Exit; } @@ -129,8 +80,7 @@ if ( version != 0x00020000UL || num_strikes >= 0x10000UL ) { - FT_ERROR(( "%s: invalid table version!\n", - "tt_face_load_sbit_strikes" )); + FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version!\n" )); error = SFNT_Err_Invalid_File_Format; goto Fail; } @@ -182,7 +132,7 @@ FT_ULong strike_index, FT_Size_Metrics* metrics ) { - FT_Byte* strike; + FT_Byte* strike; if ( strike_index >= (FT_ULong)face->sbit_num_strikes ) @@ -374,14 +324,11 @@ if ( p + 5 > limit ) goto Fail; - if ( !decoder->metrics_loaded ) - { - metrics->height = p[0]; - metrics->width = p[1]; - metrics->horiBearingX = (FT_Char)p[2]; - metrics->horiBearingY = (FT_Char)p[3]; - metrics->horiAdvance = p[4]; - } + metrics->height = p[0]; + metrics->width = p[1]; + metrics->horiBearingX = (FT_Char)p[2]; + metrics->horiBearingY = (FT_Char)p[3]; + metrics->horiAdvance = p[4]; p += 5; if ( big ) @@ -389,19 +336,16 @@ if ( p + 3 > limit ) goto Fail; - if ( !decoder->metrics_loaded ) - { - metrics->vertBearingX = (FT_Char)p[0]; - metrics->vertBearingY = (FT_Char)p[1]; - metrics->vertAdvance = p[2]; - } + metrics->vertBearingX = (FT_Char)p[0]; + metrics->vertBearingY = (FT_Char)p[1]; + metrics->vertAdvance = p[2]; p += 3; } decoder->metrics_loaded = 1; *pp = p; - return 0; + return SFNT_Err_Ok; Fail: return SFNT_Err_Invalid_Argument; @@ -507,7 +451,7 @@ if ( w > 0 ) wval = (FT_UInt)( wval | ( *p++ & ( 0xFF00U >> w ) ) ); - /* all bits read and there are ( x_pos + w ) bits to be written */ + /* all bits read and there are `x_pos + w' bits to be written */ write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) ); @@ -587,7 +531,12 @@ { w = ( width < 8 - x_pos ) ? width : 8 - x_pos; - if ( nbits < w ) + if ( h == height ) + { + rval |= *p++; + nbits += x_pos; + } + else if ( nbits < w ) { rval |= *p++; nbits += 8 - w; @@ -598,7 +547,8 @@ nbits -= w; } - *write++ |= ( ( rval >> nbits ) & 0xFF ) & ~( 0xFF << w ); + *write++ |= ( ( rval >> nbits ) & 0xFF ) & + ( ~( 0xFF << w ) << ( 8 - w - x_pos ) ); rval <<= 8; w = width - w; @@ -645,6 +595,13 @@ FT_Error error = SFNT_Err_Ok; FT_UInt num_components, nn; + FT_Char horiBearingX = decoder->metrics->horiBearingX; + FT_Char horiBearingY = decoder->metrics->horiBearingY; + FT_Byte horiAdvance = decoder->metrics->horiAdvance; + FT_Char vertBearingX = decoder->metrics->vertBearingX; + FT_Char vertBearingY = decoder->metrics->vertBearingY; + FT_Byte vertAdvance = decoder->metrics->vertAdvance; + if ( p + 2 > limit ) goto Fail; @@ -653,6 +610,13 @@ if ( p + 4 * num_components > limit ) goto Fail; + if ( !decoder->bitmap_allocated ) + { + error = tt_sbit_decoder_alloc_bitmap( decoder ); + if ( error ) + goto Exit; + } + for ( nn = 0; nn < num_components; nn++ ) { FT_UInt gindex = FT_NEXT_USHORT( p ); @@ -667,6 +631,15 @@ break; } + decoder->metrics->horiBearingX = horiBearingX; + decoder->metrics->horiBearingY = horiBearingY; + decoder->metrics->horiAdvance = horiAdvance; + decoder->metrics->vertBearingX = vertBearingX; + decoder->metrics->vertBearingY = vertBearingY; + decoder->metrics->vertAdvance = vertAdvance; + decoder->metrics->width = (FT_UInt)decoder->bitmap->width; + decoder->metrics->height = (FT_UInt)decoder->bitmap->rows; + Exit: return error; |