diff --git a/ChangeLog b/ChangeLog index 5b2aa8f56..1d82f6467 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2003-10-22 Werner Lemberg + + * src/type1/t1load.c (parse_encoding): Handle `/Encoding [ ... ]'. + + * src/type1/t1parse.c (T1_Get_Private_Dict): Test whether `eexec' + is real. + + * src/type42/t42parse.c (t42_parse_encoding): Improve boundary + checking while parsing. + + * docs/CHANGES: Updated. + 2003-10-21 Josselin Mouette * include/freetype/internal/t1types.h (T1_FontRec): `paint_type' @@ -488,7 +500,7 @@ step towards a massive simplification of the engine's internals, in order to get rid of various numbers of hacks. - Note that this changes will break source & binary compatibility for + Note that these changes will break source & binary compatibility for authors of external font drivers. * include/freetype/config/ftconfig.h (FT_BEGIN_STMNT, FT_END_STMNT, diff --git a/docs/CHANGES b/docs/CHANGES index c95658c09..b404d9260 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -9,6 +9,15 @@ LATEST CHANGES BETWEEN 2.1.6 and 2.1.5 - Type 1 font files in binary format (PFB) with an end-of-file indicator weren't accepted by the FreeType engine. + - Fonts which contain /PaintType and /StrokeWidth no longer cause + a segfault. This bug has been introduced in version 2.1.5. + + - Fonts loaded with FT_LOAD_RENDER no longer cause strange + results. This bug has been introduced in version 2.1.5. + + - Some Windows (bitmap) FNT/FON files couldn't be handled + correctly. + II. IMPORTANT CHANGES - The internal module API has been heavily changed in favor of @@ -16,6 +25,10 @@ LATEST CHANGES BETWEEN 2.1.6 and 2.1.5 that authors of third-party modules must adapt their code to the new scheme. + - The PostScript parser has been enhanced to handle comments and + strings correctly. Additionally, more syntax forms are + recognized. + ===================================================================== @@ -39,14 +52,14 @@ LATEST CHANGES BETWEEN 2.1.5 and 2.1.4 longer overwritten. - The font matrix wasn't applied to the advance width for Type1, - CID, and CFF fonts. This caused problem when loading certain - synthetic Type 1 fonts like "Helvetica Narrow" + CID, and CFF fonts. This caused problems when loading certain + synthetic Type 1 fonts like `Helvetica Narrow'. - The test for the charset registry in BDF and PCF fonts is now case-insensitive. - - FT_Vector_Rotate rotating sometimes returned strange values due - to rounding errors. + - FT_Vector_Rotate sometimes returned strange values due to + rounding errors. - The PCF driver now returns the correct number of glyphs (including an artificial `notdef' glyph at index 0). diff --git a/src/type1/t1load.c b/src/type1/t1load.c index 0aee92efe..886e6cf89 100644 --- a/src/type1/t1load.c +++ b/src/type1/t1load.c @@ -884,19 +884,28 @@ return; } - /* if we have a number, then the encoding is an array, */ - /* and we must load it now */ - if ( ft_isdigit( *cur ) ) + /* if we have a number or `[', the encoding is an array, */ + /* and we must load it now */ + if ( ft_isdigit( *cur ) || *cur == '[' ) { - T1_Encoding encode = &face->type1.encoding; + T1_Encoding encode = &face->type1.encoding; FT_Int count, n; - PS_Table char_table = &loader->encoding_table; - FT_Memory memory = parser->root.memory; + PS_Table char_table = &loader->encoding_table; + FT_Memory memory = parser->root.memory; FT_Error error; + FT_Bool only_immediates = 0; /* read the number of entries in the encoding; should be 256 */ - count = (FT_Int)T1_ToInt( parser ); + if ( *cur == '[' ) + { + count = 256; + only_immediates = 1; + parser->root.cursor++; + } + else + count = (FT_Int)T1_ToInt( parser ); + T1_Skip_Spaces( parser ); if ( parser->root.cursor >= limit ) return; @@ -921,16 +930,25 @@ T1_Add_Table( char_table, n, notdef, 8 ); } - /* Now we need to read a record of the form */ - /* ... charcode /charname ... for each entry in our table */ + /* Now we need to read records of the form */ + /* */ + /* ... charcode /charname ... */ + /* */ + /* for each entry in our table. */ /* */ /* We simply look for a number followed by an immediate */ /* name. Note that this ignores correctly the sequence */ - /* that is often seen in Type 1 fonts: */ + /* that is often seen in type1 fonts: */ /* */ /* 0 1 255 { 1 index exch /.notdef put } for dup */ /* */ /* used to clean the encoding array before anything else. */ + /* */ + /* Alternatively, if the array is directly given as */ + /* */ + /* /Encoding [ ... ] */ + /* */ + /* we only read immediates. */ n = 0; T1_Skip_Spaces( parser ); @@ -939,7 +957,7 @@ { cur = parser->root.cursor; - /* we stop when we encounter a `def' */ + /* we stop when we encounter a `def' or `]' */ if ( *cur == 'd' && cur + 3 < limit ) { if ( cur[1] == 'e' && @@ -951,18 +969,30 @@ break; } } + if ( *cur == ']' ) + { + FT_TRACE6(( "encoding end\n" )); + cur++; + break; + } - /* otherwise, we must find a number before anything else */ - if ( ft_isdigit( *cur ) ) + /* check whether we've found an entry */ + if ( ft_isdigit( *cur ) || only_immediates ) { FT_Int charcode; - charcode = (FT_Int)T1_ToInt( parser ); - T1_Skip_Spaces( parser ); + if ( only_immediates ) + charcode = n; + else + { + charcode = (FT_Int)T1_ToInt( parser ); + T1_Skip_Spaces( parser ); + } + cur = parser->root.cursor; - if ( *cur == '/' && cur + 2 < limit ) + if ( *cur == '/' && cur + 2 < limit && n < count ) { FT_PtrDist len; @@ -979,6 +1009,8 @@ char_table->elements[charcode][len] = '\0'; if ( parser->root.error ) return; + + n++; } } else diff --git a/src/type1/t1parse.c b/src/type1/t1parse.c index 5a380632e..cc0c2f3d2 100644 --- a/src/type1/t1parse.c +++ b/src/type1/t1parse.c @@ -299,24 +299,18 @@ FT_Byte c; + Again: for (;;) { c = cur[0]; if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */ /* newline + 4 chars */ { - if ( cur[1] == 'e' && cur[2] == 'x' && - cur[3] == 'e' && cur[4] == 'c' ) - { - cur += 6; /* we skip the newline after the `eexec' */ - - /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */ - /* skip the extra \n if we find it */ - if ( cur[0] == '\n' ) - cur++; - + if ( cur[1] == 'e' && + cur[2] == 'x' && + cur[3] == 'e' && + cur[4] == 'c' ) break; - } } cur++; if ( cur >= limit ) @@ -328,10 +322,43 @@ } } + /* check whether `eexec' was real -- it could be in a comment */ + /* or string (as e.g. in u003043t.gsf from ghostscript) */ + + parser->root.cursor = parser->base_dict; + parser->root.limit = cur + 9; + + cur = parser->root.cursor; + limit = parser->root.limit; + + while ( cur < limit ) + { + if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 ) + goto Found; + + T1_Skip_PS_Token( parser ); + T1_Skip_Spaces ( parser ); + cur = parser->root.cursor; + } + + /* we haven't found the correct `eexec'; go back and continue */ + /* searching */ + + cur = limit; + limit = parser->base_dict + parser->base_len; + goto Again; + /* now determine where to write the _encrypted_ binary private */ /* dictionary. We overwrite the base dictionary for disk-based */ /* resources and allocate a new block otherwise */ + Found: + parser->root.limit = parser->base_dict + parser->base_len; + + T1_Skip_PS_Token( parser ); + T1_Skip_Spaces ( parser ); + cur = parser->root.cursor; + size = (FT_Long)( parser->base_len - ( cur - parser->base_dict ) ); if ( parser->in_memory ) diff --git a/src/type42/t42parse.c b/src/type42/t42parse.c index d22c6df09..20dcb90ed 100644 --- a/src/type42/t42parse.c +++ b/src/type42/t42parse.c @@ -288,7 +288,6 @@ T1_Skip_Spaces( parser ); cur = parser->root.cursor; - if ( cur >= limit ) { FT_ERROR(( "t42_parse_encoding: out of bounds!\n" )); @@ -363,10 +362,10 @@ /* we only read immediates. */ n = 0; + T1_Skip_Spaces( parser ); while ( parser->root.cursor < limit ) { - T1_Skip_Spaces( parser ); cur = parser->root.cursor; /* we stop when we encounter `def' or `]' */ @@ -427,6 +426,8 @@ } else T1_Skip_PS_Token( parser ); + + T1_Skip_Spaces( parser ); } face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;