added support for multiple master fonts in "type1z". It is
now working, but there is no way currently to change the default weight vector (tested with custom vectors though). Note that you should remove the "type1" driver from the module list to be able to test it..
This commit is contained in:
parent
4e18369491
commit
7c388ba491
@ -645,7 +645,7 @@
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* A bit-field constant, used to indicate that a given face contains */
|
||||
/* fixed-width characters (like Courier, MonoType, etc). */
|
||||
/* fixed-width characters (like Courier, Lucida, MonoType, etc..) */
|
||||
/* */
|
||||
#define FT_FACE_FLAG_FIXED_WIDTH 4
|
||||
|
||||
|
@ -170,7 +170,7 @@
|
||||
/* print a message and exit */
|
||||
FT_EXPORT_DEF(void) FT_Panic ( const char* fmt, ... );
|
||||
|
||||
#define FT_ERROR(varformat) do { FT_XCAT( FT_Message, varformat ) } while(0)
|
||||
#define FT_ERROR(varformat) do { FT_XCAT( FT_Message, varformat ); } while(0)
|
||||
|
||||
|
||||
#endif /* FT_DEBUG_LEVEL_TRACE || FT_DEBUG_LEVEL_ERROR */
|
||||
|
@ -140,8 +140,13 @@
|
||||
} 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
|
||||
#define T1_MAX_MM_DESIGNS 16
|
||||
|
||||
/* maximum number of multiple-masters axis, per-se the spec */
|
||||
#define T1_MAX_MM_AXIS 4
|
||||
|
||||
/* maximum number of elements in a design map */
|
||||
#define T1_MAX_MM_MAP_POINTS 20
|
||||
|
||||
/* this structure is used to store the BlendDesignMap entry for an axis */
|
||||
typedef struct T1_DesignMap_
|
||||
@ -152,6 +157,7 @@
|
||||
|
||||
} T1_DesignMap;
|
||||
|
||||
|
||||
typedef struct T1_Blend_
|
||||
{
|
||||
FT_UInt num_designs;
|
||||
@ -161,6 +167,9 @@
|
||||
FT_Fixed* design_pos[ T1_MAX_MM_DESIGNS ];
|
||||
T1_DesignMap design_map[ T1_MAX_MM_AXIS ];
|
||||
|
||||
FT_Fixed* weight_vector;
|
||||
FT_Fixed* default_weight_vector;
|
||||
|
||||
T1_FontInfo* font_infos[ T1_MAX_MM_DESIGNS+1 ];
|
||||
T1_Private* privates [ T1_MAX_MM_DESIGNS+1 ];
|
||||
|
||||
@ -173,7 +182,7 @@
|
||||
typedef struct CID_FontDict_
|
||||
{
|
||||
T1_FontInfo font_info;
|
||||
T1_Private private;
|
||||
T1_Private private_dict;
|
||||
|
||||
FT_UInt num_subrs;
|
||||
FT_ULong subrmap_offset;
|
||||
|
@ -205,6 +205,7 @@
|
||||
decoder->zone = 0;
|
||||
decoder->flex_state = 0;
|
||||
decoder->num_flex_vectors = 0;
|
||||
decoder->blend = 0;
|
||||
|
||||
/* Clear loader */
|
||||
MEM_Set( &decoder->builder, 0, sizeof(decoder->builder) );
|
||||
@ -830,6 +831,72 @@
|
||||
break;;
|
||||
}
|
||||
|
||||
case 12:
|
||||
case 13:
|
||||
{
|
||||
/* counter control hints, clear stack */
|
||||
top = decoder->stack;
|
||||
break;
|
||||
}
|
||||
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18: /* multiple masters */
|
||||
{
|
||||
T1_Blend* blend = decoder->blend;
|
||||
T1_UInt num_points, nn, mm;
|
||||
T1_Int* delta;
|
||||
T1_Int* values;
|
||||
|
||||
if (!blend)
|
||||
{
|
||||
FT_ERROR(( "T1.Parse_CharStrings: unexpected multiple masters operator !!\n" ));
|
||||
goto Syntax_Error;
|
||||
}
|
||||
|
||||
num_points = top[1] - 13 + (top[1] == 18);
|
||||
if (top[0] != num_points*blend->num_designs)
|
||||
{
|
||||
FT_ERROR(( "T1.Parse_CharStrings: incorrect number of mm arguments\n" ));
|
||||
goto Syntax_Error;
|
||||
}
|
||||
|
||||
top -= blend->num_designs*num_points;
|
||||
if (top < decoder->stack)
|
||||
goto Stack_Underflow;
|
||||
|
||||
/* we want to compute: */
|
||||
/* */
|
||||
/* a0*w0 + a1*w1 + ... + ak*wk */
|
||||
/* */
|
||||
/* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */
|
||||
/* however, given that w0 + w1 + ... + wk == 1, we can */
|
||||
/* rewrite it easily as: */
|
||||
/* */
|
||||
/* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
|
||||
/* */
|
||||
/* where k == num_designs-1 */
|
||||
/* */
|
||||
/* I guess that's why it's written in this "compact" */
|
||||
/* form.. */
|
||||
/* */
|
||||
/* */
|
||||
delta = top + num_points;
|
||||
values = top;
|
||||
for ( nn = 0; nn < num_points; nn++ )
|
||||
{
|
||||
T1_Int x = values[0];
|
||||
for ( mm = 1; mm < blend->num_designs; mm++ )
|
||||
x += FT_MulFix( *delta++, blend->weight_vector[mm] );
|
||||
|
||||
*values++ = x;
|
||||
}
|
||||
/* note that "top" will be incremented later by calls to "pop" */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Unexpected_OtherSubr:
|
||||
FT_ERROR(( "T1.Parse_CharStrings: invalid othersubr [%d %d]!!\n",
|
||||
@ -1086,8 +1153,9 @@
|
||||
case op_pop: /****************************************************/
|
||||
{
|
||||
FT_TRACE4(( " pop" ));
|
||||
FT_ERROR(( "T1.Parse_CharStrings : unexpected POP\n" ));
|
||||
goto Syntax_Error;
|
||||
/* theorically, the arguments are already on the stack */
|
||||
top++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -1202,6 +1270,7 @@
|
||||
T1_Init_Decoder( &decoder );
|
||||
T1_Init_Builder( &decoder.builder, face, 0, 0 );
|
||||
|
||||
decoder.blend = face->blend;
|
||||
decoder.builder.metrics_only = 1;
|
||||
decoder.builder.load_points = 0;
|
||||
|
||||
@ -1270,6 +1339,7 @@
|
||||
T1_Init_Decoder( &decoder );
|
||||
T1_Init_Builder( &decoder.builder, face, size, glyph );
|
||||
|
||||
decoder.blend = ((T1_Face)glyph->root.face)->blend;
|
||||
decoder.builder.no_recurse = (FT_Bool)!!(load_flags & FT_LOAD_NO_RECURSE);
|
||||
|
||||
/* now load the unscaled outline */
|
||||
|
@ -139,6 +139,8 @@
|
||||
T1_Int num_flex_vectors;
|
||||
T1_Vector flex_vectors[7];
|
||||
|
||||
T1_Blend* blend; /* for multiple masters */
|
||||
|
||||
} T1_Decoder;
|
||||
|
||||
|
||||
|
@ -102,9 +102,12 @@
|
||||
{
|
||||
/* 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 ) )
|
||||
ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private ) ||
|
||||
ALLOC_ARRAY( blend->weight_vector, num_designs*2, FT_Fixed ) )
|
||||
goto Exit;
|
||||
|
||||
blend->default_weight_vector = blend->weight_vector + num_designs;
|
||||
|
||||
blend->font_infos[0] = &face->type1.font_info;
|
||||
blend->privates [0] = &face->type1.private_dict;
|
||||
blend->num_designs = num_designs;
|
||||
@ -144,7 +147,7 @@
|
||||
}
|
||||
|
||||
|
||||
static void t1_done_blend( T1_Face face )
|
||||
LOCAL_FUNC void T1_Done_Blend( T1_Face face )
|
||||
{
|
||||
FT_Memory memory = face->root.memory;
|
||||
T1_Blend* blend = face->blend;
|
||||
@ -169,6 +172,10 @@
|
||||
blend->font_infos[n] = 0;
|
||||
}
|
||||
|
||||
/* release weight vectors */
|
||||
FREE( blend->weight_vector );
|
||||
blend->default_weight_vector = 0;
|
||||
|
||||
/* release axis names */
|
||||
for ( n = 0; n < num_axis; n++ )
|
||||
FREE( blend->axis_names[n] );
|
||||
@ -178,7 +185,6 @@
|
||||
{
|
||||
T1_DesignMap* dmap = blend->design_map + n;
|
||||
FREE( dmap->design_points );
|
||||
FREE( dmap->blend_points );
|
||||
dmap->num_points = 0;
|
||||
}
|
||||
|
||||
@ -186,6 +192,261 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void parse_blend_axis_types( T1_Face face, T1_Loader* loader )
|
||||
{
|
||||
T1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ];
|
||||
T1_Int n, num_axis;
|
||||
FT_Error error = 0;
|
||||
T1_Blend* blend;
|
||||
FT_Memory memory;
|
||||
|
||||
/* take an array of objects */
|
||||
T1_ToTokenArray( &loader->parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
|
||||
if (num_axis <= 0 || num_axis > T1_MAX_MM_AXIS)
|
||||
{
|
||||
FT_ERROR(( "T1.parse_blend_axis_types: incorrect number of axis: %d\n",
|
||||
num_axis ));
|
||||
error = FT_Err_Invalid_File_Format;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* allocate blend if necessary */
|
||||
error = t1_allocate_blend( face, 0, (T1_UInt)num_axis );
|
||||
if (error) goto Exit;
|
||||
|
||||
blend = face->blend;
|
||||
memory = face->root.memory;
|
||||
|
||||
/* each token is an immediate containing the name of the axis */
|
||||
for ( n = 0; n < num_axis; n++ )
|
||||
{
|
||||
T1_Token_Rec* token = axis_tokens + n;
|
||||
T1_Byte* name;
|
||||
T1_Int len;
|
||||
|
||||
/* skip first slash, if any */
|
||||
if (token->start[0] == '/')
|
||||
token->start++;
|
||||
|
||||
len = token->limit - token->start;
|
||||
if (len <= 0)
|
||||
{
|
||||
error = FT_Err_Invalid_File_Format;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( ALLOC( blend->axis_names[n], len+1 ) )
|
||||
goto Exit;
|
||||
|
||||
name = (T1_Byte*)blend->axis_names[n];
|
||||
MEM_Copy( name, token->start, len );
|
||||
name[len] = 0;
|
||||
}
|
||||
|
||||
Exit:
|
||||
loader->parser.error = error;
|
||||
}
|
||||
|
||||
|
||||
static void parse_blend_design_positions( T1_Face face, T1_Loader* loader )
|
||||
{
|
||||
T1_Token_Rec design_tokens[ T1_MAX_MM_DESIGNS ];
|
||||
T1_Int num_designs;
|
||||
T1_Int num_axis;
|
||||
T1_Parser* parser = &loader->parser;
|
||||
|
||||
FT_Error error = 0;
|
||||
T1_Blend* blend;
|
||||
|
||||
/* get the array of design tokens - compute number of designs */
|
||||
T1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
|
||||
if (num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS)
|
||||
{
|
||||
FT_ERROR(( "T1.design positions: incorrect number of designs: %d\n",
|
||||
num_designs ));
|
||||
error = FT_Err_Invalid_File_Format;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
{
|
||||
T1_Byte* old_cursor = parser->cursor;
|
||||
T1_Byte* old_limit = parser->limit;
|
||||
T1_UInt n;
|
||||
|
||||
blend = face->blend;
|
||||
for ( n = 0; n < (T1_UInt)num_designs; n++ )
|
||||
{
|
||||
T1_Token_Rec axis_tokens[ T1_MAX_MM_DESIGNS ];
|
||||
T1_Token_Rec* token;
|
||||
T1_Int axis, n_axis;
|
||||
|
||||
/* read axis/coordinates tokens */
|
||||
token = design_tokens + n;
|
||||
parser->cursor = token->start - 1;
|
||||
parser->limit = token->limit + 1;
|
||||
T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
num_axis = n_axis;
|
||||
error = t1_allocate_blend( face, num_designs, num_axis );
|
||||
if (error) goto Exit;
|
||||
blend = face->blend;
|
||||
}
|
||||
else if (n_axis != num_axis)
|
||||
{
|
||||
FT_ERROR(( "T1.design_positions: incorrect table\n" ));
|
||||
error = FT_Err_Invalid_File_Format;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* now, read each axis token into the design position */
|
||||
for (axis = 0; axis < n_axis; axis++ )
|
||||
{
|
||||
T1_Token_Rec* token2 = axis_tokens + axis;
|
||||
parser->cursor = token2->start;
|
||||
parser->limit = token2->limit;
|
||||
blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
loader->parser.cursor = old_cursor;
|
||||
loader->parser.limit = old_limit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
loader->parser.error = error;
|
||||
}
|
||||
|
||||
static void parse_blend_design_map( T1_Face face, T1_Loader* loader )
|
||||
{
|
||||
FT_Error error = 0;
|
||||
T1_Parser* parser = &loader->parser;
|
||||
T1_Blend* blend;
|
||||
T1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ];
|
||||
T1_Int n, num_axis;
|
||||
T1_Byte* old_cursor;
|
||||
T1_Byte* old_limit;
|
||||
FT_Memory memory = face->root.memory;
|
||||
|
||||
T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
|
||||
if (num_axis <= 0 || num_axis > T1_MAX_MM_AXIS)
|
||||
{
|
||||
FT_ERROR(( "T1.design map: incorrect number of axis: %d\n",
|
||||
num_axis ));
|
||||
error = FT_Err_Invalid_File_Format;
|
||||
goto Exit;
|
||||
}
|
||||
old_cursor = parser->cursor;
|
||||
old_limit = parser->limit;
|
||||
|
||||
error = t1_allocate_blend( face, 0, num_axis );
|
||||
if (error) goto Exit;
|
||||
blend = face->blend;
|
||||
|
||||
/* now, read each axis design map */
|
||||
for ( n = 0; n < num_axis; n++ )
|
||||
{
|
||||
T1_DesignMap* map = blend->design_map + n;
|
||||
T1_Token_Rec* token;
|
||||
T1_Int p, num_points;
|
||||
|
||||
token = axis_tokens + n;
|
||||
parser->cursor = token->start;
|
||||
parser->limit = token->limit;
|
||||
|
||||
/* count the number of map points */
|
||||
{
|
||||
T1_Byte* p = token->start;
|
||||
T1_Byte* limit = token->limit;
|
||||
|
||||
num_points = 0;
|
||||
for ( ; p < limit; p++ )
|
||||
if (p[0] == '[')
|
||||
num_points++;
|
||||
}
|
||||
if (num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS)
|
||||
{
|
||||
FT_ERROR(( "T1.design map: incorrect table\n" ));
|
||||
error = FT_Err_Invalid_File_Format;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* allocate design map data */
|
||||
if ( ALLOC_ARRAY( map->design_points, num_points*2, FT_Fixed ) )
|
||||
goto Exit;
|
||||
map->blend_points = map->design_points + num_points;
|
||||
map->num_points = (FT_Byte)num_points;
|
||||
|
||||
for ( p = 0; p < num_points; p++ )
|
||||
{
|
||||
map->design_points[p] = T1_ToInt( parser );
|
||||
map->blend_points [p] = T1_ToFixed( parser, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
parser->cursor = old_cursor;
|
||||
parser->limit = old_limit;
|
||||
Exit:
|
||||
parser->error = error;
|
||||
}
|
||||
|
||||
static void parse_weight_vector( T1_Face face, T1_Loader* loader )
|
||||
{
|
||||
FT_Error error = 0;
|
||||
T1_Parser* parser = &loader->parser;
|
||||
T1_Blend* blend = face->blend;
|
||||
T1_Token_Rec master;
|
||||
T1_UInt n;
|
||||
T1_Byte* old_cursor;
|
||||
T1_Byte* old_limit;
|
||||
|
||||
if (!blend || blend->num_designs == 0)
|
||||
{
|
||||
FT_ERROR(( "t1.weight_vector: too early !!\n" ));
|
||||
error = FT_Err_Invalid_File_Format;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
T1_ToToken( parser, &master );
|
||||
if (master.type != t1_token_array)
|
||||
{
|
||||
FT_ERROR(( "t1.weight_vector: incorrect format !!\n" ));
|
||||
error = FT_Err_Invalid_File_Format;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
old_cursor = parser->cursor;
|
||||
old_limit = parser->limit;
|
||||
|
||||
parser->cursor = master.start;
|
||||
parser->limit = master.limit;
|
||||
for ( n = 0; n < blend->num_designs; n++ )
|
||||
{
|
||||
blend->default_weight_vector[n] =
|
||||
blend->weight_vector[n] = T1_ToFixed( parser, 0 );
|
||||
}
|
||||
|
||||
parser->cursor = old_cursor;
|
||||
parser->limit = old_limit;
|
||||
Exit:
|
||||
parser->error = error;
|
||||
}
|
||||
|
||||
/* the keyword /shareddict appears in some multiple master fonts with a lot */
|
||||
/* of Postscript garbage behind it (that's completely out of spec !!), we */
|
||||
/* detect it and terminate the parsing */
|
||||
static void parse_shared_dict( T1_Face face, T1_Loader* loader )
|
||||
{
|
||||
T1_Parser* parser = &loader->parser;
|
||||
|
||||
UNUSED(face);
|
||||
|
||||
parser->cursor = parser->limit;
|
||||
parser->error = 0;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
/***** *****/
|
||||
@ -802,6 +1063,13 @@
|
||||
T1_KEYWORD_CALLBACK( "Encoding", parse_encoding ),
|
||||
T1_KEYWORD_CALLBACK( "Subrs", parse_subrs ),
|
||||
T1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings ),
|
||||
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
|
||||
T1_KEYWORD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ),
|
||||
T1_KEYWORD_CALLBACK( "BlendDesignMap", parse_blend_design_map ),
|
||||
T1_KEYWORD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ),
|
||||
T1_KEYWORD_CALLBACK( "WeightVector", parse_weight_vector ),
|
||||
T1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict ),
|
||||
#endif
|
||||
T1_KEYWORD_CALLBACK( 0, 0 )
|
||||
};
|
||||
|
||||
@ -864,7 +1132,7 @@
|
||||
while (cur2 < limit && is_alpha(*cur2)) cur2++;
|
||||
len = cur2-cur;
|
||||
|
||||
if (len > 0 && len < 20)
|
||||
if (len > 0 && len < 22)
|
||||
{
|
||||
if (!loader->fontdata)
|
||||
{
|
||||
|
@ -46,6 +46,10 @@
|
||||
LOCAL_DEF
|
||||
T1_Error T1_Open_Face( T1_Face face );
|
||||
|
||||
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
|
||||
LOCAL_DEF
|
||||
void T1_Done_Blend( T1_Face face );
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -138,6 +138,12 @@
|
||||
{
|
||||
memory = face->root.memory;
|
||||
|
||||
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
|
||||
/* release multiple masters information */
|
||||
T1_Done_Blend( face );
|
||||
face->blend = 0;
|
||||
#endif
|
||||
|
||||
/* release font info strings */
|
||||
{
|
||||
T1_FontInfo* info = &type1->font_info;
|
||||
|
@ -621,6 +621,7 @@
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static
|
||||
T1_String* t1_tostring( T1_Byte* *cursor, T1_Byte* limit, FT_Memory memory )
|
||||
{
|
||||
@ -670,6 +671,7 @@
|
||||
*cursor = cur;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
int t1_tobool( T1_Byte* *cursor, T1_Byte* limit )
|
||||
@ -732,7 +734,7 @@
|
||||
/* if this is an array, and we have no blend, an error occurs */
|
||||
if (max_objects == 0)
|
||||
goto Fail;
|
||||
|
||||
|
||||
count = max_objects;
|
||||
index = 1;
|
||||
}
|
||||
@ -894,6 +896,7 @@
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
LOCAL_FUNC
|
||||
T1_String* T1_ToString( T1_Parser* parser )
|
||||
{
|
||||
@ -906,7 +909,7 @@
|
||||
{
|
||||
return t1_tobool( &parser->cursor, parser->limit );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static
|
||||
|
@ -280,25 +280,14 @@
|
||||
T1_Fixed* values,
|
||||
T1_Int power_ten );
|
||||
|
||||
#if 0
|
||||
LOCAL_DEF
|
||||
T1_String* T1_ToString( T1_Parser* parser );
|
||||
|
||||
|
||||
LOCAL_DEF
|
||||
T1_Bool T1_ToBool( T1_Parser* parser );
|
||||
|
||||
#if 0
|
||||
LOCAL_DEF
|
||||
T1_Int T1_ToImmediate( T1_Parser* parser );
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* load a single field in an object */
|
||||
LOCAL_DEF
|
||||
T1_Error T1_Load_Field( T1_Parser* parser,
|
||||
void* object,
|
||||
T1_Field_Rec* field );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user