From 229d122e928c5b5b6a1d4b613435695a2077c99a Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 25 Feb 2003 19:20:12 +0000 Subject: [PATCH] * src/gzip/ftgzip.c: fixed a bug that caused FreeType to loop endlessly when trying to read certain compressed gzip files. The following test could be used to reveal the bug: touch 0123456789 ; gzip 0123456789 ; ftdump 0123456789.gz * src/pfr/pfrobjs.c, src/pfr/pfrload.c, src/pfr/pfrtypes.h: several fixes to the PFR font driver: - the list of available embedded bitmaps was not correctly set in the root FT_FaceRec structure describing the face - the glyph loader always tried to load the outlines when FT_LOAD_SBITS_ONLY was specified - the table loaded now scans for *undocumented* elements of a physical font's auxiliary data record, this is necessary to retrieve the "real" family and style names. NOTE THAT THIS CHANGES THE FAMILY NAME OF MANY PFR FONTS !! --- ChangeLog | 26 +++++++++ src/gzip/ftgzip.c | 1 + src/pfr/pfrload.c | 134 +++++++++++++++++++++++++++++++++++++++++++-- src/pfr/pfrobjs.c | 45 ++++++++++++++- src/pfr/pfrtypes.h | 6 ++ 5 files changed, 204 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index eb03bf610..53da3db25 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2003-02-25 David Turner + + * src/gzip/ftgzip.c: fixed a bug that caused FreeType to loop endlessly + when trying to read certain compressed gzip files. The following test + could be used to reveal the bug: + + touch 0123456789 ; gzip 0123456789 ; ftdump 0123456789.gz + + + * src/pfr/pfrobjs.c, src/pfr/pfrload.c, src/pfr/pfrtypes.h: several + fixes to the PFR font driver: + + - the list of available embedded bitmaps was not correctly set + in the root FT_FaceRec structure describing the face + + - the glyph loader always tried to load the outlines when + FT_LOAD_SBITS_ONLY was specified + + - the table loaded now scans for *undocumented* elements of a + physical font's auxiliary data record, this is necessary to + retrieve the "real" family and style names. + + NOTE THAT THIS CHANGES THE FAMILY NAME OF MANY PFR FONTS !! + + + 2003-02-18 David Turner * src/truetype/ttdriver.c, src/truetype/ttobjs.h, src/truetype/ttobjs.c, diff --git a/src/gzip/ftgzip.c b/src/gzip/ftgzip.c index 768dcdc57..32c938cbf 100644 --- a/src/gzip/ftgzip.c +++ b/src/gzip/ftgzip.c @@ -376,6 +376,7 @@ if ( err == Z_STREAM_END ) { zip->limit = zstream->next_out; + error = FT_Err_Invalid_Stream_Operation; break; } else if ( err != Z_OK ) diff --git a/src/pfr/pfrload.c b/src/pfr/pfrload.c index 0cb32f4cf..1b81e652b 100644 --- a/src/pfr/pfrload.c +++ b/src/pfr/pfrload.c @@ -432,7 +432,16 @@ } - /* load font ID, i.e. name */ + /* load font ID, this is a so-called "unique" name that is rather + * long and descriptive (like "Tiresias ScreenFont v7.51"). + * + * note that a PFR font's family name is contained in an *undocumented* + * string of the "auxiliary data" portion of a physical font record. this + * may also contain the "real" style name ! + * + * if no family name is present, the font id is used instead for the + * family + */ FT_CALLBACK_DEF( FT_Error ) pfr_extra_item_load_font_id( FT_Byte* p, FT_Byte* limit, @@ -693,12 +702,54 @@ }; + /* loads a name from the auxiliary data. Since this extracts undocumented + * strings from the font file, we need to be careful here + */ + static FT_Error + pfr_aux_name_load( FT_Byte* p, + FT_UInt len, + FT_Memory memory, + FT_String* *astring ) + { + FT_Error error = 0; + FT_String* result = NULL; + FT_UInt n, ok; + + if ( len > 0 && p[len-1] == 0 ) + len--; + + /* check that each character is ASCII, that's to be sure + * to not load garbage.. + */ + ok = (len > 0); + for ( n = 0; n < len; n++ ) + if ( p[n] < 32 || p[n] > 127 ) + { + ok = 0; + break; + } + + if ( ok ) + { + if ( FT_ALLOC( result, len+1 ) ) + goto Exit; + + FT_MEM_COPY( result, p, len ); + result[len] = 0; + } + Exit: + *astring = result; + return error; + } + + FT_LOCAL_DEF( void ) pfr_phy_font_done( PFR_PhyFont phy_font, FT_Memory memory ) { - if ( phy_font->font_id ) - FT_FREE( phy_font->font_id ); + FT_FREE( phy_font->font_id ); + FT_FREE( phy_font->family_name ); + FT_FREE( phy_font->style_name ); FT_FREE( phy_font->vertical.stem_snaps ); phy_font->vertical.num_stem_snaps = 0; @@ -736,6 +787,7 @@ } + FT_LOCAL_DEF( FT_Error ) pfr_phy_font_load( PFR_PhyFont phy_font, FT_Stream stream, @@ -790,12 +842,82 @@ goto Fail; } - /* skip the aux bytes */ + /* in certain fonts, the auxiliary bytes contain interesting */ + /* information. These are not in the specification but can be */ + /* guessed by looking at the content of a few PFR0 fonts */ PFR_CHECK( 3 ); num_aux = PFR_NEXT_ULONG( p ); - PFR_CHECK( num_aux ); - p += num_aux; + if ( num_aux > 0 ) + { + FT_Byte* q = p; + FT_Byte* q2; + + PFR_CHECK( num_aux ); + p += num_aux; + + while ( num_aux >= 0 ) + { + FT_UInt length, type; + + if ( q + 4 > p ) + break; + + length = PFR_NEXT_USHORT(q); + if ( length < 4 || length > num_aux ) + break; + + q2 = q + length - 2; + type = PFR_NEXT_USHORT(q); + + switch ( type ) + { + case 1: + { + /* this seems to correspond to the font's family name, + * padded to 16-bits with one zero when necessary + */ + error = pfr_aux_name_load( q, length-4U, memory, + &phy_font->family_name ); + if ( error ) + goto Exit; + } + break; + + case 2: + { + if ( q + 32 > q2 ) + break; + + q += 10; + phy_font->ascent = PFR_NEXT_SHORT(q); + phy_font->descent = PFR_NEXT_SHORT(q); + phy_font->leading = PFR_NEXT_SHORT(q); + q += 16; + } + break; + + case 3: + { + FT_UInt n, len, ok; + + /* this seems to correspond to the font's style name, + * padded to 16-bits with one zero when necessary + */ + error = pfr_aux_name_load( q, length-4U, memory, + &phy_font->style_name ); + if ( error ) + goto Exit; + } + break; + + default: + ; + } + q = q2; + num_aux -= length; + } + } /* read the blue values */ { diff --git a/src/pfr/pfrobjs.c b/src/pfr/pfrobjs.c index 8ede63a95..202184838 100644 --- a/src/pfr/pfrobjs.c +++ b/src/pfr/pfrobjs.c @@ -41,6 +41,10 @@ FT_LOCAL_DEF( void ) pfr_face_done( PFR_Face face ) { + /* we don't want dangling pointers */ + face->root.family_name = NULL; + face->root.style_name = NULL; + /* finalize the physical font record */ pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) ); @@ -136,8 +140,18 @@ if ( phy_font->num_kern_pairs > 0 ) root->face_flags |= FT_FACE_FLAG_KERNING; - root->family_name = phy_font->font_id; - root->style_name = NULL; /* no style name in font file */ + /* if no family name was found in the "undocumented" auxiliary + * data, use the font ID instead. This sucks but is better than + * nothing + */ + root->family_name = phy_font->family_name; + if ( root->family_name == NULL ) + root->family_name = phy_font->font_id; + + /* note that the style name can be NULL in certain PFR fonts, + * probably meaning "Regular" + */ + root->style_name = phy_font->style_name; root->num_fixed_sizes = 0; root->available_sizes = 0; @@ -150,6 +164,27 @@ ( ( ( root->ascender - root->descender ) * 12 ) / 10 ); + if ( phy_font->num_strikes > 0 ) + { + FT_UInt n, count = phy_font->num_strikes; + FT_Bitmap_Size* size; + PFR_Strike strike; + FT_Memory memory = root->stream->memory; + + + if ( FT_NEW_ARRAY( root->available_sizes, count ) ) + goto Exit; + + size = root->available_sizes; + strike = phy_font->strikes; + for ( n = 0; n < count; n++, size++, strike++ ) + { + size->height = strike->y_ppm; + size->width = strike->x_ppm; + } + root->num_fixed_sizes = count; + } + /* now compute maximum advance width */ if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 ) root->max_advance_width = (FT_Short)phy_font->standard_advance; @@ -255,6 +290,12 @@ goto Exit; } + if ( load_flags & FT_LOAD_SBITS_ONLY ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + gchar = face->phy_font.chars + gindex; slot->root.format = FT_GLYPH_FORMAT_OUTLINE; outline->n_points = 0; diff --git a/src/pfr/pfrtypes.h b/src/pfr/pfrtypes.h index 3b419da5d..96744fc65 100644 --- a/src/pfr/pfrtypes.h +++ b/src/pfr/pfrtypes.h @@ -230,11 +230,17 @@ FT_BEGIN_HEADER FT_BBox bbox; FT_UInt flags; FT_UInt standard_advance; + + FT_Int ascent; /* optional, bbox.yMax if not present */ + FT_Int descent; /* optional, bbox.yMin if not present */ + FT_Int leading; /* optional, 0 if not present */ PFR_DimensionRec horizontal; PFR_DimensionRec vertical; FT_String* font_id; + FT_String* family_name; + FT_String* style_name; FT_UInt num_strikes; FT_UInt max_strikes;