ref: 52f911a12d1c552b9fad3a2fb33b9e04ff2d92ee
parent: d0cb15f1dba1e33d29bf756cee60095af519f8c0
author: Werner Lemberg <[email protected]>
date: Tue Oct 7 01:49:41 EDT 2003
Heavy modification of the PS parser to handle comments and strings correctly. This doesn't slow down the loading of PS fonts significantly since charstrings aren't affected. * include/freetype/config/ftstdlib.h (ft_xdigit): Renamed to... (ft_isxdigit): This. Updated all callers. (ft_isdigit): New alias to `isdigit'. * include/freetype/internal/psaux.h (PS_Parser_FuncsRec): Renamed `skip_alpha' to `skip_PS_token'. Add parameter to `to_bytes' and change some argument types. * src/psaux/psauxmod.c (ps_parser_funcs): Updated. * src/psaux/psobjs.c (ft_char_table): New array to map character codes (ASCII and EBCDIC) of digits to numbers. (OP): New auxiliary macro holding either `>=' or `<' depending on the character encoding. (skip_comment): New function. (skip_spaces): Use it. (skip_alpha): Removed. (skip_literal_string, skip_string): New functions. (ps_parser_skip_PS_token): New function. This is a better replacement of... (ps_parser_skip_alpha): Removed. (ps_parser_to_token, ps+parser_to_token_array): Updated. (T1Radix): Rewritten, using `ft_char_table'. (t1_toint): Renamed to... (ps_toint): This. Update all callers. Use `ft_char_table'. (ps_tobytes): Add parameter to handle delimiters and change some argument types. Use `ft_char_table'. (t1_tofixed): Renamed to... (ps_tofixed): This. Update all callers. Use `ft_char_table'. (t1_tocoordarray): Renamed and updated to... (ps_tocoordarray): This. Update all callers. (t1_tofixedarray): Renamed and updated to... (ps_tofixedarray): This. Update all callers. (t1_tobool): Renamed to... (ps_tobool): This. Update all callers. (ps_parser_load_field): Updated. (ps_parser_load_field_table): Use `T1_MAX_TABLE_ELEMENTS' everywhere. (ps_parser_to_int, ps_parser_to_fixed, ps_parser_to_coord_array, ps_parser_to_fixed_array): Skip spaces. Updated. (ps_parser_to_bytes): Add parameter to handle delimiters and change some argument types. Updated. * src/psaux/psobjs.h: Updated. * src/cid/cidload.c (cid_parse_dict): Updated. * src/cid/cidparse.c (cid_parser_new): Check whether the `StartData' token was really found. * src/cid/cidparse.h (cid_parser_skip_alpha): Updated and renamed to... (cid_parser_skip_PS_token): This. * src/type1/t1parse.h (T1_ParserRec): Use `FT_Bool' for boolean fields. (T1_Skip_Alpha): Replaced with... (T1_Skip_PS_Token): This new macro. * src/type1/t1parse.c (hexa_value): Removed. (T1_Get_Private_Dict): Use `ft_isxdigit' and `psaux->ps_parser_funcs_to_bytes' for handling ASCII hexadecimal encoding. After decrypting, replace the four random bytes at the beginning with whitespace. * src/type1/t1load.c (t1_allocate_blend): Use proper error values. (parser_blend_design_positions, parse_blend_design_map, parse_weight_vector): Updated. (is_space): Handle `\f' also. (is_name_char): Removed. (read_binary_data): Updated. (parse_encoding): Use `ft_isdigit'. Updated. (parse_subrs): Updated. (TABLE_EXTEND): New macro. (parse_charstrings): Updated. Provide a workaround for buggy fonts which have more entries in the /CharStrings dictionary then expected; the function now adds some slots and skips entries which still exceed the new limit. (parse_dict): Updated. Terminate on the token `closefile'. * src/type42/t42parse.c (T1_Skip_Alpha): Replaced with... (T1_Skip_PS_Token): This new macro. Updated all callers. (t42_parse_encoding): Use `ft_isdigit'. * src/base/ftmm.c (ft_face_get_mm_service): Return FT_Err_OK if success.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,97 @@
+2003-10-06 Werner Lemberg <[email protected]>
+
+ Heavy modification of the PS parser to handle comments and strings
+ correctly. This doesn't slow down the loading of PS fonts
+ significantly since charstrings aren't affected.
+
+ * include/freetype/config/ftstdlib.h (ft_xdigit): Renamed to...
+ (ft_isxdigit): This. Updated all callers.
+ (ft_isdigit): New alias to `isdigit'.
+
+ * include/freetype/internal/psaux.h (PS_Parser_FuncsRec): Renamed
+ `skip_alpha' to `skip_PS_token'.
+ Add parameter to `to_bytes' and change some argument types.
+
+ * src/psaux/psauxmod.c (ps_parser_funcs): Updated.
+ * src/psaux/psobjs.c (ft_char_table): New array to map character
+ codes (ASCII and EBCDIC) of digits to numbers.
+ (OP): New auxiliary macro holding either `>=' or `<' depending on
+ the character encoding.
+ (skip_comment): New function.
+ (skip_spaces): Use it.
+ (skip_alpha): Removed.
+ (skip_literal_string, skip_string): New functions.
+ (ps_parser_skip_PS_token): New function. This is a better
+ replacement of...
+ (ps_parser_skip_alpha): Removed.
+ (ps_parser_to_token, ps+parser_to_token_array): Updated.
+ (T1Radix): Rewritten, using `ft_char_table'.
+ (t1_toint): Renamed to...
+ (ps_toint): This. Update all callers.
+ Use `ft_char_table'.
+ (ps_tobytes): Add parameter to handle delimiters and change some
+ argument types.
+ Use `ft_char_table'.
+ (t1_tofixed): Renamed to...
+ (ps_tofixed): This. Update all callers.
+ Use `ft_char_table'.
+ (t1_tocoordarray): Renamed and updated to...
+ (ps_tocoordarray): This. Update all callers.
+ (t1_tofixedarray): Renamed and updated to...
+ (ps_tofixedarray): This. Update all callers.
+ (t1_tobool): Renamed to...
+ (ps_tobool): This. Update all callers.
+ (ps_parser_load_field): Updated.
+ (ps_parser_load_field_table): Use `T1_MAX_TABLE_ELEMENTS'
+ everywhere.
+ (ps_parser_to_int, ps_parser_to_fixed, ps_parser_to_coord_array,
+ ps_parser_to_fixed_array): Skip spaces. Updated.
+ (ps_parser_to_bytes): Add parameter to handle delimiters and change
+ some argument types. Updated.
+ * src/psaux/psobjs.h: Updated.
+
+ * src/cid/cidload.c (cid_parse_dict): Updated.
+ * src/cid/cidparse.c (cid_parser_new): Check whether the `StartData'
+ token was really found.
+ * src/cid/cidparse.h (cid_parser_skip_alpha): Updated and renamed
+ to...
+ (cid_parser_skip_PS_token): This.
+
+ * src/type1/t1parse.h (T1_ParserRec): Use `FT_Bool' for boolean
+ fields.
+ (T1_Skip_Alpha): Replaced with...
+ (T1_Skip_PS_Token): This new macro.
+ * src/type1/t1parse.c (hexa_value): Removed.
+ (T1_Get_Private_Dict): Use `ft_isxdigit' and
+ `psaux->ps_parser_funcs_to_bytes' for handling ASCII hexadecimal
+ encoding.
+ After decrypting, replace the four random bytes at the beginning
+ with whitespace.
+ * src/type1/t1load.c (t1_allocate_blend): Use proper error values.
+ (parser_blend_design_positions, parse_blend_design_map,
+ parse_weight_vector): Updated.
+ (is_space): Handle `\f' also.
+ (is_name_char): Removed.
+ (read_binary_data): Updated.
+ (parse_encoding): Use `ft_isdigit'.
+ Updated.
+ (parse_subrs): Updated.
+ (TABLE_EXTEND): New macro.
+ (parse_charstrings): Updated.
+ Provide a workaround for buggy fonts which have more entries in the
+ /CharStrings dictionary then expected; the function now adds some
+ slots and skips entries which still exceed the new limit.
+ (parse_dict): Updated.
+ Terminate on the token `closefile'.
+
+ * src/type42/t42parse.c (T1_Skip_Alpha): Replaced with...
+ (T1_Skip_PS_Token): This new macro. Updated all callers.
+ (t42_parse_encoding): Use `ft_isdigit'.
+
+
+ * src/base/ftmm.c (ft_face_get_mm_service): Return FT_Err_OK if
+ success.
+
2003-10-05 Werner Lemberg <[email protected]>
* include/freetype/ftmodule.h: Renamed to...
--- a/include/freetype/config/ftstdlib.h
+++ b/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
/* ANSI-specific library and header configuration file (specification */
/* only). */
/* */
-/* Copyright 2002 by */
+/* Copyright 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -73,10 +73,11 @@
#include <ctype.h>
-#define ft_isalnum isalnum
-#define ft_isupper isupper
-#define ft_islower islower
-#define ft_xdigit isxdigit
+#define ft_isalnum isalnum
+#define ft_isupper isupper
+#define ft_islower islower
+#define ft_isdigit isdigit
+#define ft_isxdigit isxdigit
#include <string.h>
--- a/include/freetype/ftoutln.h
+++ b/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
/* Support for the FT_Outline type used to store glyph shapes of */
/* most scalable font formats (specification). */
/* */
-/* Copyright 1996-2001, 2002 by */
+/* Copyright 1996-2001, 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -391,32 +391,33 @@
/**************************************************************************
*
- * @enum: FT_Orientation
+ * @enum:
+ * FT_Orientation
*
* @description:
- * a list of values used to describe an outline's contour orientation
+ * A list of values used to describe an outline's contour orientation.
*
- * The TrueType and Postscript specifications used different conventions
- * to determine wether outline contours should be filled or unfilled.
+ * The TrueType and Postscript specifications use different conventions
+ * to determine whether outline contours should be filled or unfilled.
*
* @values:
* FT_ORIENTATION_TRUETYPE ::
- * according to the TrueType specification, clockwise contours must
- * be filled, and counter-clockwise ones must be unfilled
+ * According to the TrueType specification, clockwise contours must
+ * be filled, and counter-clockwise ones must be unfilled.
*
* FT_ORIENTATION_POSTSCRIPT ::
- * according to the Postscript specification, counter-clockwise contours
- * must be filled, and clockwise ones must be unfilled
+ * According to the Postscript specification, counter-clockwise contours
+ * must be filled, and clockwise ones must be unfilled.
*
* FT_ORIENTATION_FILL_RIGHT ::
- * this is identical to @FT_ORIENTATION_TRUETYPE, but is used to
+ * This is identical to @FT_ORIENTATION_TRUETYPE, but is used to
* remember that in TrueType, everything that is to the right of
* the drawing direction of a contour must be filled.
*
* FT_ORIENTATION_FILL_LEFT ::
- * this is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to
+ * This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to
* remember that in Postscript, everything that is to the left of
- * the drawing direction of a contour must be filled
+ * the drawing direction of a contour must be filled.
*/
typedef enum
{
@@ -430,22 +431,24 @@
/**************************************************************************
*
- * @function: FT_Outline_Get_Orientation
+ * @function:
+ * FT_Outline_Get_Orientation
*
* @description:
- * this function analyzes a glyph outline and tries to compute its
- * fill orientation (see @FT_Orientation). This is done by computing
+ * This function analyzes a glyph outline and tries to compute its
+ * fill orientation (see @FT_Orientation). This is done by computing
* the direction of each global horizontal and/or vertical extrema
* within the outline.
*
- * note that this will return @FT_ORIENTATION_TRUETYPE for empty
+ * Note that this will return @FT_ORIENTATION_TRUETYPE for empty
* outlines.
*
* @input:
- * outline :: handle to source outline
+ * outline ::
+ * A handle to the source outline.
*
* @return:
- * orientation
+ * The orientation.
*
*/
FT_EXPORT( FT_Orientation )
--- a/include/freetype/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
@@ -330,7 +330,7 @@
void
(*skip_spaces)( PS_Parser parser );
void
- (*skip_alpha)( PS_Parser parser );
+ (*skip_PS_token)( PS_Parser parser );
FT_Long
(*to_int)( PS_Parser parser );
@@ -337,11 +337,13 @@
FT_Fixed
(*to_fixed)( PS_Parser parser,
FT_Int power_ten );
+
FT_Error
(*to_bytes)( PS_Parser parser,
FT_Byte* bytes,
- FT_Int max_bytes,
- FT_Int* pnum_bytes );
+ FT_Long max_bytes,
+ FT_Long* pnum_bytes,
+ FT_Bool delimiters );
FT_Int
(*to_coord_array)( PS_Parser parser,
--- a/src/base/ftmm.c
+++ b/src/base/ftmm.c
@@ -51,6 +51,9 @@
FT_FACE_LOOKUP_SERVICE( face,
*aservice,
MULTI_MASTERS );
+
+ if ( aservice )
+ error = FT_Err_Ok;
}
return error;
--- a/src/base/ftpfr.c
+++ b/src/base/ftpfr.c
@@ -26,6 +26,7 @@
{
FT_Service_PfrMetrics service;
+
FT_FACE_LOOKUP_SERVICE( face, service, PFR_METRICS );
return service;
--- a/src/cid/cidload.c
+++ b/src/cid/cidload.c
@@ -39,7 +39,7 @@
/* read a single offset */
FT_LOCAL_DEF( FT_Long )
- cid_get_offset( FT_Byte** start,
+ cid_get_offset( FT_Byte* *start,
FT_Byte offsize )
{
FT_Long result;
@@ -164,9 +164,9 @@
temp_scale = ABS( temp[3] );
- /* Set Units per EM based on FontMatrix values. We set the value to */
+ /* Set units per EM based on FontMatrix values. We set the value to */
/* `1000/temp_scale', because temp_scale was already multiplied by */
- /* 1000 (in t1_tofixed(), from psobjs.c). */
+ /* 1000 (in `t1_tofixed', from psobjs.c). */
root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L,
FT_DivFix( temp_scale, 1000 ) ) );
@@ -258,7 +258,7 @@
parser->root.cursor = base;
parser->root.limit = base + size;
- parser->root.error = 0;
+ parser->root.error = CID_Err_Ok;
{
FT_Byte* cur = base;
@@ -265,31 +265,50 @@
FT_Byte* limit = cur + size;
- for ( ; cur < limit; cur++ )
+ for (;;)
{
+ FT_Byte* newlimit;
+
+
+ parser->root.cursor = cur;
+ cid_parser_skip_spaces( parser );
+
+ if ( parser->root.cursor >= limit )
+ newlimit = limit - 1 - 17;
+ else
+ newlimit = parser->root.cursor - 17;
+
/* look for `%ADOBeginFontDict' */
- if ( *cur == '%' && cur + 20 < limit &&
- ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
+ for ( ; cur < newlimit; cur++ )
{
- cur += 17;
-
- /* if /FDArray was found, then cid->num_dicts is > 0, and */
- /* we can start increasing parser->num_dict */
- if ( face->cid.num_dicts > 0 )
- parser->num_dict++;
+ if ( *cur == '%' &&
+ ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
+ {
+ /* if /FDArray was found, then cid->num_dicts is > 0, and */
+ /* we can start increasing parser->num_dict */
+ if ( face->cid.num_dicts > 0 )
+ parser->num_dict++;
+ }
}
+
+ cur = parser->root.cursor;
+ /* no error can occur in cid_parser_skip_spaces */
+ if ( cur >= limit )
+ break;
+
+ cid_parser_skip_PS_token( parser );
+ if ( parser->root.cursor >= limit || parser->root.error )
+ break;
+
/* look for immediates */
- else if ( *cur == '/' && cur + 2 < limit )
+ if ( *cur == '/' && cur + 2 < limit )
{
FT_PtrDist len;
cur++;
-
- parser->root.cursor = cur;
- cid_parser_skip_alpha( parser );
-
len = parser->root.cursor - cur;
+
if ( len > 0 && len < 22 )
{
/* now compare the immediate name to the keyword table */
@@ -303,10 +322,7 @@
name = (FT_Byte*)keyword->ident;
if ( !name )
- {
- cid_parser_skip_alpha( parser );
break;
- }
if ( cur[0] == name[0] &&
len == ft_strlen( (const char*)name ) )
@@ -321,14 +337,11 @@
if ( n >= len )
{
/* we found it - run the parsing callback */
- cid_parser_skip_spaces( parser );
parser->root.error = cid_load_keyword( face,
loader,
keyword );
if ( parser->root.error )
return parser->root.error;
-
- cur = parser->root.cursor;
break;
}
}
@@ -336,6 +349,8 @@
}
}
}
+
+ cur = parser->root.cursor;
}
}
return parser->root.error;
--- a/src/cid/cidparse.c
+++ b/src/cid/cidparse.c
@@ -4,7 +4,7 @@
/* */
/* CID-keyed Type1 parser (body). */
/* */
-/* Copyright 1996-2001, 2002 by */
+/* Copyright 1996-2001, 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -58,6 +58,7 @@
FT_ULong base_offset, offset, ps_len;
FT_Byte buffer[256 + 10];
FT_Int buff_len;
+ FT_Byte *cur, *limit;
FT_MEM_ZERO( parser, sizeof ( *parser ) );
@@ -67,7 +68,7 @@
base_offset = FT_STREAM_POS();
- /* first of all, check the font format in the header */
+ /* first of all, check the font format in the header */
if ( FT_FRAME_ENTER( 31 ) )
goto Exit;
@@ -82,15 +83,17 @@
if ( error )
goto Exit;
- /* now, read the rest of the file, until we find a `StartData' */
+ Again:
+ /* now, read the rest of the file until we find a `StartData' */
buff_len = 256;
for (;;)
{
- FT_Byte *p, *limit = buffer + 256;
+ FT_Byte* p;
FT_ULong top_position;
/* fill input buffer */
+ limit = buffer + 256;
buff_len -= 256;
if ( buff_len > 0 )
FT_MEM_MOVE( buffer, limit, buff_len );
@@ -101,7 +104,7 @@
goto Exit;
top_position = FT_STREAM_POS() - buff_len;
- buff_len = 256 + 10;
+ buff_len = 256 + 10;
/* look for `StartData' */
for ( p = buffer; p < limit; p++ )
@@ -116,12 +119,12 @@
}
Found:
- /* we have found the start of the binary data. We will now */
- /* rewind and extract the frame of corresponding to the Postscript */
- /* section */
+ /* we have found the start of the binary data. We will now */
+ /* rewind and extract the frame corresponding to the PostScript */
+ /* section */
ps_len = offset - base_offset;
- if ( FT_STREAM_SEEK( base_offset ) ||
+ if ( FT_STREAM_SEEK( base_offset ) ||
FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
goto Exit;
@@ -131,6 +134,32 @@
parser->root.cursor = parser->postscript;
parser->root.limit = parser->root.cursor + ps_len;
parser->num_dict = -1;
+
+ /* finally we check whether `StartData' was real -- it could be */
+ /* in a comment or string */
+
+ limit = parser->root.limit;
+ cur = parser->root.cursor;
+
+ while ( cur < limit )
+ {
+ if ( *cur == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 )
+ {
+ limit = parser->root.limit;
+ cur = parser->root.cursor;
+ goto Exit;
+ }
+
+ cid_parser_skip_PS_token( parser );
+ cid_parser_skip_spaces ( parser );
+ cur = parser->root.cursor;
+ }
+
+ /* we haven't found the correct `StartData'; go back and continue */
+ /* searching */
+ FT_FRAME_RELEASE( parser->postscript );
+ if ( !FT_STREAM_SEEK( offset ) )
+ goto Again;
Exit:
return error;
--- a/src/cid/cidparse.h
+++ b/src/cid/cidparse.h
@@ -4,7 +4,7 @@
/* */
/* CID-keyed Type1 parser (specification). */
/* */
-/* Copyright 1996-2001, 2002 by */
+/* Copyright 1996-2001, 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -87,8 +87,10 @@
/* */
/*************************************************************************/
-#define cid_parser_skip_spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
-#define cid_parser_skip_alpha( p ) (p)->root.funcs.skip_alpha ( &(p)->root )
+#define cid_parser_skip_spaces( p ) \
+ (p)->root.funcs.skip_spaces( &(p)->root )
+#define cid_parser_skip_PS_token( p ) \
+ (p)->root.funcs.skip_PS_token( &(p)->root )
#define cid_parser_to_int( p ) (p)->root.funcs.to_int( &(p)->root )
#define cid_parser_to_fixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )
--- a/src/psaux/psauxmod.c
+++ b/src/psaux/psauxmod.c
@@ -39,7 +39,7 @@
ps_parser_init,
ps_parser_done,
ps_parser_skip_spaces,
- ps_parser_skip_alpha,
+ ps_parser_skip_PS_token,
ps_parser_to_int,
ps_parser_to_fixed,
ps_parser_to_bytes,
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -267,31 +267,76 @@
/*************************************************************************/
/* In the PostScript Language Reference Manual (PLRM) the following */
- /* characters are called `white-space characters'. */
+ /* characters are called `whitespace characters'. */
#define IS_T1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' )
#define IS_T1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' || (c) == '\f' )
#define IS_T1_NULLSPACE( c ) ( (c) == '\0' )
- /* According to the PLRM all white-space characters are equivalent, */
- /* except in comments and strings. */
+ /* According to the PLRM all whitespace characters are equivalent, */
+ /* except in comments and strings. */
#define IS_T1_SPACE( c ) ( IS_T1_WHITESPACE( c ) || \
IS_T1_LINESPACE( c ) || \
IS_T1_NULLSPACE( c ) )
+ /* The following array is used by various functions to quickly convert */
+ /* digits (both decimal and non-decimal) into numbers. */
+
+#if 'A' == 65
+ /* ASCII */
+
+ char ft_char_table[128] =
+ {
+ /* 0x00 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+ };
+
+ /* no character >= 0x80 can represent a valid number */
+#define OP >=
+
+#endif /* 'A' == 65 */
+
+#if 'A' == 193
+ /* EBCDIC */
+
+ char ft_char_table[128] =
+ {
+ /* 0x80 */
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
+ -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
+ -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
+ -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
+ -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+ }
+
+ /* no character < 0x80 can represent a valid number */
+#define OP <
+
+#endif /* 'A' == 193 */
+
+
+ /* first character must be already part of the comment */
+
static void
- skip_spaces( FT_Byte** acur,
- FT_Byte* limit )
+ skip_comment( FT_Byte* *acur,
+ FT_Byte* limit )
{
- FT_Byte* cur = *acur;
+ FT_Byte* cur = *acur;
while ( cur < limit )
{
- FT_Byte c = *cur;
-
-
- if ( !IS_T1_SPACE( c ) )
+ if ( IS_T1_LINESPACE( *cur ) )
break;
cur++;
}
@@ -301,8 +346,8 @@
static void
- skip_alpha( FT_Byte** acur,
- FT_Byte* limit )
+ skip_spaces( FT_Byte* *acur,
+ FT_Byte* limit )
{
FT_Byte* cur = *acur;
@@ -309,11 +354,46 @@
while ( cur < limit )
{
- FT_Byte c = *cur;
+ if ( !IS_T1_SPACE( *cur ) )
+ {
+ if ( *cur == '%' )
+ /* According to the PLRM, a comment is equal to a space. */
+ skip_comment( &cur, limit );
+ else
+ break;
+ }
+ cur++;
+ }
+ *acur = cur;
+ }
- if ( IS_T1_SPACE( c ) )
- break;
+
+ /* first character must be `(' */
+
+ static void
+ skip_literal_string( FT_Byte* *acur,
+ FT_Byte* limit )
+ {
+ FT_Byte* cur = *acur;
+ FT_Int embed = 0;
+
+
+ while ( cur < limit )
+ {
+ if ( *cur == '\\' )
+ cur++;
+ else if ( *cur == '(' )
+ embed++;
+ else if ( *cur == ')' )
+ {
+ embed--;
+ if ( embed == 0 )
+ {
+ cur++;
+ break;
+ }
+ }
cur++;
}
@@ -321,20 +401,145 @@
}
+ /* first character must be `<' */
+
+ static void
+ skip_string( PS_Parser parser )
+ {
+ FT_Byte* cur = parser->cursor;
+ FT_Byte* limit = parser->limit;
+
+
+ cur++;
+
+ while ( cur < limit )
+ {
+ int d;
+
+
+ /* All whitespace characters are ignored. */
+ skip_spaces( &cur, limit );
+ if ( cur >= limit )
+ break;
+
+ if ( *cur OP 0x80 )
+ break;
+
+ d = ft_char_table[*cur & 0x7F];
+ if ( d < 0 || d >= 16 )
+ break;
+ }
+
+ if ( cur < limit && *cur != '>' )
+ parser->error = PSaux_Err_Invalid_File_Format;
+ else
+ cur++;
+
+ parser->cursor = cur;
+ }
+
+
+ /***********************************************************************/
+ /* */
+ /* All exported parsing routines handle leading whitespace and stop at */
+ /* the first character which isn't part of the just handled token. */
+ /* */
+ /***********************************************************************/
+
+
FT_LOCAL_DEF( void )
- ps_parser_skip_spaces( PS_Parser parser )
+ ps_parser_skip_PS_token( PS_Parser parser )
{
- skip_spaces( &parser->cursor, parser->limit );
+ /* Note: PostScript allows any non-delimiting, non-whitespace */
+ /* character in a name (PS Ref Manual, 3rd ed, p31). */
+ /* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */
+
+ FT_Byte* cur = parser->cursor;
+ FT_Byte* limit = parser->limit;
+
+
+ skip_spaces( &cur, limit ); /* this also skips comments */
+ if ( cur >= limit )
+ goto Exit;
+
+ /* self-delimiting, single-character tokens */
+ if ( *cur == '[' || *cur == ']' ||
+ *cur == '{' || *cur == '}' )
+ {
+ cur++;
+ goto Exit;
+ }
+
+ if ( *cur == '(' ) /* (...) */
+ {
+ skip_literal_string( &cur, limit );
+ goto Exit;
+ }
+
+ if ( *cur == '<' ) /* <...> */
+ {
+ if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */
+ {
+ cur++;
+ cur++;
+ goto Exit;
+ }
+ parser->cursor = cur;
+ skip_string( parser );
+ return;
+ }
+
+ if ( *cur == '>' )
+ {
+ cur++;
+ if ( cur >= limit || *cur != '>' ) /* >> */
+ {
+ parser->error = PSaux_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ cur++;
+ goto Exit;
+ }
+
+ if ( *cur == '/' )
+ cur++;
+
+ /* anything else */
+ while ( cur < limit )
+ {
+ if ( IS_T1_SPACE( *cur ) ||
+ *cur == '(' ||
+ *cur == '/' ||
+ *cur == '%' ||
+ *cur == '[' || *cur == ']' ||
+ *cur == '{' || *cur == '}' ||
+ *cur == '<' || *cur == '>' )
+ break;
+
+ if ( *cur == ')' )
+ {
+ parser->error = PSaux_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ cur++;
+ }
+
+ Exit:
+ parser->cursor = cur;
}
FT_LOCAL_DEF( void )
- ps_parser_skip_alpha( PS_Parser parser )
+ ps_parser_skip_spaces( PS_Parser parser )
{
- skip_alpha( &parser->cursor, parser->limit );
+ skip_spaces( &parser->cursor, parser->limit );
}
+ /* `token' here means either something between balanced delimiters */
+ /* or the next token; the delimiters are not removed. */
+
FT_LOCAL_DEF( void )
ps_parser_to_token( PS_Parser parser,
T1_Token token )
@@ -349,72 +554,87 @@
token->start = 0;
token->limit = 0;
- /* first of all, skip space */
+ /* first of all, skip leading whitespace */
ps_parser_skip_spaces( parser );
cur = parser->cursor;
limit = parser->limit;
- if ( cur < limit )
+ if ( cur >= limit )
+ return;
+
+ switch ( *cur )
{
- switch ( *cur )
- {
- /************* check for strings ***********************/
- case '(':
- token->type = T1_TOKEN_TYPE_STRING;
- ender = ')';
- goto Lookup_Ender;
+ /************* check for literal string *****************/
+ case '(':
+ token->type = T1_TOKEN_TYPE_STRING;
+ token->start = cur;
+ skip_literal_string( &cur, limit );
+ if ( cur < limit )
+ token->limit = cur;
+ break;
- /************* check for programs/array ****************/
- case '{':
- token->type = T1_TOKEN_TYPE_ARRAY;
- ender = '}';
- goto Lookup_Ender;
+ /************* check for programs/array *****************/
+ case '{':
+ token->type = T1_TOKEN_TYPE_ARRAY;
+ ender = '}';
+ goto Lookup_Ender;
- /************* check for table/array ******************/
- case '[':
- token->type = T1_TOKEN_TYPE_ARRAY;
- ender = ']';
+ /************* check for table/array ********************/
+ case '[':
+ token->type = T1_TOKEN_TYPE_ARRAY;
+ ender = ']';
+ /* fall through */
- Lookup_Ender:
- embed = 1;
- starter = *cur++;
- token->start = cur;
- while ( cur < limit )
+ Lookup_Ender:
+ embed = 1;
+ starter = *cur;
+ token->start = cur++;
+
+ /* we need this to catch `[ ]' */
+ parser->cursor = cur;
+ ps_parser_skip_spaces( parser );
+ cur = parser->cursor;
+
+ while ( cur < limit && !parser->error )
+ {
+ if ( *cur == starter )
+ embed++;
+ else if ( *cur == ender )
{
- if ( *cur == starter )
- embed++;
- else if ( *cur == ender )
+ embed--;
+ if ( embed <= 0 )
{
- embed--;
- if ( embed <= 0 )
- {
- token->limit = cur++;
- break;
- }
+ token->limit = ++cur;
+ break;
}
- cur++;
}
- break;
- /* **************** otherwise, it's any token **********/
- default:
- token->start = cur++;
- token->type = T1_TOKEN_TYPE_ANY;
- while ( cur < limit && !IS_T1_SPACE( *cur ) )
- cur++;
+ parser->cursor = cur;
+ ps_parser_skip_PS_token( parser );
+ /* we need this to catch `[XXX ]' */
+ ps_parser_skip_spaces ( parser );
+ cur = parser->cursor;
+ }
+ break;
+ /* ************ otherwise, it is any token **************/
+ default:
+ token->start = cur;
+ token->type = T1_TOKEN_TYPE_ANY;
+ ps_parser_skip_PS_token( parser );
+ cur = parser->cursor;
+ if ( !parser->error )
token->limit = cur;
- }
+ }
- if ( !token->limit )
- {
- token->start = 0;
- token->type = T1_TOKEN_TYPE_NONE;
- }
-
- parser->cursor = cur;
+ if ( !token->limit )
+ {
+ token->start = 0;
+ token->type = T1_TOKEN_TYPE_NONE;
}
+
+ parser->cursor = cur;
}
@@ -429,7 +649,9 @@
*pnum_tokens = -1;
+ /* this also handles leading whitespace */
ps_parser_to_token( parser, &master );
+
if ( master.type == T1_TOKEN_TYPE_ARRAY )
{
FT_Byte* old_cursor = parser->cursor;
@@ -438,8 +660,9 @@
T1_Token limit = cur + max_tokens;
- parser->cursor = master.start;
- parser->limit = master.limit;
+ /* don't include outermost delimiters */
+ parser->cursor = master.start + 1;
+ parser->limit = master.limit - 1;
while ( parser->cursor < parser->limit )
{
@@ -464,37 +687,35 @@
}
+ /* first character must be already part of the number */
+
static FT_Long
T1Radix( FT_Long radixBase,
- FT_Byte** cur,
+ FT_Byte* *acur,
FT_Byte* limit )
{
- FT_Long result = 0;
- FT_Byte radixEndChar0 =
- (FT_Byte)( radixBase > 10 ? '9' + 1 : '0' + radixBase );
- FT_Byte radixEndChar1 =
- (FT_Byte)( 'A' + radixBase - 10 );
- FT_Byte radixEndChar2 =
- (FT_Byte)( 'a' + radixBase - 10 );
+ FT_Long result = 0;
+ FT_Byte* cur = *acur;
- while( *cur < limit )
+ if ( radixBase < 2 || radixBase > 36 )
+ return 0;
+
+ while ( cur < limit )
{
- if ( (*cur)[0] >= '0' && (*cur)[0] < radixEndChar0 )
- result = result * radixBase + (*cur)[0] - '0';
+ int d;
- else if ( radixBase > 10 &&
- (*cur)[0] >= 'A' && (*cur)[0] < radixEndChar1 )
- result = result * radixBase + ( (*cur)[0] - 'A' + 10 );
- else if ( radixBase > 10 &&
- (*cur)[0] >= 'a' && (*cur)[0] < radixEndChar2 )
- result = result * radixBase + ( (*cur)[0] - 'a' + 10 );
+ if ( *cur OP 0x80 )
+ break;
- else
- return result;
+ d = ft_char_table[*cur & 0x7F];
+ if ( d < 0 || d >= radixBase )
+ break;
- (*cur)++;
+ result = result * radixBase + d;
+
+ cur++;
}
return result;
@@ -501,113 +722,126 @@
}
+ /* first character must be already part of the number */
+
static FT_Long
- t1_toint( FT_Byte** cursor,
+ ps_toint( FT_Byte* *acur,
FT_Byte* limit )
{
FT_Long result = 0;
- FT_Byte* cur = *cursor;
- FT_Byte c = '\0', d;
+ FT_Byte* cur = *acur;
+ FT_Byte c;
- for ( ; cur < limit; cur++ )
+ if ( cur >= limit )
+ goto Exit;
+
+ c = *cur;
+ if ( c == '-' )
+ cur++;
+
+ while ( cur < limit )
{
- c = *cur;
- d = (FT_Byte)( c - '0' );
- if ( d < 10 )
- break;
+ int d;
- if ( c == '-' )
+
+ if ( *cur == '#' )
{
cur++;
+ result = T1Radix( result, &cur, limit );
break;
}
- }
- if ( cur < limit )
- {
- do
- {
- d = (FT_Byte)( cur[0] - '0' );
- if ( d >= 10 )
- {
- if ( cur[0] == '#' )
- {
- cur++;
- result = T1Radix( result, &cur, limit );
- }
- break;
- }
+ if ( *cur OP 0x80 )
+ break;
- result = result * 10 + d;
- cur++;
+ d = ft_char_table[*cur & 0x7F];
+ if ( d < 0 || d >= 10 )
+ break;
+ result = result * 10 + d;
- } while ( cur < limit );
+ cur++;
+ };
- if ( c == '-' )
- result = -result;
- }
+ if ( c == '-' )
+ result = -result;
- *cursor = cur;
+ Exit:
+ *acur = cur;
return result;
}
- /* <...>: hexadecimal string */
+ /* first character must be `<' if `delimiters' is non-zero */
+
static FT_Error
- ps_tobytes( FT_Byte** cursor,
+ ps_tobytes( FT_Byte* *acur,
FT_Byte* limit,
- FT_Int max_bytes,
+ FT_Long max_bytes,
FT_Byte* bytes,
- FT_Int* pnum_bytes )
+ FT_Long* pnum_bytes,
+ FT_Bool delimiters )
{
FT_Error error = PSaux_Err_Ok;
- FT_Byte* cur = *cursor;
- FT_Int n = 0;
- FT_Byte b;
+ FT_Byte* cur = *acur;
+ FT_Long n;
- skip_spaces( &cur, limit );
+ if ( cur >= limit )
+ goto Exit;
- if ( *cur != '<' )
+ if ( delimiters )
{
- error = PSaux_Err_Invalid_File_Format;
- goto Exit;
+ if ( *cur != '<' )
+ {
+ error = PSaux_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ cur++;
}
- cur++;
+ max_bytes = max_bytes * 2;
- for ( ; cur < limit; n++ )
+ for ( n = 0; cur < limit; n++, cur++ )
{
- FT_Byte* cur2 = cur;
+ int d;
- if ( n + 1 > max_bytes * 2 )
+ if ( n >= max_bytes )
+ /* buffer is full */
goto Exit;
- /* All white-space charcters are ignored. */
+ /* All whitespace characters are ignored. */
skip_spaces( &cur, limit );
+ if ( cur >= limit )
+ break;
- b = (FT_Byte) T1Radix( 16, &cur, cur + 1 );
+ if ( *cur OP 0x80 )
+ break;
- if ( cur == cur2 )
+ d = ft_char_table[*cur & 0x7F];
+ if ( d < 0 || d >= 16 )
break;
/* <f> == <f0> != <0f> */
- bytes[n / 2] = (FT_Byte)( ( n % 2 ) ? bytes[n / 2] + b
- : b * 16 );
+ bytes[n / 2] = (FT_Byte)( ( n % 2 ) ? bytes[n / 2] + d
+ : d * 16 );
}
- skip_spaces( &cur, limit );
-
- if ( *cur != '>' )
+ if ( delimiters )
{
- error = PSaux_Err_Invalid_File_Format;
- goto Exit;
+ if ( cur < limit && *cur != '>' )
+ {
+ error = PSaux_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ cur++;
}
- *cursor = ++cur;
+ *acur = cur;
Exit:
*pnum_bytes = ( n + 1 ) / 2;
@@ -616,15 +850,16 @@
}
+ /* first character must be already part of the number */
+
static FT_Long
- t1_tofixed( FT_Byte** cursor,
+ ps_tofixed( FT_Byte* *acur,
FT_Byte* limit,
FT_Long power_ten )
{
- FT_Byte* cur = *cursor;
+ FT_Byte* cur = *acur;
FT_Long num, divider, result;
FT_Int sign = 0;
- FT_Byte d;
if ( cur >= limit )
@@ -631,7 +866,7 @@
return 0;
/* first of all, check the sign */
- if ( *cur == '-' )
+ if ( *cur == '-' && cur + 1 < limit )
{
sign = 1;
cur++;
@@ -639,7 +874,7 @@
/* then, read the integer part, if any */
if ( *cur != '.' )
- result = t1_toint( &cur, limit ) << 16;
+ result = ps_toint( &cur, limit ) << 16;
else
result = 0;
@@ -656,10 +891,16 @@
for (;;)
{
- d = (FT_Byte)( *cur - '0' );
- if ( d >= 10 )
+ int d;
+
+
+ if ( *cur OP 0x80 )
break;
+ d = ft_char_table[*cur & 0x7F];
+ if ( d < 0 || d >= 10 )
+ break;
+
if ( divider < 10000000L )
{
num = num * 10 + d;
@@ -676,7 +917,7 @@
if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
{
cur++;
- power_ten += t1_toint( &cur, limit );
+ power_ten += ps_toint( &cur, limit );
}
Exit:
@@ -701,18 +942,20 @@
if ( sign )
result = -result;
- *cursor = cur;
+ *acur = cur;
return result;
}
+ /* first character must be a delimiter or a part of a number */
+
static FT_Int
- t1_tocoordarray( FT_Byte** cursor,
+ ps_tocoordarray( FT_Byte* *acur,
FT_Byte* limit,
FT_Int max_coords,
FT_Short* coords )
{
- FT_Byte* cur = *cursor;
+ FT_Byte* cur = *acur;
FT_Int count = 0;
FT_Byte c, ender;
@@ -720,8 +963,8 @@
if ( cur >= limit )
goto Exit;
- /* check for the beginning of an array; if not, only one number will */
- /* be read */
+ /* check for the beginning of an array; otherwise, only one number */
+ /* will be read */
c = *cur;
ender = 0;
@@ -735,24 +978,23 @@
cur++;
/* now, read the coordinates */
- for ( ; cur < limit; )
+ while ( cur < limit )
{
/* skip whitespace in front of data */
- for (;;)
- {
- c = *cur;
- if ( c != ' ' && c != '\t' )
- break;
+ skip_spaces( &cur, limit );
+ if ( cur >= limit )
+ goto Exit;
+ if ( count >= max_coords )
+ break;
+
+ if ( c == ender )
+ {
cur++;
- if ( cur >= limit )
- goto Exit;
+ break;
}
- if ( count >= max_coords || c == ender )
- break;
-
- coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
+ coords[count] = (FT_Short)( ps_tofixed( &cur, limit, 0 ) >> 16 );
count++;
if ( !ender )
@@ -760,27 +1002,30 @@
}
Exit:
- *cursor = cur;
+ *acur = cur;
return count;
}
+ /* first character must be a delimiter or a part of a number */
+
static FT_Int
- t1_tofixedarray( FT_Byte** cursor,
+ ps_tofixedarray( FT_Byte* *acur,
FT_Byte* limit,
FT_Int max_values,
FT_Fixed* values,
FT_Int power_ten )
{
- FT_Byte* cur = *cursor;
+ FT_Byte* cur = *acur;
FT_Int count = 0;
FT_Byte c, ender;
- if ( cur >= limit ) goto Exit;
+ if ( cur >= limit )
+ goto Exit;
- /* check for the beginning of an array. If not, only one number will */
- /* be read */
+ /* Check for the beginning of an array. Otherwise, only one number */
+ /* will be read. */
c = *cur;
ender = 0;
@@ -794,24 +1039,23 @@
cur++;
/* now, read the values */
- for ( ; cur < limit; )
+ while ( cur < limit )
{
/* skip whitespace in front of data */
- for (;;)
- {
- c = *cur;
- if ( c != ' ' && c != '\t' )
- break;
+ skip_spaces( &cur, limit );
+ if ( cur >= limit )
+ goto Exit;
+ if ( count >= max_values )
+ break;
+
+ if ( c == ender )
+ {
cur++;
- if ( cur >= limit )
- goto Exit;
+ break;
}
- if ( count >= max_values || c == ender )
- break;
-
- values[count] = t1_tofixed( &cur, limit, power_ten );
+ values[count] = ps_tofixed( &cur, limit, power_ten );
count++;
if ( !ender )
@@ -819,7 +1063,7 @@
}
Exit:
- *cursor = cur;
+ *acur = cur;
return count;
}
@@ -827,7 +1071,7 @@
#if 0
static FT_String*
- t1_tostring( FT_Byte** cursor,
+ ps_tostring( FT_Byte** cursor,
FT_Byte* limit,
FT_Memory memory )
{
@@ -887,40 +1131,41 @@
static int
- t1_tobool( FT_Byte** cursor,
+ ps_tobool( FT_Byte* *acur,
FT_Byte* limit )
{
- FT_Byte* cur = *cursor;
+ FT_Byte* cur = *acur;
FT_Bool result = 0;
/* return 1 if we find `true', 0 otherwise */
if ( cur + 3 < limit &&
- cur[0] == 't' &&
- cur[1] == 'r' &&
- cur[2] == 'u' &&
- cur[3] == 'e' )
+ cur[0] == 't' &&
+ cur[1] == 'r' &&
+ cur[2] == 'u' &&
+ cur[3] == 'e' )
{
result = 1;
cur += 5;
}
else if ( cur + 4 < limit &&
- cur[0] == 'f' &&
- cur[1] == 'a' &&
- cur[2] == 'l' &&
- cur[3] == 's' &&
- cur[4] == 'e' )
+ cur[0] == 'f' &&
+ cur[1] == 'a' &&
+ cur[2] == 'l' &&
+ cur[3] == 's' &&
+ cur[4] == 'e' )
{
result = 0;
cur += 6;
}
- *cursor = cur;
+ *acur = cur;
return result;
}
- /* Load a simple field (i.e. non-table) into the current list of objects */
+ /* load a simple field (i.e. non-table) into the current list of objects */
+
FT_LOCAL_DEF( FT_Error )
ps_parser_load_field( PS_Parser parser,
const T1_Field field,
@@ -936,6 +1181,7 @@
FT_Error error;
+ /* this also skips leading whitespace */
ps_parser_to_token( parser, &token );
if ( !token.type )
goto Fail;
@@ -945,7 +1191,7 @@
cur = token.start;
limit = token.limit;
- /* we must detect arrays */
+ /* we must detect arrays in /FontBBox */
if ( field->type == T1_FIELD_TYPE_BBOX )
{
T1_TokenRec token2;
@@ -953,8 +1199,9 @@
FT_Byte* old_limit = parser->limit;
- parser->cursor = token.start;
- parser->limit = token.limit;
+ /* don't include delimiters */
+ parser->cursor = token.start + 1;
+ parser->limit = token.limit - 1;
ps_parser_to_token( parser, &token2 );
parser->cursor = old_cur;
@@ -966,12 +1213,16 @@
else if ( token.type == T1_TOKEN_TYPE_ARRAY )
{
FieldArray:
- /* if this is an array, and we have no blend, an error occurs */
+ /* if this is an array and we have no blend, an error occurs */
if ( max_objects == 0 )
goto Fail;
count = max_objects;
- idx = 1;
+ idx = 1;
+
+ /* don't include delimiters */
+ cur++;
+ limit--;
}
for ( ; count > 0; count--, idx++ )
@@ -981,23 +1232,25 @@
FT_String* string;
+ skip_spaces( &cur, limit );
+
switch ( field->type )
{
case T1_FIELD_TYPE_BOOL:
- val = t1_tobool( &cur, limit );
+ val = ps_tobool( &cur, limit );
goto Store_Integer;
case T1_FIELD_TYPE_FIXED:
- val = t1_tofixed( &cur, limit, 0 );
+ val = ps_tofixed( &cur, limit, 0 );
goto Store_Integer;
case T1_FIELD_TYPE_FIXED_1000:
- val = t1_tofixed( &cur, limit, 3 );
+ val = ps_tofixed( &cur, limit, 3 );
goto Store_Integer;
case T1_FIELD_TYPE_INTEGER:
- val = t1_toint( &cur, limit );
- goto Store_Integer;
+ val = ps_toint( &cur, limit );
+ /* fall through */
Store_Integer:
switch ( field->size )
@@ -1026,15 +1279,25 @@
FT_UInt len = (FT_UInt)( limit - cur );
- /* with synthetic fonts, it's possible to find a field twice */
+ if ( cur >= limit )
+ break;
+
+ /* with synthetic fonts, it is possible to find a field twice */
if ( *(FT_String**)q )
break;
if ( field->type == T1_FIELD_TYPE_KEY )
{
+ /* don't include leading `/' */
len--;
cur++;
}
+ else
+ {
+ /* don't include delimiting parentheses */
+ cur++;
+ len -= 2;
+ }
if ( FT_ALLOC( string, len + 1 ) )
goto Exit;
@@ -1052,10 +1315,7 @@
FT_BBox* bbox = (FT_BBox*)q;
- /* we need the '[' and ']' delimiters */
- token.start--;
- token.limit++;
- (void)t1_tofixedarray( &token.start, token.limit, 4, temp, 0 );
+ (void)ps_tofixedarray( &token.start, token.limit, 4, temp, 0 );
bbox->xMin = FT_RoundFix( temp[0] );
bbox->yMin = FT_RoundFix( temp[1] );
@@ -1070,7 +1330,7 @@
}
}
-#if 0 /* obsolete - keep for reference */
+#if 0 /* obsolete -- keep for reference */
if ( pflags )
*pflags |= 1L << field->flag_bit;
#else
@@ -1113,7 +1373,8 @@
fieldrec.type = T1_FIELD_TYPE_FIXED;
#endif
- ps_parser_to_token_array( parser, elements, 32, &num_elements );
+ ps_parser_to_token_array( parser, elements,
+ T1_MAX_TABLE_ELEMENTS, &num_elements );
if ( num_elements < 0 )
goto Fail;
@@ -1159,7 +1420,8 @@
FT_LOCAL_DEF( FT_Long )
ps_parser_to_int( PS_Parser parser )
{
- return t1_toint( &parser->cursor, parser->limit );
+ ps_parser_skip_spaces( parser );
+ return ps_toint( &parser->cursor, parser->limit );
}
@@ -1166,14 +1428,17 @@
FT_LOCAL_DEF( FT_Error )
ps_parser_to_bytes( PS_Parser parser,
FT_Byte* bytes,
- FT_Int max_bytes,
- FT_Int* pnum_bytes )
+ FT_Long max_bytes,
+ FT_Long* pnum_bytes,
+ FT_Bool delimiters )
{
+ ps_parser_skip_spaces( parser );
return ps_tobytes( &parser->cursor,
parser->limit,
max_bytes,
bytes,
- pnum_bytes );
+ pnum_bytes,
+ delimiters );
}
@@ -1181,7 +1446,8 @@
ps_parser_to_fixed( PS_Parser parser,
FT_Int power_ten )
{
- return t1_tofixed( &parser->cursor, parser->limit, power_ten );
+ ps_parser_skip_spaces( parser );
+ return ps_tofixed( &parser->cursor, parser->limit, power_ten );
}
@@ -1190,7 +1456,8 @@
FT_Int max_coords,
FT_Short* coords )
{
- return t1_tocoordarray( &parser->cursor, parser->limit,
+ ps_parser_skip_spaces( parser );
+ return ps_tocoordarray( &parser->cursor, parser->limit,
max_coords, coords );
}
@@ -1201,7 +1468,8 @@
FT_Fixed* values,
FT_Int power_ten )
{
- return t1_tofixedarray( &parser->cursor, parser->limit,
+ ps_parser_skip_spaces( parser );
+ return ps_tofixedarray( &parser->cursor, parser->limit,
max_values, values, power_ten );
}
@@ -1211,7 +1479,7 @@
FT_LOCAL_DEF( FT_String* )
T1_ToString( PS_Parser parser )
{
- return t1_tostring( &parser->cursor, parser->limit, parser->memory );
+ return ps_tostring( &parser->cursor, parser->limit, parser->memory );
}
@@ -1218,7 +1486,7 @@
FT_LOCAL_DEF( FT_Bool )
T1_ToBool( PS_Parser parser )
{
- return t1_tobool( &parser->cursor, parser->limit );
+ return ps_tobool( &parser->cursor, parser->limit );
}
#endif /* 0 */
@@ -1230,7 +1498,7 @@
FT_Byte* limit,
FT_Memory memory )
{
- parser->error = 0;
+ parser->error = PSaux_Err_Ok;
parser->base = base;
parser->limit = limit;
parser->cursor = base;
--- a/src/psaux/psobjs.h
+++ b/src/psaux/psobjs.h
@@ -78,7 +78,7 @@
ps_parser_skip_spaces( PS_Parser parser );
FT_LOCAL( void )
- ps_parser_skip_alpha( PS_Parser parser );
+ ps_parser_skip_PS_token( PS_Parser parser );
FT_LOCAL( void )
ps_parser_to_token( PS_Parser parser,
@@ -111,8 +111,9 @@
FT_LOCAL( FT_Error )
ps_parser_to_bytes( PS_Parser parser,
FT_Byte* bytes,
- FT_Int max_bytes,
- FT_Int* pnum_bytes );
+ FT_Long max_bytes,
+ FT_Long* pnum_bytes,
+ FT_Bool delimiters );
FT_LOCAL( FT_Fixed )
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -41,12 +41,11 @@
/* */
/* All other common cases are handled very simply. The matching rules */
/* are defined in the file `t1tokens.h' through the use of several */
- /* macros calls PARSE_XXX. */
+ /* macros calls PARSE_XXX. This file is included twice here; the first */
+ /* time to generate parsing callback functions, the second time to */
+ /* generate a table of keywords (with pointers to the associated */
+ /* callback functions). */
/* */
- /* This file is included twice here; the first time to generate parsing */
- /* callback functions, the second to generate a table of keywords (with */
- /* pointers to the associated callback). */
- /* */
/* The function `parse_dict' simply scans *linearly* a given dictionary */
/* (either the top-level or private one) and calls the appropriate */
/* callback when it encounters an immediate keyword. */
@@ -71,7 +70,6 @@
#include "t1errors.h"
-
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
@@ -100,7 +98,7 @@
{
PS_Blend blend;
FT_Memory memory = face->root.memory;
- FT_Error error = 0;
+ FT_Error error = T1_Err_Ok;
blend = face->blend;
@@ -174,7 +172,7 @@
return error;
Fail:
- error = -1;
+ error = T1_Err_Invalid_File_Format;
goto Exit;
}
@@ -205,8 +203,10 @@
axis->minimum = map->design_points[0];
axis->maximum = map->design_points[map->num_points - 1];
}
- error = 0;
+
+ error = T1_Err_Ok;
}
+
return error;
}
@@ -253,6 +253,7 @@
error = T1_Err_Ok;
}
+
return error;
}
@@ -289,7 +290,7 @@
FT_Fixed p_design = designs[p];
- /* exact match ? */
+ /* exact match? */
if ( design == p_design )
{
the_blend = blends[p];
@@ -305,7 +306,7 @@
before = p;
}
- /* now, interpolate if needed */
+ /* now interpolate if necessary */
if ( before < 0 )
the_blend = blends[0];
@@ -386,9 +387,9 @@
parse_blend_axis_types( T1_Face face,
T1_Loader loader )
{
- T1_TokenRec axis_tokens[ T1_MAX_MM_AXIS ];
+ T1_TokenRec axis_tokens[T1_MAX_MM_AXIS];
FT_Int n, num_axis;
- FT_Error error = 0;
+ FT_Error error = T1_Err_Ok;
PS_Blend blend;
FT_Memory memory;
@@ -448,16 +449,16 @@
parse_blend_design_positions( T1_Face face,
T1_Loader loader )
{
- T1_TokenRec design_tokens[ T1_MAX_MM_DESIGNS ];
+ T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS];
FT_Int num_designs;
FT_Int num_axis;
T1_Parser parser = &loader->parser;
- FT_Error error = 0;
+ FT_Error error = T1_Err_Ok;
PS_Blend blend;
- /* get the array of design tokens - compute number of designs */
+ /* get the array of design tokens -- compute number of designs */
T1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
{
@@ -479,7 +480,7 @@
for ( n = 0; n < (FT_UInt)num_designs; n++ )
{
- T1_TokenRec axis_tokens[ T1_MAX_MM_DESIGNS ];
+ T1_TokenRec axis_tokens[T1_MAX_MM_DESIGNS];
T1_Token token;
FT_Int axis, n_axis;
@@ -486,8 +487,8 @@
/* read axis/coordinates tokens */
token = design_tokens + n;
- parser->root.cursor = token->start - 1;
- parser->root.limit = token->limit + 1;
+ parser->root.cursor = token->start;
+ parser->root.limit = token->limit;
T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
if ( n == 0 )
@@ -505,7 +506,7 @@
goto Exit;
}
- /* now, read each axis token into the design position */
+ /* now read each axis token into the design position */
for ( axis = 0; axis < n_axis; axis++ )
{
T1_Token token2 = axis_tokens + axis;
@@ -530,7 +531,7 @@
parse_blend_design_map( T1_Face face,
T1_Loader loader )
{
- FT_Error error = 0;
+ FT_Error error = T1_Err_Ok;
T1_Parser parser = &loader->parser;
PS_Blend blend;
T1_TokenRec axis_tokens[T1_MAX_MM_AXIS];
@@ -548,6 +549,7 @@
error = T1_Err_Invalid_File_Format;
goto Exit;
}
+
old_cursor = parser->root.cursor;
old_limit = parser->root.limit;
@@ -556,29 +558,22 @@
goto Exit;
blend = face->blend;
- /* now, read each axis design map */
+ /* now read each axis design map */
for ( n = 0; n < num_axis; n++ )
{
PS_DesignMap map = blend->design_map + n;
- T1_Token token;
+ T1_Token axis_token;
+ T1_TokenRec point_tokens[T1_MAX_MM_MAP_POINTS];
FT_Int p, num_points;
- token = axis_tokens + n;
- parser->root.cursor = token->start;
- parser->root.limit = token->limit;
+ axis_token = axis_tokens + n;
- /* count the number of map points */
- {
- FT_Byte* ptr = token->start;
- FT_Byte* limit = token->limit;
+ parser->root.cursor = axis_token->start;
+ parser->root.limit = axis_token->limit;
+ T1_ToTokenArray( parser, point_tokens,
+ T1_MAX_MM_MAP_POINTS, &num_points );
-
- num_points = 0;
- for ( ; ptr < limit; ptr++ )
- if ( ptr[0] == '[' )
- num_points++;
- }
if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
{
FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
@@ -594,6 +589,15 @@
for ( p = 0; p < num_points; p++ )
{
+ T1_Token point_token;
+
+
+ point_token = point_tokens + p;
+
+ /* don't include delimiting brackets */
+ parser->root.cursor = point_token->start + 1;
+ parser->root.limit = point_token->limit - 1;
+
map->design_points[p] = T1_ToInt( parser );
map->blend_points [p] = T1_ToFixed( parser, 0 );
}
@@ -611,7 +615,7 @@
parse_weight_vector( T1_Face face,
T1_Loader loader )
{
- FT_Error error = 0;
+ FT_Error error = T1_Err_Ok;
T1_Parser parser = &loader->parser;
PS_Blend blend = face->blend;
T1_TokenRec master;
@@ -638,8 +642,9 @@
old_cursor = parser->root.cursor;
old_limit = parser->root.limit;
- parser->root.cursor = master.start;
- parser->root.limit = master.limit;
+ /* don't include the delimiting brackets */
+ parser->root.cursor = master.start + 1;
+ parser->root.limit = master.limit - 1;
for ( n = 0; n < blend->num_designs; n++ )
{
@@ -675,6 +680,8 @@
#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -683,15 +690,6 @@
/*************************************************************************/
/*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* First of all, define the token field static variables. This is a set */
- /* of T1_FieldRec variables used later. */
- /* */
- /*************************************************************************/
-
-
static FT_Error
t1_load_keyword( T1_Face face,
T1_Loader loader,
@@ -774,33 +772,13 @@
static int
is_space( FT_Byte c )
{
- return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
+ return ( c == ' ' || c == '\t' ||
+ c == '\r' || c == '\n' || c == '\f' ||
+ c == '\0' );
}
static int
- is_name_char( FT_Byte c )
- {
- /* Note: PostScript allows any non-delimiting, non-whitespace */
- /* in a name (PS Ref Manual, 3rd Ed, p31) */
- /* PostScript delimiters include (,),<,>,[,],{,},/ and % */
-
- return ( c != '(' &&
- c != ')' &&
- c != '<' &&
- c != '>' &&
- c != '[' &&
- c != ']' &&
- c != '{' &&
- c != '}' &&
- c != '/' &&
- c != '%' &&
- ! is_space( c )
- );
- }
-
-
- static int
read_binary_data( T1_Parser parser,
FT_Long* size,
FT_Byte** base )
@@ -815,14 +793,14 @@
/* */
T1_Skip_Spaces( parser );
+
cur = parser->root.cursor;
- if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
+ if ( cur < limit && ft_isdigit( *cur ) )
{
*size = T1_ToInt( parser );
- T1_Skip_Spaces( parser );
- T1_Skip_Alpha ( parser ); /* `RD' or `-|' or something else */
+ T1_Skip_PS_Token( parser ); /* `RD' or `-|' or something else */
/* there is only one whitespace char after the */
/* `RD' or `-|' token */
@@ -838,9 +816,8 @@
}
- /* we will now define the routines used to handle */
- /* the `/Encoding', `/Subrs', and `/CharStrings' */
- /* dictionaries */
+ /* We now define the routines to handle the `/Encoding', `/Subrs', */
+ /* and `/CharStrings' dictionaries. */
static void
parse_font_matrix( T1_Face face,
@@ -855,7 +832,7 @@
if ( matrix->xx || matrix->yx )
- /* with synthetic fonts, it's possible we get here twice */
+ /* with synthetic fonts it is possible we get here twice */
return;
(void)T1_ToFixedArray( parser, 6, temp, 3 );
@@ -895,28 +872,25 @@
parse_encoding( T1_Face face,
T1_Loader loader )
{
- T1_Parser parser = &loader->parser;
- FT_Byte* cur = parser->root.cursor;
- FT_Byte* limit = parser->root.limit;
+ T1_Parser parser = &loader->parser;
+ FT_Byte* cur;
+ FT_Byte* limit = parser->root.limit;
- PSAux_Service psaux = (PSAux_Service)face->psaux;
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
- /* skip whitespace */
- while ( is_space( *cur ) )
+ T1_Skip_Spaces( parser );
+ cur = parser->root.cursor;
+ if ( cur >= limit )
{
- cur++;
- if ( cur >= limit )
- {
- FT_ERROR(( "parse_encoding: out of bounds!\n" ));
- parser->root.error = T1_Err_Invalid_File_Format;
- return;
- }
+ FT_ERROR(( "parse_encoding: out of bounds!\n" ));
+ parser->root.error = T1_Err_Invalid_File_Format;
+ return;
}
/* if we have a number, then the encoding is an array, */
/* and we must load it now */
- if ( (FT_Byte)( *cur - '0' ) < 10 )
+ if ( ft_isdigit( *cur ) )
{
T1_Encoding encode = &face->type1.encoding;
FT_Int count, n;
@@ -926,18 +900,19 @@
if ( encode->char_index )
- /* with synthetic fonts, it's possible we get here twice */
+ /* with synthetic fonts it is possible we get here twice */
return;
- /* read the number of entries in the encoding, should be 256 */
+ /* read the number of entries in the encoding; should be 256 */
count = (FT_Int)T1_ToInt( parser );
- if ( parser->root.error )
+ T1_Skip_Spaces( parser );
+ if ( parser->root.cursor >= limit )
return;
/* we use a T1_Table to store our charnames */
loader->num_chars = encode->num_chars = count;
- if ( FT_NEW_ARRAY( encode->char_index, count ) ||
- FT_NEW_ARRAY( encode->char_name, count ) ||
+ if ( FT_NEW_ARRAY( encode->char_index, count ) ||
+ FT_NEW_ARRAY( encode->char_name, count ) ||
FT_SET_ERROR( psaux->ps_table_funcs->init(
char_table, count, memory ) ) )
{
@@ -954,86 +929,74 @@
T1_Add_Table( char_table, n, notdef, 8 );
}
- /* Now, we will need to read a record of the form */
+ /* Now we need to read a record 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 type1 fonts: */
+ /* that is often seen in Type 1 fonts: */
/* */
/* 0 1 255 { 1 index exch /.notdef put } for dup */
/* */
/* used to clean the encoding array before anything else. */
- /* */
- /* We stop when we encounter a `def'. */
- cur = parser->root.cursor;
- limit = parser->root.limit;
- n = 0;
+ n = 0;
- for ( ; cur < limit; )
+ while ( parser->root.cursor < limit )
{
- FT_Byte c;
+ T1_Skip_Spaces( parser );
+ cur = parser->root.cursor;
-
- c = *cur;
-
/* we stop when we encounter a `def' */
- if ( c == 'd' && cur + 3 < limit )
+ if ( *cur == 'd' && cur + 3 < limit )
{
- if ( cur[1] == 'e' &&
- cur[2] == 'f' &&
- is_space( cur[-1] ) &&
- is_space( cur[3] ) )
+ if ( cur[1] == 'e' &&
+ cur[2] == 'f' &&
+ is_space( cur[3] ) )
{
FT_TRACE6(( "encoding end\n" ));
+ cur += 3;
break;
}
}
/* otherwise, we must find a number before anything else */
- if ( (FT_Byte)( c - '0' ) < 10 )
+ if ( ft_isdigit( *cur ) )
{
FT_Int charcode;
- parser->root.cursor = cur;
charcode = (FT_Int)T1_ToInt( parser );
- cur = parser->root.cursor;
+ T1_Skip_Spaces( parser );
+ cur = parser->root.cursor;
- /* skip whitespace */
- while ( cur < limit && is_space( *cur ) )
- cur++;
-
- if ( cur < limit && *cur == '/' )
+ if ( *cur == '/' && cur + 2 < limit )
{
- /* bingo, we have an immediate name -- it must be a */
- /* character name */
- FT_Byte* cur2 = cur + 1;
FT_PtrDist len;
- while ( cur2 < limit && is_name_char( *cur2 ) )
- cur2++;
+ cur++;
- len = cur2 - cur - 1;
+ parser->root.cursor = cur;
+ T1_Skip_PS_Token( parser );
+ len = parser->root.cursor - cur;
+
parser->root.error = T1_Add_Table( char_table, charcode,
- cur + 1, len + 1 );
+ cur, len + 1 );
char_table->elements[charcode][len] = '\0';
if ( parser->root.error )
return;
-
- cur = cur2;
}
}
else
- cur++;
+ T1_Skip_PS_Token( parser );
}
face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
parser->root.cursor = cur;
}
+
/* Otherwise, we should have either `StandardEncoding', */
/* `ExpertEncoding', or `ISOLatin1Encoding' */
else
@@ -1063,35 +1026,38 @@
parse_subrs( T1_Face face,
T1_Loader loader )
{
- T1_Parser parser = &loader->parser;
- PS_Table table = &loader->subrs;
- FT_Memory memory = parser->root.memory;
- FT_Error error;
- FT_Int n;
+ T1_Parser parser = &loader->parser;
+ PS_Table table = &loader->subrs;
+ FT_Memory memory = parser->root.memory;
+ FT_Error error;
+ FT_Int n;
PSAux_Service psaux = (PSAux_Service)face->psaux;
if ( loader->num_subrs )
- /* with synthetic fonts, it's possible we get here twice */
+ /* with synthetic fonts it is possible we get here twice */
return;
- if ( parser->root.cursor + 2 > parser->root.limit &&
- parser->root.cursor[0] == '[' &&
- parser->root.cursor[1] == ']' )
+ T1_Skip_Spaces( parser );
+
+ /* test for empty array */
+ if ( parser->root.cursor < parser->root.limit &&
+ *parser->root.cursor == '[' )
{
- /* empty array */
+ T1_Skip_PS_Token( parser );
+ T1_Skip_Spaces ( parser );
+ if ( parser->root.cursor >= parser->root.limit ||
+ *parser->root.cursor != ']' )
+ parser->root.error = T1_Err_Invalid_File_Format;
return;
}
loader->num_subrs = (FT_Int)T1_ToInt( parser );
- if ( parser->root.error )
- return;
/* position the parser right before the `dup' of the first subr */
- T1_Skip_Spaces( parser );
- T1_Skip_Alpha( parser ); /* `array' */
- T1_Skip_Spaces( parser );
+ T1_Skip_PS_Token( parser ); /* `array' */
+ T1_Skip_Spaces ( parser );
/* initialize subrs array */
error = psaux->ps_table_funcs->init( table, loader->num_subrs, memory );
@@ -1113,6 +1079,8 @@
if ( ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
break;
+ T1_Skip_PS_Token( parser ); /* `dup' */
+
idx = T1_ToInt( parser );
if ( !read_binary_data( parser, &size, &base ) )
@@ -1122,14 +1090,13 @@
/* (bound to `noaccess put') or by two separate tokens: */
/* `noaccess' & `put'. We position the parser right */
/* before the next `dup', if any. */
- T1_Skip_Spaces( parser );
- T1_Skip_Alpha( parser ); /* `NP' or `I' or `noaccess' */
- T1_Skip_Spaces( parser );
+ T1_Skip_PS_Token( parser ); /* `NP' or `I' or `noaccess' */
+ T1_Skip_Spaces ( parser );
if ( ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
{
- T1_Skip_Alpha( parser ); /* skip `put' */
- T1_Skip_Spaces( parser );
+ T1_Skip_PS_Token( parser ); /* skip `put' */
+ T1_Skip_Spaces ( parser );
}
/* some fonts use a value of -1 for lenIV to indicate that */
@@ -1164,6 +1131,9 @@
}
+#define TABLE_EXTEND 5
+
+
static void
parse_charstrings( T1_Face face,
T1_Loader loader )
@@ -1185,7 +1155,7 @@
if ( loader->num_glyphs )
- /* with synthetic fonts, it's possible we get here twice */
+ /* with synthetic fonts it is possible we get here twice */
return;
loader->num_glyphs = (FT_Int)T1_ToInt( parser );
@@ -1192,18 +1162,17 @@
if ( parser->root.error )
return;
- /* initialize tables (leaving room for addition of .notdef, */
- /* if necessary). */
+ /* initialize tables, leaving room for addition of .notdef, */
+ /* if necessary, and a few other glyphs to handle buggy */
+ /* fonts which have more glyphs than specified. */
- error = psaux->ps_table_funcs->init( code_table,
- loader->num_glyphs + 1,
- memory );
+ error = psaux->ps_table_funcs->init(
+ code_table, loader->num_glyphs + 1 + TABLE_EXTEND, memory );
if ( error )
goto Fail;
- error = psaux->ps_table_funcs->init( name_table,
- loader->num_glyphs + 1,
- memory );
+ error = psaux->ps_table_funcs->init(
+ name_table, loader->num_glyphs + 1 + TABLE_EXTEND, memory );
if ( error )
goto Fail;
@@ -1235,30 +1204,35 @@
break;
/* we stop when we find a `def' or `end' keyword */
- if ( *cur == 'd' &&
- cur + 3 < limit &&
- cur[1] == 'e' &&
- cur[2] == 'f' )
- break;
+ if ( cur + 3 < limit && is_space( cur[3] ) )
+ {
+ if ( cur[0] == 'd' &&
+ cur[1] == 'e' &&
+ cur[2] == 'f' )
+ break;
- if ( *cur == 'e' &&
- cur + 3 < limit &&
- cur[1] == 'n' &&
- cur[2] == 'd' )
- break;
+ if ( cur[0] == 'e' &&
+ cur[1] == 'n' &&
+ cur[2] == 'd' )
+ break;
+ }
if ( *cur != '/' )
- T1_Skip_Alpha( parser );
+ T1_Skip_PS_Token( parser );
else
{
- FT_Byte* cur2 = cur + 1;
FT_PtrDist len;
- while ( cur2 < limit && is_name_char( *cur2 ) )
- cur2++;
- len = cur2 - cur - 1;
+ T1_Skip_PS_Token( parser );
+ if ( cur >= limit )
+ {
+ error = T1_Err_Invalid_File_Format;
+ goto Fail;
+ }
+ len = parser->root.cursor - cur;
+
error = T1_Add_Table( name_table, n, cur + 1, len + 1 );
if ( error )
goto Fail;
@@ -1274,11 +1248,11 @@
notdef_found = 1;
}
- parser->root.cursor = cur2;
if ( !read_binary_data( parser, &size, &base ) )
return;
- if ( face->type1.private_dict.lenIV >= 0 )
+ if ( face->type1.private_dict.lenIV >= 0 &&
+ n < loader->num_glyphs + TABLE_EXTEND )
{
FT_Byte* temp;
@@ -1299,8 +1273,6 @@
goto Fail;
n++;
- if ( n >= loader->num_glyphs )
- break;
}
}
@@ -1311,11 +1283,11 @@
(const char*)name_table->elements[0] ) &&
notdef_found )
{
- /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */
- /* name and code entries to swap_table. Then place notdef_index name */
- /* and code entries into swap_table. Then swap name and code */
- /* entries at indices notdef_index and 0 using values stored in */
- /* swap_table. */
+ /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */
+ /* name and code entries to swap_table. Then place notdef_index */
+ /* name and code entries into swap_table. Then swap name and code */
+ /* entries at indices notdef_index and 0 using values stored in */
+ /* swap_table. */
/* Index 0 name */
error = T1_Add_Table( swap_table, 0,
@@ -1426,6 +1398,14 @@
}
+ /*************************************************************************/
+ /* */
+ /* Define the token field static variables. This is a set of */
+ /* T1_FieldRec variables. */
+ /* */
+ /*************************************************************************/
+
+
static
const T1_FieldRec t1_keywords[] =
{
@@ -1462,120 +1442,134 @@
FT_Byte* keyword_flags )
{
T1_Parser parser = &loader->parser;
+ FT_Byte* limit;
parser->root.cursor = base;
parser->root.limit = base + size;
- parser->root.error = 0;
+ parser->root.error = T1_Err_Ok;
+ limit = parser->root.limit;
+
+ while ( parser->root.cursor < limit )
{
- FT_Byte* cur = base;
- FT_Byte* limit = cur + size;
+ FT_Byte* cur;
- for ( ; cur < limit; cur++ )
+ T1_Skip_Spaces( parser );
+ cur = parser->root.cursor;
+
+ /* look for `FontDirectory', which causes problems for some fonts */
+ if ( *cur == 'F' && cur + 25 < limit &&
+ ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
{
- /* look for `FontDirectory', which causes problems on some fonts */
- if ( *cur == 'F' && cur + 25 < limit &&
- ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
- {
- FT_Byte* cur2;
+ FT_Byte* cur2;
- /* skip the `FontDirectory' keyword */
- cur += 13;
- cur2 = cur;
+ /* skip the `FontDirectory' keyword */
+ T1_Skip_PS_Token( parser );
+ T1_Skip_Spaces ( parser );
+ cur = cur2 = parser->root.cursor;
- /* lookup the `known' keyword */
- while ( cur < limit && *cur != 'k' &&
- ft_strncmp( (char*)cur, "known", 5 ) )
- cur++;
+ /* look up the `known' keyword */
+ while ( cur < limit )
+ {
+ if ( *cur == 'k' && cur + 5 < limit &&
+ ft_strncmp( (char*)cur, "known", 5 ) )
+ break;
- if ( cur < limit )
- {
- T1_TokenRec token;
+ T1_Skip_PS_Token( parser );
+ T1_Skip_Spaces ( parser );
+ cur = parser->root.cursor;
+ }
+ if ( cur < limit )
+ {
+ T1_TokenRec token;
- /* skip the `known' keyword and the token following it */
- cur += 5;
- loader->parser.root.cursor = cur;
- T1_ToToken( &loader->parser, &token );
- /* if the last token was an array, skip it! */
- if ( token.type == T1_TOKEN_TYPE_ARRAY )
- cur2 = parser->root.cursor;
- }
- cur = cur2;
+ /* skip the `known' keyword and the token following it */
+ T1_Skip_PS_Token( parser );
+ T1_ToToken( parser, &token );
+
+ /* if the last token was an array, skip it! */
+ if ( token.type == T1_TOKEN_TYPE_ARRAY )
+ cur2 = parser->root.cursor;
}
- /* look for immediates */
- else if ( *cur == '/' && cur + 2 < limit )
- {
- FT_Byte* cur2;
- FT_PtrDist len;
+ parser->root.cursor = cur2;
+ }
+ /* look for `closefile' which ends the eexec section */
+ else if ( *cur == 'c' && cur + 9 < limit &&
+ ft_strncmp( (char*)cur, "closefile", 9 ) == 0 )
+ break;
- cur++;
- cur2 = cur;
- while ( cur2 < limit && is_name_char( *cur2 ) )
- cur2++;
+ /* look for immediates */
+ else if ( *cur == '/' && cur + 2 < limit )
+ {
+ FT_PtrDist len;
- len = cur2 - cur;
- if ( len > 0 && len < 22 )
- {
- {
- /* now, compare the immediate name to the keyword table */
- T1_Field keyword = (T1_Field)t1_keywords;
- FT_Byte* keyword_flag = keyword_flags;
+ cur++;
- for (;;)
- {
- FT_Byte* name;
+ parser->root.cursor = cur;
+ T1_Skip_PS_Token( parser );
+ len = parser->root.cursor - cur;
- name = (FT_Byte*)keyword->ident;
- if ( !name )
- break;
+ if ( len > 0 && len < 22 )
+ {
+ /* now compare the immediate name to the keyword table */
+ T1_Field keyword = (T1_Field)t1_keywords;
+ FT_Byte* keyword_flag = keyword_flags;
- if ( cur[0] == name[0] &&
- len == ft_strlen( (const char*)name ) )
- {
- FT_PtrDist n;
+ for (;;)
+ {
+ FT_Byte* name;
- for ( n = 1; n < len; n++ )
- if ( cur[n] != name[n] )
- break;
- if ( n >= len )
- {
- /* we found it -- run the parsing callback! */
- parser->root.cursor = cur2;
- T1_Skip_Spaces( parser );
-
- /* we only record the first instance of any */
- /* field to deal adequately with synthetic fonts */
- if ( keyword_flag[0] == 0 )
- {
- parser->root.error = t1_load_keyword( face,
- loader,
- keyword );
- if ( parser->root.error )
- return parser->root.error;
- }
- keyword_flag[0] = 1;
+ name = (FT_Byte*)keyword->ident;
+ if ( !name )
+ {
+ T1_Skip_PS_Token( parser );
+ break;
+ }
- cur = parser->root.cursor;
- break;
- }
+ if ( cur[0] == name[0] &&
+ len == ft_strlen( (const char*)name ) )
+ {
+ FT_PtrDist n;
+
+
+ for ( n = 1; n < len; n++ )
+ if ( cur[n] != name[n] )
+ break;
+
+ if ( n >= len )
+ {
+ /* We found it -- run the parsing callback! */
+ /* We only record the first instance of any */
+ /* field to deal adequately with synthetic fonts */
+ if ( keyword_flag[0] == 0 )
+ {
+ parser->root.error = t1_load_keyword( face,
+ loader,
+ keyword );
+ if ( parser->root.error )
+ return parser->root.error;
}
- keyword++;
- keyword_flag++;
+ keyword_flag[0] = 1;
+ break;
}
}
+ keyword++;
+ keyword_flag++;
}
}
}
+ else
+ T1_Skip_PS_Token( parser );
}
return parser->root.error;
}
@@ -1742,16 +1736,21 @@
if ( ft_strcmp( (const char*)".notdef",
(const char*)glyph_name ) != 0 )
{
- if ( charcode < min_char ) min_char = charcode;
- if ( charcode > max_char ) max_char = charcode;
+ if ( charcode < min_char )
+ min_char = charcode;
+ if ( charcode > max_char )
+ max_char = charcode;
}
break;
}
}
}
- /* Yes, this happens: Certain PDF-embedded fonts have only a ".notdef"
- * glyph defined!
+
+ /*
+ * Yes, this happens: Certain PDF-embedded fonts have only a
+ * `.notdef' glyph defined!
*/
+
if ( min_char > max_char )
{
min_char = 0;
--- a/src/type1/t1parse.c
+++ b/src/type1/t1parse.c
@@ -104,7 +104,7 @@
FT_Long size;
- psaux->ps_parser_funcs->init( &parser->root,0, 0, memory );
+ psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
parser->stream = stream;
parser->base_len = 0;
@@ -219,29 +219,6 @@
}
- /* return the value of an hexadecimal digit */
- static int
- hexa_value( char c )
- {
- unsigned int d;
-
-
- d = (unsigned int)( c - '0' );
- if ( d <= 9 )
- return (int)d;
-
- d = (unsigned int)( c - 'a' );
- if ( d <= 5 )
- return (int)( d + 10 );
-
- d = (unsigned int)( c - 'A' );
- if ( d <= 5 )
- return (int)( d + 10 );
-
- return -1;
- }
-
-
FT_LOCAL_DEF( FT_Error )
T1_Get_Private_Dict( T1_Parser parser,
PSAux_Service psaux )
@@ -248,7 +225,7 @@
{
FT_Stream stream = parser->stream;
FT_Memory memory = parser->root.memory;
- FT_Error error = 0;
+ FT_Error error = T1_Err_Ok;
FT_Long size;
@@ -302,7 +279,8 @@
break;
}
- if ( FT_STREAM_READ( parser->private_dict + parser->private_len, size ) )
+ if ( FT_STREAM_READ( parser->private_dict + parser->private_len,
+ size ) )
goto Fail;
parser->private_len += size;
@@ -310,9 +288,9 @@
}
else
{
- /* we have already `loaded' the whole PFA font file into memory; */
+ /* We have already `loaded' the whole PFA font file into memory; */
/* if this is a memory resource, allocate a new block to hold */
- /* the private dict. Otherwise, simply overwrite into the base */
+ /* the private dict. Otherwise, simply overwrite into the base */
/* dictionary block in the heap. */
/* first of all, look at the `eexec' keyword */
@@ -330,7 +308,7 @@
if ( cur[1] == 'e' && cur[2] == 'x' &&
cur[3] == 'e' && cur[4] == 'c' )
{
- cur += 6; /* we skip the newling after the `eexec' */
+ 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 */
@@ -379,51 +357,38 @@
/* the `eexec' keyword); if they all are hexadecimal digits, then */
/* we have a case of ASCII storage */
- if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
- hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
-
- /* binary encoding -- `simply' copy the private dict */
- FT_MEM_COPY( parser->private_dict, cur, size );
-
- else
+ if ( ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) &&
+ ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) )
{
/* ASCII hexadecimal encoding */
+ FT_Long len;
- FT_Byte* write;
- FT_Int count;
+ parser->root.cursor = cur;
+ (void)psaux->ps_parser_funcs->to_bytes( &parser->root,
+ parser->private_dict,
+ parser->private_len,
+ &len,
+ 0 );
+ parser->private_len = len;
- write = parser->private_dict;
- count = 0;
-
- for ( ;cur < limit; cur++ )
- {
- int hex1;
-
-
- /* check for newline */
- if ( cur[0] == '\r' || cur[0] == '\n' )
- continue;
-
- /* exit if we have a non-hexadecimal digit that isn't a newline */
- hex1 = hexa_value( cur[0] );
- if ( hex1 < 0 || cur + 1 >= limit )
- break;
-
- /* otherwise, store byte */
- *write++ = (FT_Byte)( ( hex1 << 4 ) | hexa_value( cur[1] ) );
- count++;
- cur++;
- }
-
/* put a safeguard */
- parser->private_len = write - parser->private_dict;
- *write++ = 0;
+ parser->private_dict[len] = '\0';
}
+ else
+ /* binary encoding -- copy the private dict */
+ FT_MEM_COPY( parser->private_dict, cur, size );
}
/* we now decrypt the encoded binary private dictionary */
psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
+
+ /* replace the four random bytes at the beginning with whitespace */
+ parser->private_dict[0] = ' ';
+ parser->private_dict[1] = ' ';
+ parser->private_dict[2] = ' ';
+ parser->private_dict[3] = ' ';
+
parser->root.base = parser->private_dict;
parser->root.cursor = parser->private_dict;
parser->root.limit = parser->root.cursor + parser->private_len;
--- a/src/type1/t1parse.h
+++ b/src/type1/t1parse.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 parser (specification). */
/* */
-/* Copyright 1996-2001, 2002 by */
+/* Copyright 1996-2001, 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -69,9 +69,9 @@
FT_Byte* private_dict;
FT_Long private_len;
- FT_Byte in_pfb;
- FT_Byte in_memory;
- FT_Byte single_block;
+ FT_Bool in_pfb;
+ FT_Bool in_memory;
+ FT_Bool single_block;
} T1_ParserRec, *T1_Parser;
@@ -91,8 +91,8 @@
} while ( 0 )
-#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
-#define T1_Skip_Alpha( p ) (p)->root.funcs.skip_alpha ( &(p)->root )
+#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
+#define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root )
#define T1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root )
#define T1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )
--- a/src/type42/t42parse.c
+++ b/src/type42/t42parse.c
@@ -111,8 +111,8 @@
(p)->funcs.release( p ); \
} while ( 0 )
-#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
-#define T1_Skip_Alpha( p ) (p)->root.funcs.skip_alpha ( &(p)->root )
+#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
+#define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root )
#define T1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root )
#define T1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )
@@ -318,7 +318,7 @@
/* if we have a number, then the encoding is an array, */
/* and we must load it now */
- if ( (FT_Byte)( *cur - '0' ) < 10 )
+ if ( ft_isdigit( *cur ) )
{
T1_Encoding encode = &face->type1.encoding;
FT_Int count, n;
@@ -394,7 +394,7 @@
}
/* otherwise, we must find a number before anything else */
- if ( (FT_Byte)( c - '0' ) < 10 )
+ if ( ft_isdigit( c ) )
{
FT_Int charcode;
@@ -571,7 +571,7 @@
}
default:
- if ( !ft_xdigit( *cur ) || !ft_xdigit( *(cur + 1) ) )
+ if ( !ft_isxdigit( *cur ) || !ft_isxdigit( *(cur + 1) ) )
{
FT_ERROR(( "t42_parse_sfnts: found non-hex characters in string" ));
error = T42_Err_Invalid_File_Format;
@@ -705,7 +705,7 @@
break;
if ( *cur != '/' )
- T1_Skip_Alpha( parser );
+ T1_Skip_PS_Token( parser );
else
{
FT_Byte* cur2 = cur + 1;