important modifications to the Type1z driver
these are used to prepare for multiple master fonts
This commit is contained in:
parent
1fb6eea7d1
commit
1c9a1cab3f
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
T1_Int num_subrs;
|
||||
T1_Table subrs;
|
||||
T1_Bool fontdata;
|
||||
|
||||
} T1_Loader;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue