ref: 1a380e02d1668d559a073d75200e3866d37b8e4d
parent: 4af3c4d7ee1de7d4e7591578092cac4f1a124d49
author: Werner Lemberg <[email protected]>
date: Fri Jul 14 14:28:08 EDT 2006
* freetype2/include/freetype/internal/psaux.h: New macros IS_PS_NEWLINE, IS_PS_SPACE, IS_PS_SPECIAL, IS_PS_DELIM, IS_PS_DIGIT, IS_PS_XDIGIT, and IS_PS_BASE85 (from freetype2/src/psaux/psconv.h). (T1_FieldLocation): Add T1_FIELD_LOCATION_LOADER, T1_FIELD_LOCATION_FACE, and T1_FIELD_LOCATION_BLEND. (T1_DecoderRec): New fields `buildchar' and `face'. (IS_PS_TOKEN): New macro. * freetype2/include/freetype/internal/t1types.h (T1_FaceRec): New fields `ndv_idx', `cdv_idx', and `len_buildchar'. * freetype2/include/freetype/t1tables.h (PS_BlendRec): New fields `default_design_vector' and `num_default_design_vector'. * freetype2/src/psaux/psconv.h: Move macros IS_PS_NEWLINE, IS_PS_SPACE, IS_PS_SPECIAL, IS_PS_DELIM, IS_PS_DIGIT, IS_PS_XDIGIT, and IS_PS_BASE85 to freetype2/include/freetype/internal/psaux.h. * freetype2/src/psaux/psobjs.c (ps_parser_to_token_array): Allow `token' argument to be NULL if we want only to count the number of tokens. (ps_tocoordarray): Allow `coords' argument to be NULL if we just want to skip the array. (ps_tofixedarray): Allow `values' argument to be NULL if we just want to skip the array. * freetype2/src/psaux/t1decode.c (t1_decoder_parse_charstrings): Add support for (partially commented out) othersubrs 19-25, 27, and 28. (t1_decoder_init): Initialize new fields `face' and `buildchar'. (t1_decoder_done): Release new field `buildchar'. * freetype2/src/type1/t1load.c (parse_buildchar, parse_private): New functions. (t1_keywords): Register them. (t1_allocate_blend): Updated. (t1_load_keyword): Handle field types T1_FIELD_LOCATION_LOADER, T1_FIELD_LOCATION_FACE and T1_FIELD_LOCATION_BLEND. (parse_dict): Remove `keyword_flags' argument. Use new macro IS_PS_TOKEN. Changed function so that later PostScript definitions override earlier ones. (t1_init_loader): Initialize new field `keywords_encountered'. (T1_Open_Face): Initialize new fields `ndv_idx', `cdv_idx', and `len_buildchar'. Remove `keywords_flags'. * freetype2/src/type1/t1load.h (T1_LoaderRect): New field `keywords_encountered'. (T1_PRIVATE, T1_FONTDIR_AFTER_PRIVATE): New macros. * freetype2/src/type1/t1tokens.h [!T1_CONFIG_OPTION_NO_MM_SUPPORT]: New entries for parsing /NDV, /CDV, and /DesignVector.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+2006-07-14 Jens Claudius <[email protected]>
+
+ * freetype2/include/freetype/internal/psaux.h: New macros
+ IS_PS_NEWLINE, IS_PS_SPACE, IS_PS_SPECIAL, IS_PS_DELIM, IS_PS_DIGIT,
+ IS_PS_XDIGIT, and IS_PS_BASE85 (from freetype2/src/psaux/psconv.h).
+ (T1_FieldLocation): Add T1_FIELD_LOCATION_LOADER,
+ T1_FIELD_LOCATION_FACE, and T1_FIELD_LOCATION_BLEND.
+ (T1_DecoderRec): New fields `buildchar' and `face'.
+ (IS_PS_TOKEN): New macro.
+
+ * freetype2/include/freetype/internal/t1types.h (T1_FaceRec): New
+ fields `ndv_idx', `cdv_idx', and `len_buildchar'.
+
+ * freetype2/include/freetype/t1tables.h (PS_BlendRec): New fields
+ `default_design_vector' and `num_default_design_vector'.
+
+ * freetype2/src/psaux/psconv.h: Move macros IS_PS_NEWLINE,
+ IS_PS_SPACE, IS_PS_SPECIAL, IS_PS_DELIM, IS_PS_DIGIT, IS_PS_XDIGIT,
+ and IS_PS_BASE85 to freetype2/include/freetype/internal/psaux.h.
+
+ * freetype2/src/psaux/psobjs.c (ps_parser_to_token_array): Allow
+ `token' argument to be NULL if we want only to count the number of
+ tokens.
+ (ps_tocoordarray): Allow `coords' argument to be NULL if we just
+ want to skip the array.
+ (ps_tofixedarray): Allow `values' argument to be NULL if we just
+ want to skip the array.
+
+ * freetype2/src/psaux/t1decode.c (t1_decoder_parse_charstrings): Add
+ support for (partially commented out) othersubrs 19-25, 27, and 28.
+ (t1_decoder_init): Initialize new fields `face' and `buildchar'.
+ (t1_decoder_done): Release new field `buildchar'.
+
+ * freetype2/src/type1/t1load.c (parse_buildchar, parse_private): New
+ functions.
+ (t1_keywords): Register them.
+ (t1_allocate_blend): Updated.
+ (t1_load_keyword): Handle field types T1_FIELD_LOCATION_LOADER,
+ T1_FIELD_LOCATION_FACE and T1_FIELD_LOCATION_BLEND.
+ (parse_dict): Remove `keyword_flags' argument.
+ Use new macro IS_PS_TOKEN.
+ Changed function so that later PostScript definitions override
+ earlier ones.
+ (t1_init_loader): Initialize new field `keywords_encountered'.
+ (T1_Open_Face): Initialize new fields `ndv_idx', `cdv_idx', and
+ `len_buildchar'.
+ Remove `keywords_flags'.
+
+ * freetype2/src/type1/t1load.h (T1_LoaderRect): New field
+ `keywords_encountered'.
+ (T1_PRIVATE, T1_FONTDIR_AFTER_PRIVATE): New macros.
+
+ * freetype2/src/type1/t1tokens.h [!T1_CONFIG_OPTION_NO_MM_SUPPORT]:
+ New entries for parsing /NDV, /CDV, and /DesignVector.
+
2006-07-07 Werner Lemberg <[email protected]>
Add many checks to protect against malformed PCF files.
--- a/include/freetype/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
@@ -199,6 +199,9 @@
T1_FIELD_LOCATION_FONT_INFO,
T1_FIELD_LOCATION_PRIVATE,
T1_FIELD_LOCATION_BBOX,
+ T1_FIELD_LOCATION_LOADER,
+ T1_FIELD_LOCATION_FACE,
+ T1_FIELD_LOCATION_BLEND,
/* do not remove */
T1_FIELD_LOCATION_MAX
@@ -683,6 +686,10 @@
T1_Decoder_Callback parse_callback;
T1_Decoder_FuncsRec funcs;
+ FT_Int* buildchar;
+
+ T1_Face face;
+
} T1_DecoderRec;
@@ -712,8 +719,10 @@
} AFM_Parser_FuncsRec;
+
typedef struct AFM_StreamRec_* AFM_Stream;
+
/*************************************************************************/
/* */
/* <Struct> */
@@ -800,6 +809,57 @@
/* backwards-compatible type definition */
typedef PSAux_ServiceRec PSAux_Interface;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Some convenience functions *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define IS_PS_NEWLINE( ch ) \
+ ( (ch) == '\r' || \
+ (ch) == '\n' )
+
+#define IS_PS_SPACE( ch ) \
+ ( (ch) == ' ' || \
+ IS_PS_NEWLINE( ch ) || \
+ (ch) == '\t' || \
+ (ch) == '\f' || \
+ (ch) == '\0' )
+
+#define IS_PS_SPECIAL( ch ) \
+ ( (ch) == '/' || \
+ (ch) == '(' || (ch) == ')' || \
+ (ch) == '<' || (ch) == '>' || \
+ (ch) == '[' || (ch) == ']' || \
+ (ch) == '{' || (ch) == '}' || \
+ (ch) == '%' )
+
+#define IS_PS_DELIM( ch ) \
+ ( IS_PS_SPACE( ch ) || \
+ IS_PS_SPECIAL( ch ) )
+
+#define IS_PS_DIGIT( ch ) \
+ ( (ch) >= '0' && (ch) <= '9' )
+
+#define IS_PS_XDIGIT( ch ) \
+ ( IS_PS_DIGIT( ch ) || \
+ ( (ch) >= 'A' && (ch) <= 'F' ) || \
+ ( (ch) >= 'a' && (ch) <= 'f' ) )
+
+#define IS_PS_BASE85( ch ) \
+ ( (ch) >= '!' && (ch) <= 'u' )
+
+#define IS_PS_TOKEN( cur, limit, token ) \
+ ( (char)(cur)[0] == (token)[0] && \
+ ( (cur) + sizeof ( (token) ) == (limit) || \
+ ( (cur) + sizeof( (token) ) < (limit) && \
+ IS_PS_DELIM( (cur)[sizeof ( (token) ) - 1] ) ) ) && \
+ ft_strncmp( (char*)(cur), (token), sizeof ( (token) ) - 1 ) == 0 )
+
FT_END_HEADER
--- a/include/freetype/internal/t1types.h
+++ b/include/freetype/internal/t1types.h
@@ -208,6 +208,16 @@
/* support for Multiple Masters fonts */
PS_Blend blend;
+ /* undocumented, optional: indices of subroutines that express */
+ /* the NormalizeDesignVector and the ConvertDesignVector procedure, */
+ /* respectively, as Type 2 charstrings; -1 if keywords not present */
+ FT_Int ndv_idx;
+ FT_Int cdv_idx;
+
+ /* undocumented, optional: has the same meaning as len_buildchar */
+ /* for Type 2 fonts; manipulated by othersubrs 19, 24, and 25 */
+ FT_UInt len_buildchar;
+
/* since version 2.1 - interface to PostScript hinter */
const void* pshinter;
--- a/include/freetype/t1tables.h
+++ b/include/freetype/t1tables.h
@@ -5,7 +5,7 @@
/* Basic Type 1/Type 2 tables definitions and interface (specification */
/* only). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004 by */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -255,6 +255,15 @@
FT_ULong blend_bitflags;
FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1];
+
+ /* since 2.2.2 */
+
+ /* undocumented, optional: the default design instance; */
+ /* corresponds to default_weight_vector -- */
+ /* num_default_design_vector == 0 means it is not present */
+ /* in the font and associated metrics files */
+ FT_UInt default_design_vector[T1_MAX_MM_DESIGNS];
+ FT_UInt num_default_design_vector;
} PS_BlendRec, *PS_Blend;
--- a/src/psaux/psconv.h
+++ b/src/psaux/psconv.h
@@ -63,42 +63,6 @@
FT_UShort* seed );
-#define IS_PS_NEWLINE( ch ) \
- ( ( ch ) == '\r' || \
- ( ch ) == '\n' )
-
-#define IS_PS_SPACE( ch ) \
- ( ( ch ) == ' ' || \
- IS_PS_NEWLINE( ch ) || \
- ( ch ) == '\t' || \
- ( ch ) == '\f' || \
- ( ch ) == '\0' )
-
-#define IS_PS_SPECIAL( ch ) \
- ( ( ch ) == '/' || \
- ( ch ) == '(' || \
- ( ch ) == ')' || \
- ( ch ) == '<' || \
- ( ch ) == '>' || \
- ( ch ) == '[' || \
- ( ch ) == ']' || \
- ( ch ) == '{' || \
- ( ch ) == '}' || \
- ( ch ) == '%' )
-
-#define IS_PS_DELIM( ch ) \
- ( IS_PS_SPACE( ch ) || \
- IS_PS_SPECIAL( ch ) )
-
-#define IS_PS_DIGIT( ch ) ( ( ch ) >= '0' && ( ch ) <= '9' )
-
-#define IS_PS_XDIGIT( ch ) \
- ( IS_PS_DIGIT( ( ch ) ) || \
- ( ( ch ) >= 'A' && ( ch ) <= 'F' ) || \
- ( ( ch ) >= 'a' && ( ch ) <= 'f' ) )
-
-#define IS_PS_BASE85( ch ) ( ( ch ) >= '!' && ( ch ) <= 'u' )
-
FT_END_HEADER
#endif /* __PSCONV_H__ */
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -698,6 +698,9 @@
}
+ /* NB: `tokens' can be NULL if we only want to count */
+ /* the number of array elements */
+
FT_LOCAL_DEF( void )
ps_parser_to_token_array( PS_Parser parser,
T1_Token tokens,
@@ -733,7 +736,7 @@
if ( !token.type )
break;
- if ( cur < limit )
+ if ( tokens != NULL && cur < limit )
*cur = token;
cur++;
@@ -748,6 +751,8 @@
/* first character must be a delimiter or a part of a number */
+ /* NB: `coords' can be NULL if we just want to skip the */
+ /* array; in this case we ignore `max_coords' */
static FT_Int
ps_tocoordarray( FT_Byte* *acur,
@@ -780,21 +785,26 @@
/* now, read the coordinates */
while ( cur < limit )
{
+ FT_Short dummy;
+
+
/* skip whitespace in front of data */
skip_spaces( &cur, limit );
if ( cur >= limit )
goto Exit;
- if ( count >= max_coords )
+ if ( coords != NULL && count >= max_coords )
break;
- if ( c == ender )
+ if ( *cur == ender )
{
cur++;
break;
}
- coords[count] =
+ /* call PS_Conv_ToFixed() even if coords == NULL */
+ /* to properly parse number at `cur' */
+ *( coords != NULL ? &coords[count] : &dummy ) =
(FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
count++;
@@ -809,6 +819,8 @@
/* first character must be a delimiter or a part of a number */
+ /* NB: `values' can be NULL if we just want to skip the */
+ /* array in this case we ignore `max_values' */
static FT_Int
ps_tofixedarray( FT_Byte* *acur,
@@ -842,21 +854,27 @@
/* now, read the values */
while ( cur < limit )
{
+ FT_Fixed dummy;
+
+
/* skip whitespace in front of data */
skip_spaces( &cur, limit );
if ( cur >= limit )
goto Exit;
- if ( count >= max_values )
+ if ( values != NULL && count >= max_values )
break;
- if ( c == ender )
+ if ( *cur == ender )
{
cur++;
break;
}
- values[count] = PS_Conv_ToFixed( &cur, limit, power_ten );
+ /* call PS_Conv_ToFixed() even if coords == NULL */
+ /* to properly parse number at `cur' */
+ *( values != NULL ? &values[count] : &dummy ) =
+ PS_Conv_ToFixed( &cur, limit, power_ten );
count++;
if ( !ender )
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -348,6 +348,14 @@
hinter = (T1_Hints_Funcs)builder->hints_funcs;
+ /* a font that reads BuildCharArray without setting */
+ /* its values first is buggy, but ... */
+ if ( decoder->face->len_buildchar > 0 )
+ memset( &decoder->buildchar[0],
+ 0,
+ sizeof( decoder->buildchar[0] ) *
+ decoder->face->len_buildchar );
+
FT_TRACE4(( "\nStart charstring\n" ));
zone->base = charstring_base;
@@ -582,12 +590,9 @@
subr_no = (FT_Int)top[1];
arg_cnt = (FT_Int)top[0];
- if ( arg_cnt > top - decoder->stack )
- goto Stack_Underflow;
-
/***********************************************************/
/* */
- /* remove all operands to callsubr from the stack */
+ /* remove all operands to callothersubr from the stack */
/* */
/* for handled othersubrs, where we know the number of */
/* arguments, we increase the stack by the value of */
@@ -596,11 +601,30 @@
/* for unhandled othersubrs the following pops adjust the */
/* stack pointer as necessary */
+ if ( arg_cnt > top - decoder->stack )
+ goto Stack_Underflow;
+
top -= arg_cnt;
known_othersubr_result_cnt = 0;
unknown_othersubr_result_cnt = 0;
+ /* XXX TODO: The checks to `arg_count == <whatever>' */
+ /* might not be correct; an othersubr expects a certain */
+ /* number of operands on the PostScript stack (as opposed */
+ /* to the T1 stack) but it doesn't have to put them there */
+ /* by itself; previous othersubrs might have left the */
+ /* operands there if they were not followed by an */
+ /* appropriate number of pops */
+ /* */
+ /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */
+ /* accept a font that contains charstrings like */
+ /* */
+ /* 100 200 2 20 callothersubr */
+ /* 300 1 20 callothersubr pop */
+ /* */
+ /* Perhaps this is the reason why BuildCharArray exists. */
+
switch ( subr_no )
{
case 1: /* start flex feature */
@@ -726,6 +750,158 @@
break;
}
+#ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS
+
+ /* We cannot yet enable these since currently */
+ /* our T1 stack stores integers which lack the */
+ /* precision to express the values */
+
+ case 19:
+ /* <idx> 1 19 callothersubr */
+ /* => replace elements starting from index cvi( <idx> ) */
+ /* of BuildCharArray with WeightVector */
+ {
+ FT_Int idx;
+ PS_Blend blend = decoder->blend;
+
+
+ if ( arg_cnt != 1 || blend == NULL )
+ goto Unexpected_OtherSubr;
+
+ idx = top[0];
+
+ if ( idx < 0 ||
+ idx + blend->num_designs > decoder->face->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ memcpy( &decoder->buildchar[idx],
+ blend->weight_vector,
+ blend->num_designs *
+ sizeof( blend->weight_vector[ 0 ] ) );
+ }
+ break;
+
+ case 20:
+ /* <arg1> <arg2> 2 20 callothersubr pop */
+ /* ==> push <arg1> + <arg2> onto T1 stack */
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ top[0] += top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+ case 21:
+ /* <arg1> <arg2> 2 21 callothersubr pop */
+ /* ==> push <arg1> - <arg2> onto T1 stack */
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ top[0] -= top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+ case 22:
+ /* <arg1> <arg2> 2 22 callothersubr pop */
+ /* ==> push <arg1> * <arg2> onto T1 stack */
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ top[0] *= top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+ case 23:
+ /* <arg1> <arg2> 2 23 callothersubr pop */
+ /* ==> push <arg1> / <arg2> onto T1 stack */
+ if ( arg_cnt != 2 || top[1] == 0 )
+ goto Unexpected_OtherSubr;
+
+ top[0] /= top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+#endif /* CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS */
+
+ case 24:
+ /* <val> <idx> 2 24 callothersubr */
+ /* => set BuildCharArray[cvi( <idx> )] = <val> */
+ {
+ FT_Int idx;
+ PS_Blend blend = decoder->blend;
+
+ if ( arg_cnt != 2 || blend == NULL )
+ goto Unexpected_OtherSubr;
+
+ idx = top[1];
+
+ if ( idx < 0 || (FT_UInt) idx >= decoder->face->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ decoder->buildchar[idx] = top[0];
+ }
+ break;
+
+ case 25:
+ /* <idx> 1 25 callothersubr pop */
+ /* => push BuildCharArray[cvi( idx )] */
+ /* onto T1 stack */
+ {
+ FT_Int idx;
+ PS_Blend blend = decoder->blend;
+
+ if ( arg_cnt != 1 || blend == NULL )
+ goto Unexpected_OtherSubr;
+
+ idx = top[0];
+
+ if ( idx < 0 || (FT_UInt) idx >= decoder->face->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ top[0] = decoder->buildchar[idx];
+ }
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+#if 0
+ case 26:
+ /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */
+ /* leave mark on T1 stack */
+ /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */
+ XXX who has left his mark on the (PostScript) stack ?;
+ break;
+#endif
+
+ case 27:
+ /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
+ /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
+ /* otherwise push <res2> */
+ if ( arg_cnt != 4 )
+ goto Unexpected_OtherSubr;
+
+ if ( top[2] > top[3] )
+ top[0] = top[1];
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+#ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS
+ case 28:
+ /* 0 28 callothersubr pop */
+ /* => push random value from interval [0, 1) onto stack */
+ if ( arg_cnt != 0 )
+ goto Unexpected_OtherSubr;
+
+ top[0] = FT_rand();
+ known_othersubr_result_cnt = 1;
+ break;
+#endif
+
default:
FT_ERROR(( "t1_decoder_parse_charstrings: "
"unknown othersubr [%d %d], wish me luck!\n",
@@ -805,8 +981,30 @@
/* add current outline to the glyph slot */
FT_GlyphLoader_Add( builder->loader );
+ FT_TRACE4(( "\n" ));
+
+ /* the compiler should optimize away this empty loop but ... */
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+ if ( decoder->face->len_buildchar > 0 )
+ {
+ FT_UInt i;
+
+
+ FT_TRACE4(( "BuildCharArray = [ " ));
+
+ for ( i = 0; i < decoder->face->len_buildchar; ++i )
+ FT_TRACE4(( "%d ", decoder->buildchar[ i ] ));
+
+ FT_TRACE4(( "]\n" ));
+ }
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ FT_TRACE4(( "\n" ));
+
/* return now! */
- FT_TRACE4(( "\n\n" ));
return PSaux_Err_Ok;
case op_hsbw:
@@ -1225,6 +1423,10 @@
FT_Render_Mode hint_mode,
T1_Decoder_Callback parse_callback )
{
+ FT_Error error;
+ FT_Memory memory = face->memory;
+
+
FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
/* retrieve PSNames interface from list of current modules */
@@ -1243,6 +1445,18 @@
decoder->psnames = psnames;
}
+ decoder->face = (T1_Face) face;
+
+ if ( decoder->face->len_buildchar > 0 )
+ {
+ if ( FT_NEW_ARRAY( decoder->buildchar, decoder->face->len_buildchar ) )
+ {
+ FT_ERROR(( "t1_decoder_init: " ));
+ FT_ERROR(( "cannot allocate memory for BuildCharArray\n" ));
+ return error;
+ }
+ }
+
t1_builder_init( &decoder->builder, face, size, slot, hinting );
decoder->num_glyphs = (FT_UInt)face->num_glyphs;
@@ -1261,7 +1475,12 @@
FT_LOCAL_DEF( void )
t1_decoder_done( T1_Decoder decoder )
{
+ FT_Memory memory = decoder->face->root.memory;
+
+
t1_builder_done( &decoder->builder );
+
+ FT_FREE( decoder->buildchar );
}
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -107,6 +107,8 @@
if ( FT_NEW( blend ) )
goto Exit;
+ blend->num_default_design_vector = 0;
+
face->blend = blend;
}
@@ -877,6 +879,18 @@
}
+ /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */
+ /* we're only interested in the number of array elements */
+ static void
+ parse_buildchar( T1_Face face,
+ T1_Loader loader )
+ {
+ face->len_buildchar = T1_ToFixedArray( &loader->parser, 0, NULL, 0 );
+
+ return;
+ }
+
+
#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
@@ -950,6 +964,26 @@
}
break;
+ case T1_FIELD_LOCATION_LOADER:
+ dummy_object = loader;
+ objects = &dummy_object;
+ max_objects = 0;
+ break;
+
+ case T1_FIELD_LOCATION_FACE:
+ dummy_object = face;
+ objects = &dummy_object;
+ max_objects = 0;
+ break;
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ case T1_FIELD_LOCATION_BLEND:
+ dummy_object = face->blend;
+ objects = &dummy_object;
+ max_objects = 0;
+ break;
+#endif
+
default:
dummy_object = &face->type1;
objects = &dummy_object;
@@ -969,6 +1003,16 @@
}
+ static void
+ parse_private( T1_Face face,
+ T1_Loader loader )
+ {
+ FT_UNUSED( face );
+
+ loader->keywords_encountered |= T1_PRIVATE;
+ }
+
+
static int
is_space( FT_Byte c )
{
@@ -1681,6 +1725,7 @@
T1_FIELD_CALLBACK( "Encoding", parse_encoding )
T1_FIELD_CALLBACK( "Subrs", parse_subrs )
T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
+ T1_FIELD_CALLBACK( "Private", parse_private )
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions )
@@ -1687,6 +1732,7 @@
T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map )
T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types )
T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector )
+ T1_FIELD_CALLBACK( "BuildCharArray", parse_buildchar )
#endif
{ 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
@@ -1701,8 +1747,7 @@
parse_dict( T1_Face face,
T1_Loader loader,
FT_Byte* base,
- FT_Long size,
- FT_Byte* keyword_flags )
+ FT_Long size )
{
T1_Parser parser = &loader->parser;
FT_Byte *limit, *start_binary = NULL;
@@ -1724,31 +1769,23 @@
cur = parser->root.cursor;
- /* cur[5] must be a token delimiter; */
- /* eexec encryption is optional, so look for `eexec' */
- if ( *cur == 'e' && cur + 5 < limit &&
- ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
+ /* look for `eexec' */
+ if ( IS_PS_TOKEN( cur, limit, "eexec" ) )
break;
- /* cur[9] must be a token delimiter; */
/* look for `closefile' which ends the eexec section */
- else if ( *cur == 'c' && cur + 9 < limit &&
- ft_strncmp( (char*)cur, "closefile", 9 ) == 0 )
+ else if ( IS_PS_TOKEN( cur, limit, "closefile" ) )
break;
-#ifdef TO_BE_DONE
/* in a synthetic font the base font starts after a */
/* `FontDictionary' token that is placed after a Private dict */
-
- /* cur[13] must be a token delimiter */
- else if ( *cur == 'F' && cur + 13 < limit &&
- ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
+ else if ( IS_PS_TOKEN( cur, limit, "FontDirectory" ) )
{
- if ( loader->private_encountered )
- loader->fontdir_after_private = 1;
+ if ( loader->keywords_encountered & T1_PRIVATE )
+ loader->keywords_encountered |=
+ T1_FONTDIR_AFTER_PRIVATE;
parser->root.cursor += 13;
}
-#endif
/* check whether we have an integer */
else if ( ft_isdigit( *cur ) )
@@ -1807,8 +1844,7 @@
if ( len > 0 && len < 22 && parser->root.cursor < limit )
{
/* now compare the immediate name to the keyword table */
- T1_Field keyword = (T1_Field)t1_keywords;
- FT_Byte* keyword_flag = keyword_flags;
+ T1_Field keyword = (T1_Field)t1_keywords;
for (;;)
@@ -1824,21 +1860,28 @@
len == (FT_PtrDist)ft_strlen( (const char *)name ) &&
ft_memcmp( cur, name, len ) == 0 )
{
- /* We found it -- run the parsing callback! */
- /* We only record the first instance of any */
- /* field to deal adequately with synthetic */
- /* fonts; /Subrs and /CharStrings are */
- /* handled specially. */
- if ( keyword_flag[0] == 0 ||
- ft_strcmp( (const char*)name, "Subrs" ) == 0 ||
- ft_strcmp( (const char*)name, "CharStrings" ) == 0 )
+ /* We found it -- run the parsing callback! */
+ /* We record every instance of every field */
+ /* (until we reach the base font of a */
+ /* synthetic font) to deal adequately with */
+ /* multiple master fonts; this is also */
+ /* necessary because later PostScript */
+ /* definitions override earlier ones */
+
+ /* Once we encounter `FontDirectory' after */
+ /* `/Private', we know that this is a synthetic */
+ /* font; except for `/CharStrings' we are not */
+ /* interested in anything that follows this */
+ /* `FontDirectory' */
+
+ if ( !( loader->keywords_encountered &
+ T1_FONTDIR_AFTER_PRIVATE ) ||
+ ft_strcmp((const char*)name, "CharStrings") == 0 )
{
parser->root.error = t1_load_keyword( face,
loader,
keyword );
- if ( parser->root.error == T1_Err_Ok )
- keyword_flag[0] = 1;
- else
+ if ( parser->root.error != T1_Err_Ok )
{
if ( FT_ERROR_BASE( parser->root.error ) == FT_Err_Ignore )
parser->root.error = T1_Err_Ok;
@@ -1850,7 +1893,6 @@
}
keyword++;
- keyword_flag++;
}
}
@@ -1883,12 +1925,13 @@
loader->num_chars = 0;
/* initialize the tables -- simply set their `init' field to 0 */
- loader->encoding_table.init = 0;
- loader->charstrings.init = 0;
- loader->glyph_names.init = 0;
- loader->subrs.init = 0;
- loader->swap_table.init = 0;
- loader->fontdata = 0;
+ loader->encoding_table.init = 0;
+ loader->charstrings.init = 0;
+ loader->glyph_names.init = 0;
+ loader->subrs.init = 0;
+ loader->swap_table.init = 0;
+ loader->fontdata = 0;
+ loader->keywords_encountered = 0;
}
@@ -1918,7 +1961,6 @@
T1_Font type1 = &face->type1;
PS_Private priv = &type1->private_dict;
FT_Error error;
- FT_Byte keyword_flags[T1_FIELD_COUNT];
PSAux_Service psaux = (PSAux_Service)face->psaux;
@@ -1926,6 +1968,10 @@
t1_init_loader( &loader, face );
/* default values */
+ face->ndv_idx = -1;
+ face->cdv_idx = -1;
+ face->len_buildchar = 0;
+
priv->blue_shift = 7;
priv->blue_fuzz = 1;
priv->lenIV = 4;
@@ -1940,16 +1986,8 @@
if ( error )
goto Exit;
- {
- FT_UInt n;
-
-
- for ( n = 0; n < T1_FIELD_COUNT; n++ )
- keyword_flags[n] = 0;
- }
-
- error = parse_dict( face, &loader, parser->base_dict, parser->base_len,
- keyword_flags );
+ error = parse_dict( face, &loader,
+ parser->base_dict, parser->base_len );
if ( error )
goto Exit;
@@ -1957,9 +1995,8 @@
if ( error )
goto Exit;
- error = parse_dict( face, &loader, parser->private_dict,
- parser->private_len,
- keyword_flags );
+ error = parse_dict( face, &loader,
+ parser->private_dict, parser->private_len );
if ( error )
goto Exit;
@@ -1967,6 +2004,19 @@
priv->num_blue_values &= ~1;
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+ if ( face->blend &&
+ face->blend->num_default_design_vector != 0 &&
+ face->blend->num_default_design_vector != face->blend->num_axis )
+ {
+ /* we don't use it currently so just warn, reset, and ignore */
+ FT_ERROR(( "T1_Open_Face(): /DesignVector contains %u entries "
+ "while there are %u axes.\n",
+ face->blend->num_default_design_vector,
+ face->blend->num_axis ));
+
+ face->blend->num_default_design_vector = 0;
+ }
/* the following can happen for MM instances; we then treat the */
/* font as a normal PS font */
--- a/src/type1/t1load.h
+++ b/src/type1/t1load.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 font loader (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2004 by */
+/* Copyright 1996-2001, 2002, 2004, 2006 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -48,7 +48,16 @@
PS_TableRec subrs;
FT_Bool fontdata;
+ FT_UInt keywords_encountered; /* T1_LOADER_ENCOUNTERED_XXX */
+
} T1_LoaderRec, *T1_Loader;
+
+
+ /* treatment of some keywords differs depending on whether */
+ /* they preceed or follow certain other keywords */
+
+#define T1_PRIVATE ( 1 << 0 )
+#define T1_FONTDIR_AFTER_PRIVATE ( 1 << 1 )
FT_LOCAL( FT_Error )
--- a/src/type1/t1tokens.h
+++ b/src/type1/t1tokens.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 tokenizer (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004 by */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -73,6 +73,7 @@
T1_FIELD_NUM ( "FontType", font_type )
T1_FIELD_FIXED( "StrokeWidth", stroke_width )
+
#undef FT_STRUCTURE
#define FT_STRUCTURE FT_BBox
#undef T1CODE
@@ -79,6 +80,28 @@
#define T1CODE T1_FIELD_LOCATION_BBOX
T1_FIELD_BBOX("FontBBox", xMin )
+
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE T1_FaceRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_FACE
+
+ T1_FIELD_NUM ( "NDV", ndv_idx )
+ T1_FIELD_NUM ( "CDV", cdv_idx )
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PS_BlendRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_BLEND
+
+ T1_FIELD_NUM_TABLE( "DesignVector", default_design_vector, T1_MAX_MM_DESIGNS )
+
+
+#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
/* END */