ref: 1c9a1cab3f6f5d3387094726e5958a29afd2e2c2
parent: 1fb6eea7d12ca6fe6649cfee191dc56240f8cc89
author: David Turner <[email protected]>
date: Wed May 24 17:12:02 EDT 2000
important modifications to the Type1z driver these are used to prepare for multiple master fonts
--- a/include/freetype/internal/t1types.h
+++ b/include/freetype/internal/t1types.h
@@ -29,7 +29,6 @@
#endif
-
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
@@ -391,6 +390,9 @@
FT_CharMapRec charmaprecs[2];
FT_CharMap charmaps[2];
PS_Unicodes unicode_map;
+
+ /* support for multiple masters */
+ T1_Blend* blend;
} T1_FaceRec;
--- a/include/freetype/t1tables.h
+++ b/include/freetype/t1tables.h
@@ -84,8 +84,8 @@
FT_Int blue_shift;
FT_Int blue_fuzz;
- FT_UShort standard_width;
- FT_UShort standard_height;
+ FT_UShort standard_width[1];
+ FT_UShort standard_height[1];
FT_Byte num_snap_widths;
FT_Byte num_snap_heights;
@@ -116,10 +116,8 @@
*/
typedef enum
{
- t1_blend_none = 0,
-
/* required fields in a FontInfo blend dictionary */
- t1_blend_underline_position,
+ t1_blend_underline_position = 0,
t1_blend_underline_thickness,
t1_blend_italic_angle,
@@ -139,38 +137,35 @@
/* never remove */
t1_blend_max
- } T1_Flags;
+ } T1_Blend_Flags;
+ /* maximum number of multiple-masters designs, per-se the spec */
+ #define T1_MAX_MM_DESIGNS 16
+ #define T1_MAX_MM_AXIS 4
- typedef struct T1_Blend_Pos
+ /* this structure is used to store the BlendDesignMap entry for an axis */
+ typedef struct T1_DesignMap_
{
- FT_Fixed min;
- FT_Fixed max;
+ FT_Byte num_points;
+ FT_Fixed* design_points;
+ FT_Fixed* blend_points;
+
+ } T1_DesignMap;
- } T1_Blend_Pos;
-
- /*************************************************************************
- *
- * <Struct>
- * T1_Blend
- *
- * <Description>
- * A structure used to describe the multiple-master fonts information
- * of a given Type 1 font.
- *
- */
typedef struct T1_Blend_
{
- FT_Int num_axis;
- FT_String* axis_types[4];
-
- /* XXXX : add /BlendDesignMap entries */
-
- FT_Int num_blends;
- T1_Flags* flags [17];
- T1_Private* privates [17];
- T1_FontInfo* fontinfos[17];
-
+ FT_UInt num_designs;
+ FT_UInt num_axis;
+
+ FT_String* axis_names[ T1_MAX_MM_AXIS ];
+ FT_Fixed* design_pos[ T1_MAX_MM_DESIGNS ];
+ T1_DesignMap design_map[ T1_MAX_MM_AXIS ];
+
+ T1_FontInfo* font_infos[ T1_MAX_MM_DESIGNS+1 ];
+ T1_Private* privates [ T1_MAX_MM_DESIGNS+1 ];
+
+ FT_ULong blend_bitflags;
+
} T1_Blend;
--- a/src/type1/t1hinter.c
+++ b/src/type1/t1hinter.c
@@ -291,7 +291,7 @@
/* start with horizontal snap zones */
direction = 0;
- standard_width = priv->standard_width;
+ standard_width = priv->standard_width[0];
n_zones = priv->num_snap_widths;
base_zone = hints->snap_widths;
orgs = priv->stem_snap_widths;
@@ -458,7 +458,7 @@
/* continue with vertical snap zone */
direction++;
- standard_width = priv->standard_height;
+ standard_width = priv->standard_height[0];
n_zones = priv->num_snap_heights;
base_zone = hints->snap_heights;
orgs = priv->stem_snap_heights;
--- a/src/type1/t1objs.c
+++ b/src/type1/t1objs.c
@@ -330,7 +330,7 @@
/* now compute the maximum advance width */
- root->max_advance_width = type1->private_dict.standard_width;
+ root->max_advance_width = type1->private_dict.standard_width[0];
/* compute max advance width for proportional fonts */
if (!type1->font_info.is_fixed_pitch)
--- a/src/type1z/t1load.c
+++ b/src/type1z/t1load.c
@@ -70,84 +70,314 @@
#undef FT_COMPONENT
#define FT_COMPONENT trace_t1load
+ /***************************************************************************/
+ /***************************************************************************/
+ /***** *****/
+ /***** MULTIPLE MASTERS SUPPORT *****/
+ /***** *****/
+ /***************************************************************************/
+ /***************************************************************************/
+
+ static T1_Error t1_allocate_blend( T1_Face face,
+ T1_UInt num_designs,
+ T1_UInt num_axis )
+ {
+ T1_Blend* blend;
+ FT_Memory memory = face->root.memory;
+ T1_Error error = 0;
+
+ blend = face->blend;
+ if (!blend)
+ {
+ if ( ALLOC( blend, sizeof(*blend) ) )
+ goto Exit;
+
+ face->blend = blend;
+ }
+
+ /* allocate design data if needed */
+ if (num_designs > 0)
+ {
+ if (blend->num_designs == 0)
+ {
+ /* allocate the blend "private" and "font_info" dictionaries */
+ if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo ) ||
+ ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private ) )
+ goto Exit;
+
+ blend->font_infos[0] = &face->type1.font_info;
+ blend->privates [0] = &face->type1.private_dict;
+ blend->num_designs = num_designs;
+ }
+ else if (blend->num_designs != num_designs)
+ goto Fail;
+ }
+
+ /* allocate axis data if needed */
+ if (num_axis > 0)
+ {
+ if (blend->num_axis != 0 && blend->num_axis != num_axis)
+ goto Fail;
+
+ blend->num_axis = num_axis;
+ }
+
+ /* allocate the blend design pos table if needed */
+ num_designs = blend->num_designs;
+ num_axis = blend->num_axis;
+ if ( num_designs && num_axis && blend->design_pos[0] == 0)
+ {
+ FT_UInt n;
+
+ if ( ALLOC_ARRAY( blend->design_pos[0], num_designs*num_axis, FT_Fixed ) )
+ goto Exit;
+
+ for ( n = 1; n < num_designs; n++ )
+ blend->design_pos[n] = blend->design_pos[0] + num_axis*n;
+ }
+
+ Exit:
+ return error;
+ Fail:
+ error = -1;
+ goto Exit;
+ }
+
+
+ static void t1_done_blend( T1_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ T1_Blend* blend = face->blend;
+
+ if (blend)
+ {
+ T1_UInt num_designs = blend->num_designs;
+ T1_UInt num_axis = blend->num_axis;
+ T1_UInt n;
+
+ /* release design pos table */
+ FREE( blend->design_pos[0] );
+ for ( n = 1; n < num_designs; n++ )
+ blend->design_pos[n] = 0;
+
+ /* release blend "private" and "font info" dictionaries */
+ FREE( blend->privates[1] );
+ FREE( blend->font_infos[1] );
+ for ( n = 0; n < num_designs; n++ )
+ {
+ blend->privates [n] = 0;
+ blend->font_infos[n] = 0;
+ }
+
+ /* release axis names */
+ for ( n = 0; n < num_axis; n++ )
+ FREE( blend->axis_names[n] );
+
+ /* release design map */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ T1_DesignMap* dmap = blend->design_map + n;
+ FREE( dmap->design_points );
+ FREE( dmap->blend_points );
+ dmap->num_points = 0;
+ }
+
+ FREE( face->blend );
+ }
+ }
+
+ /***************************************************************************/
+ /***************************************************************************/
+ /***** *****/
+ /***** TYPE 1 SYMBOL PARSING *****/
+ /***** *****/
+ /***************************************************************************/
+ /***************************************************************************/
+
+ /*********************************************************************
+ *
+ * First of all, define the token field static variables. This is
+ * a set of T1_Field_Rec variables used later..
+ *
+ *********************************************************************/
+
+#define T1_NEW_STRING( _name, _field ) \
+ static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_STRING( T1TYPE, _field );
+
+#define T1_NEW_BOOL( _name, _field ) \
+ static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_BOOL( T1TYPE, _field );
+
+#define T1_NEW_NUM( _name, _field ) \
+ static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_NUM( T1TYPE, _field );
+
+#define T1_NEW_FIXED( _name, _field ) \
+ static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_FIXED( T1TYPE, _field, _power );
+
+#define T1_NEW_NUM_TABLE( _name, _field, _max, _count ) \
+ static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max );
+
+#define T1_NEW_FIXED_TABLE( _name, _field, _max, _count ) \
+ static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max );
+
+#define T1_NEW_NUM_TABLE2( _name, _field, _max ) \
+ static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max );
+
+#define T1_NEW_FIXED_TABLE2( _name, _field, _max ) \
+ static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max );
+
+
+#define T1_FONTINFO_STRING(n,f) T1_NEW_STRING(n,f)
+#define T1_FONTINFO_NUM(n,f) T1_NEW_NUM(n,f)
+#define T1_FONTINFO_BOOL(n,f) T1_NEW_BOOL(n,f)
+#define T1_PRIVATE_NUM(n,f) T1_NEW_NUM(n,f)
+#define T1_PRIVATE_FIXED(n,f) T1_NEW_FIXED(n,f)
+#define T1_PRIVATE_NUM_TABLE(n,f,m,c) T1_NEW_NUM_TABLE(n,f,m,c)
+#define T1_PRIVATE_NUM_TABLE2(n,f,m) T1_NEW_NUM_TABLE2(n,f,m)
+#define T1_TOPDICT_NUM(n,f) T1_NEW_NUM(n,f)
+#define T1_TOPDICT_NUM_FIXED2(n,f,m) T1_NEW_FIXED_TABLE2(n,f,m)
+
+/* including this file defines all field variables */
+#include <t1tokens.h>
+
+ /*********************************************************************
+ *
+ * Second, define the keyword variables. This is a set of T1_KeyWord
+ * structures used to model the way each keyword is "loaded"..
+ *
+ *********************************************************************/
+
typedef void (*T1_Parse_Func)( T1_Face face, T1_Loader* loader );
+ typedef enum T1_KeyWord_Type_
+ {
+ t1_keyword_callback = 0,
+ t1_keyword_field,
+ t1_keyword_field_table
+
+ } T1_KeyWord_Type;
+
+ typedef enum T1_KeyWord_Location_
+ {
+ t1_keyword_type1 = 0,
+ t1_keyword_font_info,
+ t1_keyword_private
+
+ } T1_KeyWord_Location;
+
typedef struct T1_KeyWord_
{
- const char* name;
- T1_Parse_Func parsing;
+ const char* name;
+ T1_KeyWord_Type type;
+ T1_KeyWord_Location location;
+ T1_Parse_Func parsing;
+ const T1_Field_Rec* field;
} T1_KeyWord;
- /* some handy macros used to easily define parsing callback functions */
- /* each callback is in charge of loading a value and storing it in a */
- /* given field of the Type 1 face.. */
-#define PARSE_(x) static void FT_XCAT(parse_,x) ( T1_Face face, T1_Loader* loader )
+#define T1_KEYWORD_CALLBACK( name, callback ) \
+ { name, t1_keyword_callback, t1_keyword_type1, callback, 0 }
-#define FIELD FACE.x
+#define T1_KEYWORD_TYPE1( name, f ) \
+ { name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f }
+
+#define T1_KEYWORD_FONTINFO( name, f ) \
+ { name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f }
-#define PARSE_STRING(s,x) PARSE_(x) \
- { \
- FACE.x = T1_ToString(&loader->parser); \
- FT_TRACE2(( "type1.parse_%s: \"%s\"\n", #x, FACE.x )); \
- }
+#define T1_KEYWORD_PRIVATE( name, f ) \
+ { name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f }
-#define PARSE_NUM(s,x,t) PARSE_(x) \
- { \
- FACE.x = (t)T1_ToInt(&loader->parser); \
- FT_TRACE2(( "type1.parse_%s: \"%d\"\n", #x, FACE.x )); \
- }
+#define T1_KEYWORD_FONTINFO_TABLE( name, f ) \
+ { name, t1_keyword_field_table, t1_keyword_font_info, 0, &t1_field_ ## f }
-#define PARSE_INT(s,x) PARSE_(x) \
- { \
- FACE.x = T1_ToInt(&loader->parser); \
- FT_TRACE2(( "type1.parse_%s: \"%d\"\n", #x, FACE.x )); \
- }
+#define T1_KEYWORD_PRIVATE_TABLE( name, f ) \
+ { name, t1_keyword_field_table, t1_keyword_private, 0, &t1_field_ ## f }
-#define PARSE_BOOL(s,x) PARSE_(x) \
- { \
- FACE.x = T1_ToBool(&loader->parser); \
- FT_TRACE2(( "type1.parse_%s : \"%s\"\n", \
- #x, FACE.x ? "true" : "false" )); \
- }
+#undef T1_FONTINFO_STRING
+#undef T1_FONTINFO_NUM
+#undef T1_FONTINFO_BOOL
+#undef T1_PRIVATE_NUM
+#undef T1_PRIVATE_FIXED
+#undef T1_PRIVATE_NUM_TABLE
+#undef T1_PRIVATE_NUM_TABLE2
+#undef T1_TOPDICT_NUM
+#undef T1_TOPDICT_NUM_FIXED2
-#define PARSE_FIXED(s,x) PARSE_(x) \
- { \
- FACE.x = T1_ToFixed(&loader->parser,3); \
- FT_TRACE2(( "type1.parse_%s: \"%f\"\n", #x, FACE.x/65536.0 )); \
- }
+#define T1_FONTINFO_STRING(n,f) T1_KEYWORD_FONTINFO(n,f),
+#define T1_FONTINFO_NUM(n,f) T1_KEYWORD_FONTINFO(n,f),
+#define T1_FONTINFO_BOOL(n,f) T1_KEYWORD_FONTINFO(n,f),
+#define T1_PRIVATE_NUM(n,f) T1_KEYWORD_PRIVATE(n,f),
+#define T1_PRIVATE_FIXED(n,f) T1_KEYWORD_PRIVATE(n,f),
+#define T1_PRIVATE_NUM_TABLE(n,f,m,c) T1_KEYWORD_PRIVATE_TABLE(n,f),
+#define T1_PRIVATE_NUM_TABLE2(n,f,m) T1_KEYWORD_PRIVATE_TABLE(n,f),
+#define T1_TOPDICT_NUM(n,f) T1_KEYWORD_TYPE1(n,f),
+#define T1_TOPDICT_NUM_FIXED2(n,f,m) T1_KEYWORD_TYPE1(n,f),
-#define PARSE_COORDS(s,c,m,x) PARSE_(x) \
- { \
- FACE.c = T1_ToCoordArray(&loader->parser, m, (T1_Short*)FACE.x ); \
- FT_TRACE2(( "type1.parse_%s\n", #x )); \
- }
-#define PARSE_FIXEDS(s,c,m,x) PARSE_(x) \
- { \
- FACE.c = T1_ToFixedArray(&loader->parser, m, (T1_Fixed*)FACE.x, 3 ); \
- FT_TRACE2(( "type1.parse_%s\n", #x )); \
+ static T1_Error t1_load_keyword( T1_Face face,
+ T1_Loader* loader,
+ T1_KeyWord* keyword )
+ {
+ T1_Error error;
+ void* dummy_object;
+ void** objects;
+ T1_UInt max_objects;
+ T1_Blend* blend = face->blend;
+
+ /* if the keyword has a dedicated callback, call it */
+ if (keyword->type == t1_keyword_callback)
+ {
+ keyword->parsing( face, loader );
+ error = loader->parser.error;
+ goto Exit;
+ }
+
+ /* now, the keyword is either a simple field, or a table of fields */
+ /* we are now going to take care of it.. */
+ switch (keyword->location)
+ {
+ case t1_keyword_font_info:
+ {
+ dummy_object = &face->type1.font_info;
+ objects = &dummy_object;
+ max_objects = 0;
+ if (blend)
+ {
+ objects = (void**)blend->font_infos;
+ max_objects = blend->num_designs;
+ }
}
-
-
-#define PARSE_COORDS2(s,m,x) PARSE_(x) \
- { \
- (void)T1_ToCoordArray( &loader->parser, m, (T1_Short*)&FACE.x ); \
- FT_TRACE2(( "type1.parse_%s\n", #x )); \
+ break;
+
+ case t1_keyword_private:
+ {
+ dummy_object = &face->type1.private_dict;
+ objects = &dummy_object;
+ max_objects = 0;
+ if (blend)
+ {
+ objects = (void**)blend->privates;
+ max_objects = blend->num_designs;
+ }
}
+ break;
+
+ default:
+ dummy_object = &face->type1;
+ objects = &dummy_object;
+ max_objects = 0;
+ }
+
+ if (keyword->type == t1_keyword_field_table)
+ error = T1_Load_Field_Table( &loader->parser, keyword->field, objects, max_objects, 0 );
+ else
+ error = T1_Load_Field( &loader->parser, keyword->field, objects, max_objects, 0 );
+
+ Exit:
+ return error;
+ }
-#define PARSE_FIXEDS2(s,m,x) PARSE_(x) \
- { \
- (void)T1_ToFixedArray(&loader->parser, m, (T1_Fixed*)&FACE.x, 3 ); \
- FT_TRACE2(( "type1.parse_%s\n", #x )); \
- }
-
-/* define all parsing callbacks */
-#include <t1tokens.h>
-
-
static
int is_space( char c )
{
@@ -274,6 +504,22 @@
}
static
+ void parse_font_matrix( T1_Face face, T1_Loader* loader )
+ {
+ T1_Parser* parser = &loader->parser;
+ FT_Matrix* matrix = &face->type1.font_matrix;
+ T1_Fixed temp[4];
+
+ (void)T1_ToFixedArray( parser, 4, temp, 3 );
+ matrix->xx = temp[0];
+ matrix->yx = temp[1];
+ matrix->xy = temp[2];
+ matrix->yy = temp[3];
+ }
+
+
+
+ static
void parse_encoding( T1_Face face, T1_Loader* loader )
{
T1_Parser* parser = &loader->parser;
@@ -542,40 +788,21 @@
}
-#undef PARSE_STRING
-#undef PARSE_INT
-#undef PARSE_NUM
-#undef PARSE_BOOL
-#undef PARSE_FIXED
-#undef PARSE_COORDS
-#undef PARSE_FIXEDS
-#undef PARSE_COORDS2
-#undef PARSE_FIXEDS2
-#undef PARSE_
-#define PARSE_(s,x) { s, parse_##x },
-#define PARSE_STRING(s,x) PARSE_(s,x)
-#define PARSE_INT(s,x) PARSE_(s,x)
-#define PARSE_NUM(s,x,t) PARSE_(s,x)
-#define PARSE_BOOL(s,x) PARSE_(s,x)
-#define PARSE_FIXED(s,x) PARSE_(s,x)
-#define PARSE_COORDS(s,c,m,x) PARSE_(s,x)
-#define PARSE_FIXEDS(s,c,m,x) PARSE_(s,x)
-#define PARSE_COORDS2(s,m,x) PARSE_(s,x)
-#define PARSE_FIXEDS2(s,m,x) PARSE_(s,x)
-
static
const T1_KeyWord t1_keywords[] =
{
-#include <t1tokens.h>
+#include <t1tokens.h>
+
/* now add the special functions... */
- { "FontName", parse_font_name },
- { "FontBBox", parse_font_bbox },
- { "Encoding", parse_encoding },
- { "Subrs", parse_subrs },
- { "CharStrings", parse_charstrings },
- { 0, 0 }
+ T1_KEYWORD_CALLBACK( "FontName", parse_font_name ),
+ T1_KEYWORD_CALLBACK( "FontBBox", parse_font_bbox ),
+ T1_KEYWORD_CALLBACK( "FontMatrix", parse_font_matrix ),
+ T1_KEYWORD_CALLBACK( "Encoding", parse_encoding ),
+ T1_KEYWORD_CALLBACK( "Subrs", parse_subrs ),
+ T1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings ),
+ T1_KEYWORD_CALLBACK( 0, 0 )
};
@@ -585,7 +812,7 @@
T1_Byte* base,
T1_Long size )
{
- T1_Parser* parser = &loader->parser;
+ T1_Parser* parser = &loader->parser;
parser->cursor = base;
parser->limit = base + size;
@@ -597,8 +824,37 @@
for ( ;cur < limit; cur++ )
{
+ /* look for "FontDirectory", which causes problems on some fonts */
+ if ( *cur == 'F' && cur+25 < limit &&
+ strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
+ {
+ T1_Byte* cur2;
+
+ /* skip the "FontDirectory" keyword */
+ cur += 13;
+ cur2 = cur;
+
+ /* lookup the 'known' keyword */
+ while (cur < limit && *cur != 'k' && strncmp( (char*)cur, "known", 5 ) )
+ cur++;
+
+ if (cur < limit)
+ {
+ T1_Token_Rec token;
+
+ /* skip the "known" keyword and the token following it */
+ cur += 5;
+ loader->parser.cursor = cur;
+ T1_ToToken( &loader->parser, &token );
+
+ /* if the last token was an array, skip it !! */
+ if (token.type == t1_token_array)
+ cur2 = parser->cursor;
+ }
+ cur = cur2;
+ }
/* look for immediates */
- if (*cur == '/' && cur+2 < limit)
+ else if (*cur == '/' && cur+2 < limit)
{
T1_Byte* cur2;
T1_Int len;
@@ -610,38 +866,46 @@
if (len > 0 && len < 20)
{
- /* now, compare the immediate name to the keyword table */
- T1_KeyWord* keyword = (T1_KeyWord*)t1_keywords;
-
- for (;;)
+ if (!loader->fontdata)
{
- T1_Byte* name;
-
- name = (T1_Byte*)keyword->name;
- if (!name) break;
-
- if ( cur[0] == name[0] &&
- len == (T1_Int)strlen((const char*)name) )
+ if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 )
+ loader->fontdata = 1;
+ }
+ else
+ {
+ /* now, compare the immediate name to the keyword table */
+ T1_KeyWord* keyword = (T1_KeyWord*)t1_keywords;
+
+ for (;;)
{
- T1_Int n;
- for ( n = 1; n < len; n++ )
- if (cur[n] != name[n])
- break;
-
- if (n >= len)
+ T1_Byte* name;
+
+ name = (T1_Byte*)keyword->name;
+ if (!name) break;
+
+ if ( cur[0] == name[0] &&
+ len == (T1_Int)strlen((const char*)name) )
{
- /* we found it - run the parsing callback !! */
- parser->cursor = cur2;
- skip_whitespace( parser );
- keyword->parsing( face, loader );
- if (parser->error)
- return parser->error;
-
- cur = parser->cursor;
- break;
+ T1_Int n;
+ for ( n = 1; n < len; n++ )
+ if (cur[n] != name[n])
+ break;
+
+ if (n >= len)
+ {
+ /* we found it - run the parsing callback !! */
+ parser->cursor = cur2;
+ skip_whitespace( parser );
+ parser->error = t1_load_keyword( face, loader, keyword );
+ if (parser->error)
+ return parser->error;
+
+ cur = parser->cursor;
+ break;
+ }
}
+ keyword++;
}
- keyword++;
}
}
}
@@ -664,6 +928,7 @@
loader->charstrings.init = 0;
loader->glyph_names.init = 0;
loader->subrs.init = 0;
+ loader->fontdata = 0;
}
static
--- a/src/type1z/t1load.h
+++ b/src/type1z/t1load.h
@@ -39,6 +39,7 @@
T1_Int num_subrs;
T1_Table subrs;
+ T1_Bool fontdata;
} T1_Loader;
--- a/src/type1z/t1objs.c
+++ b/src/type1z/t1objs.c
@@ -298,7 +298,7 @@
/* now compute the maximum advance width */
- root->max_advance_width = face->type1.private_dict.standard_width;
+ root->max_advance_width = face->type1.private_dict.standard_width[0];
/* compute max advance width for proportional fonts */
if (!face->type1.font_info.is_fixed_pitch)
--- a/src/type1z/t1parse.c
+++ b/src/type1z/t1parse.c
@@ -39,6 +39,18 @@
#define FT_COMPONENT trace_t1load
/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+/***** *****/
+/***** IMPLEMENTATION OF T1_TABLE OBJECT *****/
+/***** *****/
+/***** *****/
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+
+
+/*************************************************************************/
/* */
/* <Function> T1_New_Table */
/* */
@@ -221,6 +233,163 @@
}
}
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+/***** *****/
+/***** INPUT STREAM PARSER *****/
+/***** *****/
+/***** *****/
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+
+ #define IS_T1_WHITESPACE(c) ( (c) == ' ' || (c) == '\t' )
+ #define IS_T1_LINESPACE(c) ( (c) == '\r' || (c) == '\n' )
+
+ #define IS_T1_SPACE(c) ( IS_T1_WHITESPACE(c) || IS_T1_LINESPACE(c) )
+
+ LOCAL_FUNC
+ void T1_Skip_Spaces( T1_Parser* parser )
+ {
+ T1_Byte* cur = parser->cursor;
+ T1_Byte* limit = parser->limit;
+
+ while (cur < limit)
+ {
+ T1_Byte c = *cur;
+ if (!IS_T1_SPACE(c))
+ break;
+ cur++;
+ }
+ parser->cursor = cur;
+ }
+
+ LOCAL_FUNC
+ void T1_ToToken( T1_Parser* parser,
+ T1_Token_Rec* token )
+ {
+ T1_Byte* cur;
+ T1_Byte* limit;
+ T1_Byte starter, ender;
+ T1_Int embed;
+
+ token->type = t1_token_none;
+ token->start = 0;
+ token->limit = 0;
+
+ /* first of all, skip space */
+ T1_Skip_Spaces(parser);
+
+ cur = parser->cursor;
+ limit = parser->limit;
+
+ if ( cur < limit )
+ {
+ switch (*cur)
+ {
+ /************* check for strings ***********************/
+ case '(':
+ token->type = t1_token_string;
+ ender = ')';
+ goto Lookup_Ender;
+
+ /************* check for programs/array ****************/
+ case '{':
+ token->type = t1_token_array;
+ ender = '}';
+ goto Lookup_Ender;
+
+ /************* check for table/array ******************/
+ case '[':
+ token->type = t1_token_array;
+ ender = ']';
+
+ Lookup_Ender:
+ embed = 1;
+ starter = *cur++;
+ token->start = cur;
+ while (cur < limit)
+ {
+ if (*cur == starter)
+ embed++;
+ else if (*cur == ender)
+ {
+ embed--;
+ if (embed <= 0)
+ {
+ token->limit = cur++;
+ break;
+ }
+ }
+ cur++;
+ }
+ break;
+
+ /* **************** otherwise, it's any token **********/
+ default:
+ token->start = cur++;
+ token->type = t1_token_any;
+ while (cur < limit && !IS_T1_SPACE(*cur))
+ cur++;
+
+ token->limit = cur;
+ }
+
+ if (!token->limit)
+ {
+ token->start = 0;
+ token->type = t1_token_none;
+ }
+
+ parser->cursor = cur;
+ }
+ }
+
+
+ LOCAL_FUNC
+ void T1_ToTokenArray( T1_Parser* parser,
+ T1_Token_Rec* tokens,
+ T1_UInt max_tokens,
+ T1_Int *pnum_tokens )
+ {
+ T1_Token_Rec master;
+
+ *pnum_tokens = -1;
+
+ T1_ToToken( parser, &master );
+ if (master.type == t1_token_array)
+ {
+ T1_Byte* old_cursor = parser->cursor;
+ T1_Byte* old_limit = parser->limit;
+ T1_Token_Rec* cur = tokens;
+ T1_Token_Rec* limit = cur + max_tokens;
+
+ parser->cursor = master.start;
+ parser->limit = master.limit;
+
+ while (parser->cursor < parser->limit)
+ {
+ T1_Token_Rec token;
+
+ T1_ToToken( parser, &token );
+ if (!token.type)
+ break;
+
+ if (cur < limit)
+ *cur = token;
+
+ cur++;
+ }
+
+ *pnum_tokens = cur - tokens;
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+ }
+ }
+
+
static
T1_Long t1_toint( T1_Byte* *cursor,
T1_Byte* limit )
@@ -533,7 +702,166 @@
}
+
+ /* Loads a simple field (i.e. non-table) into the current list of objects */
LOCAL_FUNC
+ T1_Error T1_Load_Field( T1_Parser* parser,
+ const T1_Field_Rec* field,
+ void** objects,
+ T1_UInt max_objects,
+ T1_ULong* pflags )
+ {
+ T1_Token_Rec token;
+ T1_Byte* cur;
+ T1_Byte* limit;
+ T1_UInt count;
+ T1_UInt index;
+ T1_Error error;
+
+ T1_ToToken( parser, &token );
+ if (!token.type)
+ goto Fail;
+
+ count = 1;
+ index = 0;
+ cur = token.start;
+ limit = token.limit;
+
+ if (token.type == t1_token_array)
+ {
+ /* if this is an array, and we have no blend, an error occurs */
+ if (max_objects == 0)
+ goto Fail;
+
+ count = max_objects;
+ index = 1;
+ }
+
+ for ( ; count > 0; count--, index++ )
+ {
+ T1_Byte* q = (T1_Byte*)objects[index] + field->offset;
+ T1_Long val;
+ T1_String* string;
+
+ switch (field->type)
+ {
+ case t1_field_bool:
+ {
+ val = t1_tobool( &cur, limit );
+ goto Store_Integer;
+ }
+
+ case t1_field_fixed:
+ {
+ val = t1_tofixed( &cur, limit, 3 );
+ goto Store_Integer;
+ }
+
+ case t1_field_integer:
+ {
+ val = t1_toint( &cur, limit );
+ Store_Integer:
+ switch (field->size)
+ {
+ case 1: *(T1_Byte*)q = (T1_Byte)val; break;
+ case 2: *(T1_UShort*)q = (T1_UShort)val; break;
+ default: *(T1_Long*)q = val;
+ }
+ }
+ break;
+
+ case t1_field_string:
+ {
+ FT_Memory memory = parser->memory;
+ FT_UInt len = limit-cur;
+
+ if ( ALLOC( string, len+1 ) )
+ goto Exit;
+
+ MEM_Copy( string, cur, len );
+ string[len] = 0;
+
+ *(T1_String**)q = string;
+ }
+ break;
+
+ default:
+ /* an error occured */
+ goto Fail;
+ }
+ }
+ if (pflags)
+ *pflags |= 1L << field->flag_bit;
+ error = 0;
+
+ Exit:
+ return error;
+ Fail:
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+
+#define T1_MAX_TABLE_ELEMENTS 32
+
+ LOCAL_FUNC
+ T1_Error T1_Load_Field_Table( T1_Parser* parser,
+ const T1_Field_Rec* field,
+ void** objects,
+ T1_UInt max_objects,
+ T1_ULong* pflags )
+ {
+ T1_Token_Rec elements[T1_MAX_TABLE_ELEMENTS];
+ T1_Token_Rec* token;
+ T1_Int num_elements;
+ T1_Error error = 0;
+ T1_Byte* old_cursor;
+ T1_Byte* old_limit;
+ T1_Field_Rec fieldrec = *(T1_Field_Rec*)field;
+
+ T1_ToTokenArray( parser, elements, 32, &num_elements );
+ if (num_elements < 0)
+ goto Fail;
+
+ if (num_elements > T1_MAX_TABLE_ELEMENTS)
+ num_elements = T1_MAX_TABLE_ELEMENTS;
+
+ old_cursor = parser->cursor;
+ old_limit = parser->limit;
+
+ /* we store the elements count */
+ *(T1_Byte*)((T1_Byte*)objects[0] + field->count_offset) = num_elements;
+
+ /* we now load each element, adjusting the field.offset on each one */
+ token = elements;
+ for ( ; num_elements > 0; num_elements--, token++ )
+ {
+ parser->cursor = token->start;
+ parser->limit = token->limit;
+ T1_Load_Field( parser, &fieldrec, objects, max_objects, 0 );
+ fieldrec.offset += fieldrec.size;
+ }
+
+ if (pflags)
+ *pflags |= 1L << field->flag_bit;
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+
+ Exit:
+ return error;
+ Fail:
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+
+
+
+
+
+
+ LOCAL_FUNC
T1_Long T1_ToInt ( T1_Parser* parser )
{
return t1_toint( &parser->cursor, parser->limit );
@@ -580,41 +908,6 @@
}
-#if 0
- /* load a single field in an object */
- LOCAL_FUNC
- T1_Error T1_Load_Field( T1_Parser* parser,
- void* object,
- T1_Field_Rec* field )
- {
- FT_Byte* p = (FT_Byte*)object + field->offset;
- FT_Byte** pcursor = &parser->cursor;
- FT_Byte* limit = parser->limit;
-
- switch (field->type)
- {
- case t1_field_boolean:
- *(T1_Bool*)p = t1_tobool( pcursor, limit );
- break;
-
- case t1_field_string:
- *(T1_String**)p = t1_tostring( pcursor, limit, parser->memory );
- break;
-
- case t1_field_int:
- *(T1_Long*)p = t1_toint( pcursor, limit );
- break;
-
- case t1_field_fixed:
- *(T1_Fixed*)p = t1_tofixed( pcursor, limit, field->power_ten );
- break;
-
- default:
- return T1_Err_Invalid_Argument;
- }
- return 0;
- }
-#endif
static
FT_Error read_pfb_tag( FT_Stream stream, T1_UShort *tag, T1_Long* size )
--- a/src/type1z/t1parse.h
+++ b/src/type1z/t1parse.h
@@ -38,6 +38,29 @@
#endif
+ /* simple enumeration type used to identify token types */
+ typedef enum T1_Token_Type_
+ {
+ t1_token_none = 0,
+ t1_token_any,
+ t1_token_string,
+ t1_token_array,
+
+ /* do not remove */
+ t1_token_max
+
+ } T1_Token_Type;
+
+ /* a simple structure used to identify tokens */
+ typedef struct T1_Token_Rec_
+ {
+ T1_Byte* start; /* first character of token in input stream */
+ T1_Byte* limit; /* first character after the token */
+ T1_Token_Type type; /* type of token.. */
+
+ } T1_Token_Rec;
+
+ /* enumeration type used to identify object fields */
typedef enum T1_Field_Type_
{
t1_field_none = 0,
@@ -45,22 +68,84 @@
t1_field_integer,
t1_field_fixed,
t1_field_string,
+ t1_field_integer_array,
t1_field_fixed_array,
- t1_field_coord_array
+ /* do not remove */
+ t1_field_max
+
} T1_Field_Type;
-
-
+
+ /* structure type used to model object fields */
typedef struct T1_Field_Rec_
{
- T1_Field_Type type; /* type of field */
- FT_UInt offset; /* offset of field in object */
- FT_UInt size; /* size of field in bytes */
- T1_Int array_max; /* maximum number of elements for array */
- T1_Int power_ten; /* power of ten for "fixed" fields */
-
+ T1_Field_Type type; /* type of field */
+ T1_UInt offset; /* offset of field in object */
+ T1_UInt size; /* size of field in bytes */
+ T1_UInt array_max; /* maximum number of elements for array */
+ T1_UInt count_offset; /* offset of element count for arrays */
+ T1_Int flag_bit; /* bit number for field flag */
+
} T1_Field_Rec;
-
+
+#define T1_FIELD_REF(s,f) (((s*)0)->f)
+
+#define T1_FIELD_BOOL( _ftype, _fname ) \
+ { t1_field_bool, \
+ (T1_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
+ sizeof(T1_FIELD_REF(_ftype,_fname)), \
+ 0, 0, 0 }
+
+#define T1_FIELD_NUM( _ftype, _fname ) \
+ { t1_field_integer, \
+ (T1_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
+ sizeof(T1_FIELD_REF(_ftype,_fname)), \
+ 0, 0, 0 }
+
+#define T1_FIELD_FIXED( _ftype, _fname, _power ) \
+ { t1_field_fixed, \
+ (T1_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
+ sizeof(T1_FIELD_REF(_ftype,_fname)), \
+ 0, 0, 0 }
+
+#define T1_FIELD_STRING( _ftype, _fname ) \
+ { t1_field_string, \
+ (T1_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
+ sizeof(T1_FIELD_REF(_ftype,_fname)), \
+ 0, 0, 0 }
+
+#define T1_FIELD_NUM_ARRAY( _ftype, _fname, _fcount, _fmax ) \
+ { t1_field_integer, \
+ (T1_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
+ sizeof(T1_FIELD_REF(_ftype,_fname)[0]), \
+ _fmax, \
+ (T1_UInt)(char*)&T1_FIELD_REF(_ftype,_fcount), \
+ 0 }
+
+#define T1_FIELD_FIXED_ARRAY( _ftype, _fname, _fcount, _fmax ) \
+ { t1_field_fixed, \
+ (T1_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
+ sizeof(T1_FIELD_REF(_ftype,_fname)[0]), \
+ _fmax, \
+ (T1_UInt)(char*)&T1_FIELD_REF(_ftype,_fcount), \
+ 0 }
+
+#define T1_FIELD_NUM_ARRAY2( _ftype, _fname, _fmax ) \
+ { t1_field_integer, \
+ (T1_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
+ sizeof(T1_FIELD_REF(_ftype,_fname)[0]), \
+ _fmax, \
+ 0, 0 }
+
+#define T1_FIELD_FIXED_ARRAY2( _ftype, _fname, _fmax ) \
+ { t1_field_fixed, \
+ (T1_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
+ sizeof(T1_FIELD_REF(_ftype,_fname)[0]), \
+ _fmax, \
+ 0, 0 }
+
+
+
/*************************************************************************
*
* <Struct> T1_Table
@@ -214,6 +299,32 @@
void* object,
T1_Field_Rec* field );
#endif
+
+
+
+
+
+ LOCAL_DEF
+ void T1_Skip_Spaces( T1_Parser* parser );
+
+ LOCAL_DEF
+ void T1_ToToken( T1_Parser* parser,
+ T1_Token_Rec* token );
+
+ LOCAL_DEF
+ T1_Error T1_Load_Field( T1_Parser* parser,
+ const T1_Field_Rec* field,
+ void** objects,
+ T1_UInt max_objects,
+ T1_ULong* pflags );
+
+ LOCAL_DEF
+ T1_Error T1_Load_Field_Table( T1_Parser* parser,
+ const T1_Field_Rec* field,
+ void** objects,
+ T1_UInt max_objects,
+ T1_ULong* pflags );
+
LOCAL_DEF
T1_Error T1_New_Parser( T1_Parser* parser,
--- a/src/type1z/t1tokens.h
+++ b/src/type1z/t1tokens.h
@@ -17,6 +17,52 @@
*
******************************************************************/
+#undef T1TYPE
+#define T1TYPE T1_FontInfo
+
+ T1_FONTINFO_STRING( "version", version )
+ T1_FONTINFO_STRING( "Notice", notice )
+ T1_FONTINFO_STRING( "FullName", full_name )
+ T1_FONTINFO_STRING( "FamilyName", family_name )
+ T1_FONTINFO_STRING( "Weight", weight )
+
+ T1_FONTINFO_NUM( "ItalicAngle", italic_angle )
+ T1_FONTINFO_BOOL( "isFixedPitch", is_fixed_pitch )
+ T1_FONTINFO_NUM( "UnderlinePosition", underline_position )
+ T1_FONTINFO_NUM( "UnderlineThickness", underline_thickness )
+
+#undef T1TYPE
+#define T1TYPE T1_Private
+
+ T1_PRIVATE_NUM ( "UniqueID", unique_id )
+ T1_PRIVATE_NUM ( "lenIV", lenIV )
+ T1_PRIVATE_NUM ( "LanguageGroup", language_group )
+ T1_PRIVATE_NUM ( "password", password )
+
+ T1_PRIVATE_FIXED( "BlueScale", blue_scale )
+ T1_PRIVATE_NUM ( "BlueShift", blue_shift )
+ T1_PRIVATE_NUM ( "BlueFuzz", blue_fuzz )
+
+ T1_PRIVATE_NUM_TABLE( "BlueValues", blue_values, 14, num_blues )
+ T1_PRIVATE_NUM_TABLE( "OtherBlues", other_blues, 10, num_other_blues )
+ T1_PRIVATE_NUM_TABLE( "FamilyBlues", family_blues, 14, num_family_blues )
+ T1_PRIVATE_NUM_TABLE( "FamilyOtherBlues", family_other_blues, 10, num_family_other_blues )
+
+ T1_PRIVATE_NUM_TABLE2( "StdHW", standard_width, 1 )
+ T1_PRIVATE_NUM_TABLE2( "StdVW", standard_height, 1 )
+ T1_PRIVATE_NUM_TABLE2( "MinFeature", min_feature, 2 )
+
+ T1_PRIVATE_NUM_TABLE ( "StemSnapH", stem_snap_widths, 12, num_snap_widths )
+ T1_PRIVATE_NUM_TABLE ( "StemSnapV", stem_snap_heights, 12, num_snap_heights )
+
+#undef T1TYPE
+#define T1TYPE T1_Font
+
+ T1_TOPDICT_NUM( "PaintType", paint_type )
+ T1_TOPDICT_NUM( "FontType", font_type )
+ T1_TOPDICT_NUM( "StrokeWidth", stroke_width )
+
+#if 0
/* define the font info dictionary parsing callbacks */
#undef FACE
#define FACE (face->type1.font_info)
@@ -75,5 +121,5 @@
PARSE_INT( "StrokeWidth", stroke_width )
#undef FACE
-
+#endif