important modifications to the Type1z driver

these are used to prepare for multiple master fonts
This commit is contained in:
David Turner 2000-05-24 21:12:02 +00:00
parent 1fb6eea7d1
commit 1c9a1cab3f
10 changed files with 916 additions and 203 deletions

View File

@ -29,7 +29,6 @@
#endif
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
@ -392,6 +391,9 @@
FT_CharMap charmaps[2];
PS_Unicodes unicode_map;
/* support for multiple masters */
T1_Blend* blend;
} T1_FaceRec;

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -70,82 +70,312 @@
#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 T1_KEYWORD_FONTINFO_TABLE( name, f ) \
{ name, t1_keyword_field_table, t1_keyword_font_info, 0, &t1_field_ ## f }
#define T1_KEYWORD_PRIVATE_TABLE( name, f ) \
{ name, t1_keyword_field_table, t1_keyword_private, 0, &t1_field_ ## f }
#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 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),
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_NUM(s,x,t) PARSE_(x) \
{ \
FACE.x = (t)T1_ToInt(&loader->parser); \
FT_TRACE2(( "type1.parse_%s: \"%d\"\n", #x, FACE.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;
}
}
#define PARSE_INT(s,x) PARSE_(x) \
{ \
FACE.x = T1_ToInt(&loader->parser); \
FT_TRACE2(( "type1.parse_%s: \"%d\"\n", #x, FACE.x )); \
}
#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" )); \
}
#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 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 )); \
}
#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 )); \
}
#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>
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;
}
static
@ -273,6 +503,22 @@
bbox->yMax = temp[3];
}
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 )
{
@ -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

View File

@ -39,6 +39,7 @@
T1_Int num_subrs;
T1_Table subrs;
T1_Bool fontdata;
} T1_Loader;

View File

@ -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)

View File

@ -38,6 +38,18 @@
#undef FT_COMPONENT
#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,6 +702,165 @@
}
/* 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 )
{
@ -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 )

View File

@ -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
@ -215,6 +300,32 @@
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,
FT_Stream stream,

View File

@ -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