diff --git a/src/cff/t2load.h b/src/cff/t2load.h index 54a016436..7ebc76d27 100644 --- a/src/cff/t2load.h +++ b/src/cff/t2load.h @@ -20,6 +20,7 @@ #define T2LOAD_H #include +#include #ifdef __cplusplus extern "C" { diff --git a/src/cff/t2objs.c b/src/cff/t2objs.c index 5c249d618..d82a3bb9b 100644 --- a/src/cff/t2objs.c +++ b/src/cff/t2objs.c @@ -175,8 +175,8 @@ break; } - default: /* unknown charset format !! */ - FT_ERROR(( "CFF: unknown charset format !!\n" )); + default: /* unknown charset format! */ + FT_ERROR(( "CFF: unknown charset format!\n" )); error = FT_Err_Invalid_File_Format; goto Fail; } diff --git a/src/type1z/z1load.c b/src/type1z/z1load.c index d1af02936..a2b4742f9 100644 --- a/src/type1z/z1load.c +++ b/src/type1z/z1load.c @@ -1,63 +1,65 @@ -/******************************************************************* - * - * t1load.h 2.0 - * - * Type1 Loader. - * - * Copyright 1996-2000 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used - * modified and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - * - * This is the new and improved Type 1 data loader for FreeType 2. - * The old loader has several problems: it is slow, complex, difficult - * to maintain, and contains incredible hacks to make it accept some - * ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% - * of the Type 1 fonts on my machine still aren't loaded correctly - * by it. - * - * This version is much simpler, much faster and also easier to - * read and maintain by a great order of magnitude. The idea behind - * it is to _not_ try to read the Type 1 token stream with a state - * machine (i.e. a Postscript-like interpreter) but rather to perform - * simple pattern-matching. - * - * Indeed, nearly all data definitions follow a simple pattern - * like : - * - * ..... /Field .... - * - * where can be a number, a boolean, a string, or an - * array of numbers. There are a few exceptions, namely the - * encoding, font name, charstrings and subrs and they are - * handled with a special pattern-matching routine. - * - * All other common cases are handled very simply. The matching - * rules are defined in the file "t1tokens.h" through the use - * of several macros calls PARSE_XXXX - * - * This file is included twice here, the first time to generate - * parsing callback functions, the second to generate a table - * of keywords (with pointers to the associated callback). - * - * The function "parse_dict" simply scans *linearly* a given - * dictionary (either the top-level or private one) and calls - * the appropriate callback when it encounters an immediate - * keyword. - * - * This is by far the fastest way one can find to parse and read - * all data :-) - * - * This led to tremendous code size reduction. Note that later, - * the glyph loader will also be _greatly_ simplified, and the - * automatic hinter will replace the clumsy "t1hinter".. - * - ******************************************************************/ +/***************************************************************************/ +/* */ +/* z1load.c */ +/* */ +/* Experimental Type 1 font loader (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This is the new and improved Type 1 data loader for FreeType 2. The */ + /* old loader has several problems: it is slow, complex, difficult to */ + /* maintain, and contains incredible hacks to make it accept some */ + /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */ + /* the Type 1 fonts on my machine still aren't loaded correctly by it. */ + /* */ + /* This version is much simpler, much faster and also easier to read and */ + /* maintain by a great order of magnitude. The idea behind it is to */ + /* _not_ try to read the Type 1 token stream with a state machine (i.e. */ + /* a Postscript-like interpreter) but rather to perform simple pattern */ + /* matching. */ + /* */ + /* Indeed, nearly all data definitions follow a simple pattern like */ + /* */ + /* ... /Field ... */ + /* */ + /* where can be a number, a boolean, a string, or an array of */ + /* numbers. There are a few exceptions, namely the encoding, font name, */ + /* charstrings, and subrs; they are handled with a special pattern */ + /* matching routine. */ + /* */ + /* All other common cases are handled very simply. The matching rules */ + /* are defined in the file `t1tokens.h' through the use of several */ + /* macros calls PARSE_XXX. */ + /* */ + /* This file is included twice here; the first time to generate parsing */ + /* callback functions, the second to generate a table of keywords (with */ + /* pointers to the associated callback). */ + /* */ + /* The function `parse_dict' simply scans *linearly* a given dictionary */ + /* (either the top-level or private one) and calls the appropriate */ + /* callback when it encounters an immediate keyword. */ + /* */ + /* This is by far the fastest way one can find to parse and read all */ + /* data. */ + /* */ + /* This led to tremendous code size reduction. Note that later, the */ + /* glyph loader will also be _greatly_ simplified, and the automatic */ + /* hinter will replace the clumsy `t1hinter'. */ + /* */ + /*************************************************************************/ + #include #include @@ -66,593 +68,701 @@ #include #include + #ifdef FT_FLAT_COMPILE + #include "z1load.h" + #else + #include + #endif -#include +#include /* for strncmp(), strcmp() */ +#include /* for isalnum() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ #undef FT_COMPONENT -#define FT_COMPONENT trace_t1load +#define FT_COMPONENT trace_z1load + #ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT - /***************************************************************************/ - /***************************************************************************/ - /***** *****/ - /***** MULTIPLE MASTERS SUPPORT *****/ - /***** *****/ - /***************************************************************************/ - /***************************************************************************/ - - static FT_Error t1_allocate_blend( T1_Face face, - FT_UInt num_designs, - FT_UInt num_axis ) - { - T1_Blend* blend; - FT_Memory memory = face->root.memory; - FT_Error error = 0; - - blend = face->blend; - if (!blend) - { - if ( ALLOC( blend, sizeof(*blend) ) ) - goto Exit; - - face->blend = blend; - } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** MULTIPLE MASTERS SUPPORT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static + FT_Error t1_allocate_blend( T1_Face face, + FT_UInt num_designs, + FT_UInt num_axis ) + { + T1_Blend* blend; + FT_Memory memory = face->root.memory; + FT_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 ) || + ALLOC_ARRAY( blend->weight_vector, num_designs * 2, FT_Fixed ) ) + goto Exit; - /* 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 ) || - 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; + } + 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; + } + + + LOCAL_FUNC + FT_Error Z1_Get_Multi_Master( T1_Face face, + FT_Multi_Master* master ) + { + T1_Blend* blend = face->blend; + FT_UInt n; + FT_Error error; + + + error = T1_Err_Invalid_Argument; + + if ( blend ) + { + master->num_axis = blend->num_axis; + master->num_designs = blend->num_designs; + + for ( n = 0; n < blend->num_axis; n++ ) + { + FT_MM_Axis* axis = master->axis + n; + T1_DesignMap* map = blend->design_map + n; + + + axis->name = blend->axis_names[n]; + axis->minimum = map->design_points[0]; + axis->maximum = map->design_points[map->num_points - 1]; + } + error = 0; + } + return error; + } + + + LOCAL_FUNC + FT_Error Z1_Set_MM_Blend( T1_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + T1_Blend* blend = face->blend; + FT_Error error; + FT_UInt n, m; + + + error = T1_Err_Invalid_Argument; + + if ( blend && blend->num_axis == num_coords ) + { + /* recompute the weight vector from the blend coordinates */ + error = FT_Err_Ok; + + for ( n = 0; n < blend->num_designs; n++ ) + { + FT_Fixed result = 0x10000L; /* 1.0 fixed */ + + + for ( m = 0; m < blend->num_axis; m++ ) + { + FT_Fixed factor; + + + /* get current blend axis position */ + factor = coords[m]; + if ( factor < 0 ) factor = 0; + if ( factor > 0x10000L ) factor = 0x10000L; + + if ( ( n & ( 1 << m ) ) == 0 ) + factor = 0x10000L - factor; + + result = FT_MulFix( result, factor ); + } + blend->weight_vector[n] = result; + } + + error = FT_Err_Ok; + } + return error; + } - 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; - } - 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; - } - - LOCAL_FUNC FT_Error Z1_Get_Multi_Master( T1_Face face, - FT_Multi_Master* master ) - { - T1_Blend* blend = face->blend; - FT_UInt n; - FT_Error error; - - error = T1_Err_Invalid_Argument; - if (blend) - { - master->num_axis = blend->num_axis; - master->num_designs = blend->num_designs; - for ( n = 0; n < blend->num_axis; n++ ) - { - FT_MM_Axis* axis = master->axis + n; - T1_DesignMap* map = blend->design_map + n; - - axis->name = blend->axis_names[n]; - axis->minimum = map->design_points[0]; - axis->maximum = map->design_points[map->num_points-1]; - } - error = 0; - } - return error; - } + + LOCAL_FUNC + FT_Error Z1_Set_MM_Design( T1_Face face, + FT_UInt num_coords, + FT_Long* coords ) + { + T1_Blend* blend = face->blend; + FT_Error error; + FT_UInt n, p; + + error = T1_Err_Invalid_Argument; + if ( blend && blend->num_axis == num_coords ) + { + /* compute the blend coordinates through the blend design map */ + FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; + - LOCAL_FUNC FT_Error Z1_Set_MM_Blend( T1_Face face, - FT_UInt num_coords, - FT_Fixed* coords ) - { - T1_Blend* blend = face->blend; - FT_Error error; - FT_UInt n, m; - - error = T1_Err_Invalid_Argument; - if (blend && blend->num_axis == num_coords) - { - /* recompute the weight vector from the blend coordinates */ - error = 0; - for ( n = 0; n < blend->num_designs; n++ ) - { - FT_Fixed result = 0x10000L; /* 1.0 fixed */ - for ( m = 0; m < blend->num_axis; m++ ) - { - FT_Fixed factor; - - /* get current blend axis position */ - factor = coords[m]; - if (factor < 0) factor = 0; - if (factor > 0x10000L) factor = 0x10000L; - - if ((n & (1 << m)) == 0) - factor = 0x10000L - factor; + for ( n = 0; n < blend->num_axis; n++ ) + { + FT_Long design = coords[n]; + FT_Fixed the_blend; + T1_DesignMap* map = blend->design_map + n; + FT_Fixed* designs = map->design_points; + FT_Fixed* blends = map->blend_points; + FT_Int before = -1, after = -1; + + for ( p = 0; p < map->num_points; p++ ) + { + FT_Fixed p_design = designs[p]; + + + /* exact match ? */ + if ( design == p_design ) + { + the_blend = blends[p]; + goto Found; + } + + if ( design < p_design ) + { + after = p; + break; + } + + before = p; + } + + /* now, interpolate if needed */ + if ( before < 0 ) + the_blend = blends[0]; + + else if ( after < 0 ) + the_blend = blends[map->num_points - 1]; + + else + the_blend = FT_MulDiv( design - designs[before], + blends [after] - blends [before], + designs[after] - designs[before] ); + + Found: + final_blends[n] = the_blend; + } + + error = Z1_Set_MM_Blend( face, num_coords, final_blends ); + } + + return error; + } + + + LOCAL_FUNC + void Z1_Done_Blend( T1_Face face ) + { + FT_Memory memory = face->root.memory; + T1_Blend* blend = face->blend; + + + if ( blend ) + { + FT_UInt num_designs = blend->num_designs; + FT_UInt num_axis = blend->num_axis; + FT_UInt n; - result = FT_MulFix( result, factor ); - } - blend->weight_vector[n] = result; - } - error = 0; - } - return error; - } + + /* 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] ); - LOCAL_FUNC FT_Error Z1_Set_MM_Design( T1_Face face, - FT_UInt num_coords, - FT_Long* coords ) - { - T1_Blend* blend = face->blend; - FT_Error error; - FT_UInt n, p; - - error = T1_Err_Invalid_Argument; - if (blend && blend->num_axis == num_coords) - { - /* compute the blend coordinates through the blend design map */ - FT_Fixed final_blends[ T1_MAX_MM_DESIGNS ]; - - for ( n = 0; n < blend->num_axis; n++ ) - { - FT_Long design = coords[n]; - FT_Fixed the_blend; - T1_DesignMap* map = blend->design_map + n; - FT_Fixed* designs = map->design_points; - FT_Fixed* blends = map->blend_points; - FT_Int before = -1, after = -1; - - for ( p = 0; p < map->num_points; p++ ) - { - FT_Fixed p_design = designs[p]; - - /* exact match ? */ - if (design == p_design) - { - the_blend = blends[p]; - goto Found; - } - - if (design < p_design) - { - after = p; - break; - } - - before = p; - } - - /* now, interpolate if needed */ - if (before < 0) - the_blend = blends[0]; - - else if (after < 0) - the_blend = blends[map->num_points-1]; - - else - the_blend = FT_MulDiv( design - designs[before], - blends [after] - blends [before], - designs[after] - designs[before] ); - Found: - final_blends[n] = the_blend; - } - - error = Z1_Set_MM_Blend( face, num_coords, final_blends ); - } - return error; - } + for ( n = 0; n < num_designs; n++ ) + { + blend->privates [n] = 0; + 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] ); + + /* release design map */ + for ( n = 0; n < num_axis; n++ ) + { + T1_DesignMap* dmap = blend->design_map + n; + + FREE( dmap->design_points ); + dmap->num_points = 0; + } + + FREE( face->blend ); + } + } + + + static + void parse_blend_axis_types( T1_Face face, + Z1_Loader* loader ) + { + Z1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ]; + FT_Int n, num_axis; + FT_Error error = 0; + T1_Blend* blend; + FT_Memory memory; - LOCAL_FUNC void Z1_Done_Blend( T1_Face face ) - { - FT_Memory memory = face->root.memory; - T1_Blend* blend = face->blend; - - if (blend) - { - FT_UInt num_designs = blend->num_designs; - FT_UInt num_axis = blend->num_axis; - FT_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 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] ); - - /* release design map */ - for ( n = 0; n < num_axis; n++ ) - { - T1_DesignMap* dmap = blend->design_map + n; - FREE( dmap->design_points ); - dmap->num_points = 0; - } - - FREE( face->blend ); - } - } - - - - static void parse_blend_axis_types( T1_Face face, Z1_Loader* loader ) - { - Z1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ]; - FT_Int n, num_axis; - FT_Error error = 0; - T1_Blend* blend; - FT_Memory memory; - - /* take an array of objects */ - Z1_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 = T1_Err_Invalid_File_Format; - goto Exit; - } - - /* allocate blend if necessary */ - error = t1_allocate_blend( face, 0, (FT_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++ ) - { - Z1_Token_Rec* token = axis_tokens + n; - FT_Byte* name; - FT_Int len; - - /* skip first slash, if any */ - if (token->start[0] == '/') - token->start++; - - len = token->limit - token->start; - if (len <= 0) - { - error = T1_Err_Invalid_File_Format; - goto Exit; - } - - if ( ALLOC( blend->axis_names[n], len+1 ) ) - goto Exit; - - name = (FT_Byte*)blend->axis_names[n]; - MEM_Copy( name, token->start, len ); - name[len] = 0; - } - Exit: - loader->parser.error = error; - } + /* take an array of objects */ + Z1_ToTokenArray( &loader->parser, axis_tokens, + T1_MAX_MM_AXIS, &num_axis ); + if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS ) + { + FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n", + num_axis )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + /* allocate blend if necessary */ + error = t1_allocate_blend( face, 0, (FT_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++ ) + { + Z1_Token_Rec* token = axis_tokens + n; + FT_Byte* name; + FT_Int len; + + /* skip first slash, if any */ + if (token->start[0] == '/') + token->start++; + + len = token->limit - token->start; + if ( len <= 0 ) + { + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + if ( ALLOC( blend->axis_names[n], len + 1 ) ) + goto Exit; + + name = (FT_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, + Z1_Loader* loader ) + { + Z1_Token_Rec design_tokens[ T1_MAX_MM_DESIGNS ]; + FT_Int num_designs; + FT_Int num_axis; + Z1_Parser* parser = &loader->parser; + + FT_Error error = 0; + T1_Blend* blend; - static void parse_blend_design_positions( T1_Face face, Z1_Loader* loader ) - { - Z1_Token_Rec design_tokens[ T1_MAX_MM_DESIGNS ]; - FT_Int num_designs; - FT_Int num_axis; - Z1_Parser* parser = &loader->parser; - - FT_Error error = 0; - T1_Blend* blend; - - /* get the array of design tokens - compute number of designs */ - Z1_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 = T1_Err_Invalid_File_Format; - goto Exit; - } - - { - FT_Byte* old_cursor = parser->cursor; - FT_Byte* old_limit = parser->limit; - FT_UInt n; - - blend = face->blend; - num_axis = 0; /* make compiler happy */ - for ( n = 0; n < (FT_UInt)num_designs; n++ ) - { - Z1_Token_Rec axis_tokens[ T1_MAX_MM_DESIGNS ]; - Z1_Token_Rec* token; - FT_Int axis, n_axis; - - /* read axis/coordinates tokens */ - token = design_tokens + n; - parser->cursor = token->start - 1; - parser->limit = token->limit + 1; - Z1_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 = T1_Err_Invalid_File_Format; - goto Exit; - } - - /* now, read each axis token into the design position */ - for (axis = 0; axis < n_axis; axis++ ) - { - Z1_Token_Rec* token2 = axis_tokens + axis; - parser->cursor = token2->start; - parser->limit = token2->limit; - blend->design_pos[n][axis] = Z1_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, Z1_Loader* loader ) - { - FT_Error error = 0; - Z1_Parser* parser = &loader->parser; - T1_Blend* blend; - Z1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ]; - FT_Int n, num_axis; - FT_Byte* old_cursor; - FT_Byte* old_limit; - FT_Memory memory = face->root.memory; - - Z1_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 = T1_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; - Z1_Token_Rec* token; - FT_Int p, num_points; - - token = axis_tokens + n; - parser->cursor = token->start; - parser->limit = token->limit; - - /* count the number of map points */ - { - FT_Byte* p = token->start; - FT_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 = T1_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] = Z1_ToInt( parser ); - map->blend_points [p] = Z1_ToFixed( parser, 0 ); - } - } - - parser->cursor = old_cursor; - parser->limit = old_limit; - Exit: - parser->error = error; - } - - static void parse_weight_vector( T1_Face face, Z1_Loader* loader ) - { - FT_Error error = 0; - Z1_Parser* parser = &loader->parser; - T1_Blend* blend = face->blend; - Z1_Token_Rec master; - FT_UInt n; - FT_Byte* old_cursor; - FT_Byte* old_limit; - - if (!blend || blend->num_designs == 0) - { - FT_ERROR(( "t1.weight_vector: too early !!\n" )); - error = T1_Err_Invalid_File_Format; - goto Exit; - } - - Z1_ToToken( parser, &master ); - if (master.type != t1_token_array) - { - FT_ERROR(( "t1.weight_vector: incorrect format !!\n" )); - error = T1_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] = Z1_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, Z1_Loader* loader ) - { - Z1_Parser* parser = &loader->parser; - - FT_UNUSED(face); - - parser->cursor = parser->limit; - parser->error = 0; - } -#endif + + /* get the array of design tokens - compute number of designs */ + Z1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs ); + if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS ) + { + FT_ERROR(( "parse_blend_design_positions:" )); + FT_ERROR(( " incorrect number of designs: %d\n", + num_designs )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + { + FT_Byte* old_cursor = parser->cursor; + FT_Byte* old_limit = parser->limit; + FT_UInt n; + + + blend = face->blend; + num_axis = 0; /* make compiler happy */ + + for ( n = 0; n < (FT_UInt)num_designs; n++ ) + { + Z1_Token_Rec axis_tokens[ T1_MAX_MM_DESIGNS ]; + Z1_Token_Rec* token; + FT_Int axis, n_axis; + + + /* read axis/coordinates tokens */ + token = design_tokens + n; + parser->cursor = token->start - 1; + parser->limit = token->limit + 1; + Z1_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(( "parse_blend_design_positions: incorrect table\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + /* now, read each axis token into the design position */ + for ( axis = 0; axis < n_axis; axis++ ) + { + Z1_Token_Rec* token2 = axis_tokens + axis; + + + parser->cursor = token2->start; + parser->limit = token2->limit; + blend->design_pos[n][axis] = Z1_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, + Z1_Loader* loader ) + { + FT_Error error = 0; + Z1_Parser* parser = &loader->parser; + T1_Blend* blend; + Z1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ]; + FT_Int n, num_axis; + FT_Byte* old_cursor; + FT_Byte* old_limit; + FT_Memory memory = face->root.memory; + + + Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis ); + if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS ) + { + FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n", + num_axis )); + error = T1_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; + Z1_Token_Rec* token; + FT_Int p, num_points; + + + token = axis_tokens + n; + parser->cursor = token->start; + parser->limit = token->limit; + + /* count the number of map points */ + { + FT_Byte* p = token->start; + FT_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(( "parse_blend_design_map: incorrect table\n" )); + error = T1_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] = Z1_ToInt( parser ); + map->blend_points [p] = Z1_ToFixed( parser, 0 ); + } + } + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + parser->error = error; + } + + + static + void parse_weight_vector( T1_Face face, + Z1_Loader* loader ) + { + FT_Error error = 0; + Z1_Parser* parser = &loader->parser; + T1_Blend* blend = face->blend; + Z1_Token_Rec master; + FT_UInt n; + FT_Byte* old_cursor; + FT_Byte* old_limit; + + + if ( !blend || blend->num_designs == 0 ) + { + FT_ERROR(( "parse_weight_vector: too early!\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + Z1_ToToken( parser, &master ); + if ( master.type != t1_token_array ) + { + FT_ERROR(( "parse_weight_vector: incorrect format!\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + old_cursor = parser->cursor; + old_limit = parser->limit; - /***************************************************************************/ - /***************************************************************************/ - /***** *****/ - /***** TYPE 1 SYMBOL PARSING *****/ - /***** *****/ - /***************************************************************************/ - /***************************************************************************/ - - /********************************************************************* - * - * First of all, define the token field static variables. This is - * a set of Z1_Field_Rec variables used later.. - * - *********************************************************************/ - -#define Z1_NEW_STRING( _name, _field ) \ - static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_STRING( T1TYPE, _field ); - -#define Z1_NEW_BOOL( _name, _field ) \ - static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_BOOL( T1TYPE, _field ); + 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] = Z1_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, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + + FT_UNUSED( face ); + + + parser->cursor = parser->limit; + parser->error = 0; + } + +#endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE 1 SYMBOL PARSING *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* First of all, define the token field static variables. This is a set */ + /* of Z1_Field_Rec variables used later. */ + /* */ + /*************************************************************************/ + +#define Z1_NEW_STRING( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_STRING( T1TYPE, _field ); + +#define Z1_NEW_BOOL( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_BOOL( T1TYPE, _field ); -#define Z1_NEW_NUM( _name, _field ) \ - static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_NUM( T1TYPE, _field ); +#define Z1_NEW_NUM( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM( T1TYPE, _field ); -#define Z1_NEW_FIXED( _name, _field ) \ - static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_FIXED( T1TYPE, _field, _power ); - -#define Z1_NEW_NUM_TABLE( _name, _field, _max, _count ) \ - static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max ); +#define Z1_NEW_FIXED( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED( T1TYPE, _field, _power ); + +#define Z1_NEW_NUM_TABLE( _name, _field, _max, _count ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max ); -#define Z1_NEW_FIXED_TABLE( _name, _field, _max, _count ) \ - static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max ); - -#define Z1_NEW_NUM_TABLE2( _name, _field, _max ) \ - static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max ); +#define Z1_NEW_FIXED_TABLE( _name, _field, _max, _count ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max ); + +#define Z1_NEW_NUM_TABLE2( _name, _field, _max ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max ); -#define Z1_NEW_FIXED_TABLE2( _name, _field, _max ) \ - static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max ); +#define Z1_NEW_FIXED_TABLE2( _name, _field, _max ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max ); + +#define Z1_FONTINFO_STRING( n, f ) Z1_NEW_STRING( n, f ) +#define Z1_FONTINFO_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_FONTINFO_BOOL( n, f ) Z1_NEW_BOOL( n, f ) +#define Z1_PRIVATE_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_PRIVATE_FIXED( n, f ) Z1_NEW_FIXED( n, f ) +#define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_NEW_NUM_TABLE( n, f, m, c ) +#define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_NEW_NUM_TABLE2( n, f, m ) +#define Z1_TOPDICT_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_NEW_FIXED_TABLE2( n, f, m ) -#define Z1_FONTINFO_STRING(n,f) Z1_NEW_STRING(n,f) -#define Z1_FONTINFO_NUM(n,f) Z1_NEW_NUM(n,f) -#define Z1_FONTINFO_BOOL(n,f) Z1_NEW_BOOL(n,f) -#define Z1_PRIVATE_NUM(n,f) Z1_NEW_NUM(n,f) -#define Z1_PRIVATE_FIXED(n,f) Z1_NEW_FIXED(n,f) -#define Z1_PRIVATE_NUM_TABLE(n,f,m,c) Z1_NEW_NUM_TABLE(n,f,m,c) -#define Z1_PRIVATE_NUM_TABLE2(n,f,m) Z1_NEW_NUM_TABLE2(n,f,m) -#define Z1_TOPDICT_NUM(n,f) Z1_NEW_NUM(n,f) -#define Z1_TOPDICT_NUM_FIXED2(n,f,m) Z1_NEW_FIXED_TABLE2(n,f,m) -/* including this file defines all field variables */ + /* including this file defines all field variables */ #ifdef FT_FLAT_COMPILE + #include "z1tokens.h" + #else + #include + #endif - /********************************************************************* - * - * Second, define the keyword variables. This is a set of Z1_KeyWord - * structures used to model the way each keyword is "loaded".. - * - *********************************************************************/ - typedef void (*Z1_Parse_Func)( T1_Face face, Z1_Loader* loader ); + /*************************************************************************/ + /* */ + /* Second, define the keyword variables. This is a set of Z1_KeyWord */ + /* structures used to model the way each keyword is `loaded'. */ + /* */ + /*************************************************************************/ - typedef enum Z1_KeyWord_Type_ + typedef void (*Z1_Parse_Func)( T1_Face face, + Z1_Loader* loader ); + + + typedef enum Z1_KeyWord_Type_ { t1_keyword_callback = 0, t1_keyword_field, @@ -660,7 +770,8 @@ } Z1_KeyWord_Type; - typedef enum Z1_KeyWord_Location_ + + typedef enum Z1_KeyWord_Location_ { t1_keyword_type1 = 0, t1_keyword_font_info, @@ -668,7 +779,8 @@ } Z1_KeyWord_Location; - typedef struct Z1_KeyWord_ + + typedef struct Z1_KeyWord_ { const char* name; Z1_KeyWord_Type type; @@ -679,23 +791,38 @@ } Z1_KeyWord; -#define Z1_KEYWORD_CALLBACK( name, callback ) \ - { name, t1_keyword_callback, t1_keyword_type1, callback, 0 } +#define Z1_KEYWORD_CALLBACK( name, callback ) \ + { \ + name, t1_keyword_callback, t1_keyword_type1, callback, 0 \ + } -#define Z1_KEYWORD_TYPE1( name, f ) \ - { name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f } +#define Z1_KEYWORD_TYPE1( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f \ + } -#define Z1_KEYWORD_FONTINFO( name, f ) \ - { name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f } +#define Z1_KEYWORD_FONTINFO( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f \ + } -#define Z1_KEYWORD_PRIVATE( name, f ) \ - { name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f } +#define Z1_KEYWORD_PRIVATE( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f \ + } + +#define Z1_KEYWORD_FONTINFO_TABLE( name, f ) \ + { \ + name, t1_keyword_field_table, t1_keyword_font_info, 0, \ + &t1_field_ ## f \ + } -#define Z1_KEYWORD_FONTINFO_TABLE( name, f ) \ - { name, t1_keyword_field_table, t1_keyword_font_info, 0, &t1_field_ ## f } +#define Z1_KEYWORD_PRIVATE_TABLE( name, f ) \ + { \ + name, t1_keyword_field_table, t1_keyword_private, 0, \ + &t1_field_ ## f \ + } -#define Z1_KEYWORD_PRIVATE_TABLE( name, f ) \ - { name, t1_keyword_field_table, t1_keyword_private, 0, &t1_field_ ## f } #undef Z1_FONTINFO_STRING #undef Z1_FONTINFO_NUM @@ -707,75 +834,77 @@ #undef Z1_TOPDICT_NUM #undef Z1_TOPDICT_NUM_FIXED2 -#define Z1_FONTINFO_STRING(n,f) Z1_KEYWORD_FONTINFO(n,f), -#define Z1_FONTINFO_NUM(n,f) Z1_KEYWORD_FONTINFO(n,f), -#define Z1_FONTINFO_BOOL(n,f) Z1_KEYWORD_FONTINFO(n,f), -#define Z1_PRIVATE_NUM(n,f) Z1_KEYWORD_PRIVATE(n,f), -#define Z1_PRIVATE_FIXED(n,f) Z1_KEYWORD_PRIVATE(n,f), -#define Z1_PRIVATE_NUM_TABLE(n,f,m,c) Z1_KEYWORD_PRIVATE_TABLE(n,f), -#define Z1_PRIVATE_NUM_TABLE2(n,f,m) Z1_KEYWORD_PRIVATE_TABLE(n,f), -#define Z1_TOPDICT_NUM(n,f) Z1_KEYWORD_TYPE1(n,f), -#define Z1_TOPDICT_NUM_FIXED2(n,f,m) Z1_KEYWORD_TYPE1(n,f), +#define Z1_FONTINFO_STRING( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_FONTINFO_NUM( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_FONTINFO_BOOL( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_PRIVATE_NUM( n, f ) Z1_KEYWORD_PRIVATE( n, f ), +#define Z1_PRIVATE_FIXED( n, f ) Z1_KEYWORD_PRIVATE( n, f ), +#define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_KEYWORD_PRIVATE_TABLE( n, f ), +#define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_KEYWORD_PRIVATE_TABLE( n, f ), +#define Z1_TOPDICT_NUM( n, f ) Z1_KEYWORD_TYPE1( n, f ), +#define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_KEYWORD_TYPE1( n, f ), - static FT_Error t1_load_keyword( T1_Face face, - Z1_Loader* loader, - Z1_KeyWord* keyword ) + static + FT_Error t1_load_keyword( T1_Face face, + Z1_Loader* loader, + Z1_KeyWord* keyword ) { - FT_Error error; - void* dummy_object; - void** objects; - FT_UInt max_objects; - T1_Blend* blend = face->blend; + FT_Error error; + void* dummy_object; + void** objects; + FT_UInt max_objects; + T1_Blend* blend = face->blend; + /* if the keyword has a dedicated callback, call it */ - if (keyword->type == t1_keyword_callback) + 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) + /* 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; - } - } - break; + 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; + } + 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; + 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; + default: + dummy_object = &face->type1; + objects = &dummy_object; + max_objects = 0; } - if (keyword->type == t1_keyword_field_table) - error = Z1_Load_Field_Table( &loader->parser, keyword->field, objects, max_objects, 0 ); + if ( keyword->type == t1_keyword_field_table ) + error = Z1_Load_Field_Table( &loader->parser, keyword->field, + objects, max_objects, 0 ); else - error = Z1_Load_Field( &loader->parser, keyword->field, objects, max_objects, 0 ); + error = Z1_Load_Field( &loader->parser, keyword->field, + objects, max_objects, 0 ); Exit: return error; @@ -783,84 +912,91 @@ static - int is_space( char c ) + int is_space( char c ) { return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ); } + static int is_alpha( char c ) { - return ( (c >= 'A' && c <= 'Z') || - (c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9') || - (c == '.') || - (c == '_') ); + return ( isalnum( c ) || + ( c == '.' ) || + ( c == '_' ) ); } + static - void skip_whitespace( Z1_Parser* parser ) + void skip_whitespace( Z1_Parser* parser ) { FT_Byte* cur = parser->cursor; - while ( cur < parser->limit && is_space(*cur) ) + + while ( cur < parser->limit && is_space( *cur ) ) cur++; parser->cursor = cur; } + static - void skip_blackspace( Z1_Parser* parser ) + void skip_blackspace( Z1_Parser* parser ) { FT_Byte* cur = parser->cursor; - while ( cur < parser->limit && !is_space(*cur) ) + while ( cur < parser->limit && !is_space( *cur ) ) cur++; parser->cursor = cur; } + static - int read_binary_data( Z1_Parser* parser, FT_Int *size, FT_Byte* *base ) + int read_binary_data( Z1_Parser* parser, + FT_Int* size, + FT_Byte** base ) { FT_Byte* cur; FT_Byte* limit = parser->limit; + /* the binary data has the following format */ /* */ - /* "size" [white*] RD white ....... ND */ + /* `size' [white*] RD white ....... ND */ /* */ - skip_whitespace(parser); + skip_whitespace( parser ); cur = parser->cursor; - if ( cur < limit && (FT_Byte)(*cur-'0') < 10 ) + if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 ) { - *size = Z1_ToInt(parser); + *size = Z1_ToInt( parser ); - skip_whitespace(parser); - skip_blackspace(parser); /* "RD" or "-|" or something else */ + skip_whitespace( parser ); + skip_blackspace( parser ); /* `RD' or `-|' or something else */ /* there is only one whitespace char after the */ - /* "RD" or "-|" token */ + /* `RD' or `-|' token */ *base = parser->cursor + 1; parser->cursor += *size+1; return 1; } - FT_ERROR(( "type1.read_binary_data: invalid size field\n" )); + FT_ERROR(( "read_binary_data: invalid size field\n" )); parser->error = T1_Err_Invalid_File_Format; return 0; } /* we will now define the routines used to handle */ - /* the /Encoding, /Subrs and /CharStrings */ - /* dictionaries.. */ + /* the `/Encoding', `/Subrs', and `/CharStrings' */ + /* dictionaries */ static - void parse_font_name( T1_Face face, Z1_Loader* loader ) + void parse_font_name( T1_Face face, + Z1_Loader* loader ) { Z1_Parser* parser = &loader->parser; FT_Error error; @@ -870,18 +1006,24 @@ FT_Byte* cur2; FT_Byte* limit; - skip_whitespace(parser); + + skip_whitespace( parser ); + cur = parser->cursor; limit = parser->limit; - if ( cur >= limit-1 || *cur != '/' ) return; + + if ( cur >= limit - 1 || *cur != '/' ) + return; cur++; cur2 = cur; - while (cur2 < limit && is_alpha(*cur2)) cur2++; - len = cur2-cur; - if (len > 0) + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + + len = cur2 - cur; + if ( len > 0 ) { - if ( ALLOC( face->type1.font_name, len+1 ) ) + if ( ALLOC( face->type1.font_name, len + 1 ) ) { parser->error = error; return; @@ -893,12 +1035,15 @@ parser->cursor = cur2; } + static - void parse_font_bbox( T1_Face face, Z1_Loader* loader ) + void parse_font_bbox( T1_Face face, + Z1_Loader* loader ) { Z1_Parser* parser = &loader->parser; FT_Short temp[4]; - FT_BBox* bbox = &face->type1.font_bbox; + FT_BBox* bbox = &face->type1.font_bbox; + (void)Z1_ToCoordArray( parser, 4, temp ); bbox->xMin = temp[0]; @@ -907,13 +1052,16 @@ bbox->yMax = temp[3]; } + static - void parse_font_matrix( T1_Face face, Z1_Loader* loader ) + void parse_font_matrix( T1_Face face, + Z1_Loader* loader ) { Z1_Parser* parser = &loader->parser; FT_Matrix* matrix = &face->type1.font_matrix; FT_Fixed temp[4]; + (void)Z1_ToFixedArray( parser, 4, temp, 3 ); matrix->xx = temp[0]; matrix->yx = temp[1]; @@ -922,21 +1070,22 @@ } - static - void parse_encoding( T1_Face face, Z1_Loader* loader ) + void parse_encoding( T1_Face face, + Z1_Loader* loader ) { Z1_Parser* parser = &loader->parser; FT_Byte* cur = parser->cursor; FT_Byte* limit = parser->limit; + /* skip whitespace */ - while (is_space(*cur)) + while ( is_space( *cur ) ) { cur++; - if (cur >= limit) + if ( cur >= limit ) { - FT_ERROR(( "type1.parse_encoding: out of bounds !!\n" )); + FT_ERROR(( "parse_encoding: out of bounds!\n" )); parser->error = T1_Err_Invalid_File_Format; return; } @@ -944,7 +1093,7 @@ /* if we have a number, then the encoding is an array, */ /* and we must load it now */ - if ((FT_Byte)(*cur - '0') < 10) + if ( (FT_Byte)( *cur - '0' ) < 10 ) { T1_Encoding* encode = &face->type1.encoding; FT_Int count, n; @@ -952,33 +1101,34 @@ FT_Memory memory = parser->memory; FT_Error error; + /* read the number of entries in the encoding, should be 256 */ count = Z1_ToInt( parser ); - if (parser->error) return; + if ( parser->error ) + return; /* we use a Z1_Table to store our charnames */ encode->num_chars = count; - if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) || - ALLOC_ARRAY( encode->char_name, count, FT_String* ) || - (error = Z1_New_Table( char_table, count, memory )) != 0 ) + if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) || + ALLOC_ARRAY( encode->char_name, count, FT_String* ) || + ( error = Z1_New_Table( char_table, count, memory ) ) != 0 ) { parser->error = error; return; } - /* now, we will need to read a record of the form */ + /* Now, we will need to read a record of the form */ /* ... charcode /charname ... for each entry in our table */ /* */ - /* we simply look for a number followed by an immediate */ - /* name. Note that this ignores correctly the sequence */ - /* that is often seen in type1 fonts : */ + /* We simply look for a number followed by an immediate */ + /* name. Note that this ignores correctly the sequence */ + /* that is often seen in type1 fonts: */ /* */ /* 0 1 255 { 1 index exch /.notdef put } for dup */ /* */ - /* used to clean the encoding array before anything else */ - /* */ - /* we stop when we encounter a "def" */ + /* used to clean the encoding array before anything else. */ /* */ + /* We stop when we encounter a `def'. */ cur = parser->cursor; limit = parser->limit; @@ -988,45 +1138,54 @@ { FT_Byte c; + c = *cur; - /* we stop when we encounter a 'def' */ - if ( c == 'd' && cur+3 < limit ) + /* we stop when we encounter a `def' */ + if ( c == 'd' && cur + 3 < limit ) { if ( cur[1] == 'e' && cur[2] == 'f' && is_space(cur[-1]) && is_space(cur[3]) ) { - FT_TRACE6(( "encoding end\n" )); - break; + FT_TRACE6(( "encoding end\n" )); + break; } } /* otherwise, we must find a number before anything else */ - if ( (FT_Byte)(c-'0') < 10 ) + if ( (FT_Byte)( c - '0' ) < 10 ) { FT_Int charcode; + parser->cursor = cur; - charcode = Z1_ToInt(parser); + charcode = Z1_ToInt( parser ); cur = parser->cursor; /* skip whitespace */ - while (cur < limit && is_space(*cur)) cur++; + while ( cur < limit && is_space( *cur ) ) + cur++; - if (cur < limit && *cur == '/') + if ( cur < limit && *cur == '/' ) { - /* bingo, we have an immediate name - it must be a */ - /* character name */ - FT_Byte* cur2 = cur+1; + /* bingo, we have an immediate name -- it must be a */ + /* character name */ + FT_Byte* cur2 = cur + 1; FT_Int len; - while (cur2 < limit && is_alpha(*cur2)) cur2++; - len = cur2-cur-1; - parser->error = Z1_Add_Table( char_table, charcode, cur+1, len+1 ); + + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + + len = cur2 - cur - 1; + + parser->error = Z1_Add_Table( char_table, charcode, + cur + 1, len + 1 ); char_table->elements[charcode][len] = '\0'; - if (parser->error) return; + if ( parser->error ) + return; cur = cur2; } @@ -1038,21 +1197,21 @@ face->type1.encoding_type = t1_encoding_array; parser->cursor = cur; } - /* Otherwise, we should have either "StandardEncoding" or */ - /* "ExpertEncoding" */ + /* Otherwise, we should have either `StandardEncoding' or */ + /* `ExpertEncoding' */ else { - if ( cur+17 < limit && + if ( cur + 17 < limit && strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) face->type1.encoding_type = t1_encoding_standard; - else if ( cur+15 < limit && + else if ( cur + 15 < limit && strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) face->type1.encoding_type = t1_encoding_expert; else { - FT_ERROR(( "type1.parse_encoding: invalid token !!\n" )); + FT_ERROR(( "parse_encoding: invalid token!\n" )); parser->error = T1_Err_Invalid_File_Format; } } @@ -1060,7 +1219,8 @@ static - void parse_subrs( T1_Face face, Z1_Loader* loader ) + void parse_subrs( T1_Face face, + Z1_Loader* loader ) { Z1_Parser* parser = &loader->parser; Z1_Table* table = &loader->subrs; @@ -1068,16 +1228,19 @@ FT_Error error; FT_Int n; + loader->num_subrs = Z1_ToInt( parser ); - if (parser->error) return; + if ( parser->error ) + return; - /* initialise subrs array */ + /* initialize subrs array */ error = Z1_New_Table( table, loader->num_subrs, memory ); - if (error) goto Fail; + if ( error ) + goto Fail; - /* the format is simple : */ + /* the format is simple: */ /* */ - /* "index" + binary data */ + /* `index' + binary data */ /* */ for ( n = 0; n < loader->num_subrs; n++ ) @@ -1085,15 +1248,17 @@ FT_Int index, size; FT_Byte* base; - index = Z1_ToInt(parser); - if (!read_binary_data(parser,&size,&base)) return; + + index = Z1_ToInt( parser ); + if ( !read_binary_data( parser, &size, &base ) ) + return; /* some fonts use a value of -1 for lenIV to indicate that */ /* the charstrings are unencoded.. */ /* */ /* thanks to Tom Kacvinsky for pointing this out.. */ /* */ - if (face->type1.private_dict.lenIV >= 0) + if ( face->type1.private_dict.lenIV >= 0 ) { Z1_Decrypt( base, size, 4330 ); size -= face->type1.private_dict.lenIV; @@ -1101,7 +1266,8 @@ } error = Z1_Add_Table( table, index, base, size ); - if (error) goto Fail; + if ( error ) + goto Fail; } return; @@ -1110,10 +1276,9 @@ } - - static - void parse_charstrings( T1_Face face, Z1_Loader* loader ) + void parse_charstrings( T1_Face face, + Z1_Loader* loader ) { Z1_Parser* parser = &loader->parser; Z1_Table* code_table = &loader->charstrings; @@ -1125,67 +1290,72 @@ FT_Byte* limit = parser->limit; FT_Int n; + loader->num_glyphs = Z1_ToInt( parser ); - if (parser->error) return; + if ( parser->error ) + return; - /* initialise tables */ + /* initialize tables */ error = Z1_New_Table( code_table, loader->num_glyphs, memory ) || Z1_New_Table( name_table, loader->num_glyphs, memory ); - if (error) goto Fail; + if ( error ) + goto Fail; n = 0; - for ( ;; ) + for (;;) { FT_Int size; FT_Byte* base; - /* the format is simple : */ - /* "/glyphname" + binary data */ + + /* the format is simple: */ + /* `/glyphname' + binary data */ /* */ - /* note that we stop when we find a "def" */ + /* note that we stop when we find a `def' */ /* */ - skip_whitespace(parser); + skip_whitespace( parser ); + cur = parser->cursor; - if (cur >= limit) break; + if ( cur >= limit ) + break; - /* we stop when we find a "def" or "end" keyword */ - if (*cur == 'd' && - cur+3 < limit && - cur[1] == 'e' && - cur[2] == 'f' ) + /* we stop when we find a `def' or `end' keyword */ + if ( *cur == 'd' && + cur + 3 < limit && + cur[1] == 'e' && + cur[2] == 'f' ) break; - if (*cur == 'e' && - cur+3 < limit && - cur[1] == 'n' && - cur[2] == 'd' ) + if ( *cur == 'e' && + cur + 3 < limit && + cur[1] == 'n' && + cur[2] == 'd' ) break; - if (*cur != '/') - skip_blackspace(parser); + if ( *cur != '/' ) + skip_blackspace( parser ); else { - FT_Byte* cur2 = cur+1; + FT_Byte* cur2 = cur + 1; FT_Int len; - while (cur2 < limit && is_alpha(*cur2)) cur2++; - len = cur2-cur-1; - error = Z1_Add_Table( name_table, n, cur+1, len+1 ); - if (error) goto Fail; + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + len = cur2 - cur - 1; + + error = Z1_Add_Table( name_table, n, cur + 1, len + 1 ); + if ( error ) + goto Fail; /* add a trailing zero to the name table */ name_table->elements[n][len] = '\0'; parser->cursor = cur2; - if (!read_binary_data(parser,&size,&base)) return; - - /* some fonts use a value of -1 for lenIV to indicate that */ - /* the charstrings are unencoded.. */ - /* */ - /* thanks to Tom Kacvinsky for pointing this out.. */ - /* */ - if (face->type1.private_dict.lenIV >= 0) + if ( !read_binary_data( parser, &size, &base ) ) + return; + + if ( face->type1.private_dict.lenIV >= 0 ) { Z1_Decrypt( base, size, 4330 ); size -= face->type1.private_dict.lenIV; @@ -1193,10 +1363,11 @@ } error = Z1_Add_Table( code_table, n, base, size ); - if (error) goto Fail; + if ( error ) + goto Fail; n++; - if (n >= loader->num_glyphs) + if ( n >= loader->num_glyphs ) break; } } @@ -1208,31 +1379,36 @@ } - - static const Z1_KeyWord t1_keywords[] = { + #ifdef FT_FLAT_COMPILE + #include "z1tokens.h" + #else + #include + #endif /* now add the special functions... */ Z1_KEYWORD_CALLBACK( "FontName", parse_font_name ), Z1_KEYWORD_CALLBACK( "FontBBox", parse_font_bbox ), Z1_KEYWORD_CALLBACK( "FontMatrix", parse_font_matrix ), - Z1_KEYWORD_CALLBACK( "Encoding", parse_encoding ), - Z1_KEYWORD_CALLBACK( "Subrs", parse_subrs ), + Z1_KEYWORD_CALLBACK( "Encoding", parse_encoding ), + Z1_KEYWORD_CALLBACK( "Subrs", parse_subrs ), Z1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings ), + #ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT Z1_KEYWORD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ), Z1_KEYWORD_CALLBACK( "BlendDesignMap", parse_blend_design_map ), Z1_KEYWORD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ), Z1_KEYWORD_CALLBACK( "WeightVector", parse_weight_vector ), - Z1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict ), + Z1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict ), #endif + Z1_KEYWORD_CALLBACK( 0, 0 ) }; @@ -1243,61 +1419,68 @@ FT_Byte* base, FT_Long size ) { - Z1_Parser* parser = &loader->parser; + Z1_Parser* parser = &loader->parser; + parser->cursor = base; parser->limit = base + size; parser->error = 0; { - FT_Byte* cur = base; - FT_Byte* limit = cur + size; + FT_Byte* cur = base; + FT_Byte* limit = cur + size; + - for ( ;cur < limit; cur++ ) + for ( ; cur < limit; cur++ ) { - /* look for "FontDirectory", which causes problems on some fonts */ - if ( *cur == 'F' && cur+25 < limit && + /* look for `FontDirectory', which causes problems on some fonts */ + if ( *cur == 'F' && cur + 25 < limit && strncmp( (char*)cur, "FontDirectory", 13 ) == 0 ) { FT_Byte* cur2; - /* skip the "FontDirectory" keyword */ + + /* skip the `FontDirectory' keyword */ cur += 13; cur2 = cur; - /* lookup the 'known' keyword */ - while (cur < limit && *cur != 'k' && strncmp( (char*)cur, "known", 5 ) ) + /* lookup the `known' keyword */ + while ( cur < limit && *cur != 'k' && + strncmp( (char*)cur, "known", 5 ) ) cur++; - if (cur < limit) + if ( cur < limit ) { Z1_Token_Rec token; - /* skip the "known" keyword and the token following it */ + + /* skip the `known' keyword and the token following it */ cur += 5; loader->parser.cursor = cur; Z1_ToToken( &loader->parser, &token ); - /* if the last token was an array, skip it !! */ - if (token.type == t1_token_array) + /* if the last token was an array, skip it! */ + if ( token.type == t1_token_array ) cur2 = parser->cursor; } cur = cur2; } /* look for immediates */ - else if (*cur == '/' && cur+2 < limit) + else if ( *cur == '/' && cur + 2 < limit ) { - FT_Byte* cur2; - FT_Int len; + FT_Byte* cur2; + FT_Int len; + - cur ++; + cur++; cur2 = cur; - while (cur2 < limit && is_alpha(*cur2)) cur2++; - len = cur2-cur; + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; - if (len > 0 && len < 22) + len = cur2 - cur; + if ( len > 0 && len < 22 ) { - if (!loader->fontdata) + if ( !loader->fontdata ) { if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 ) loader->fontdata = 1; @@ -1307,28 +1490,33 @@ /* now, compare the immediate name to the keyword table */ Z1_KeyWord* keyword = (Z1_KeyWord*)t1_keywords; + for (;;) { FT_Byte* name; + name = (FT_Byte*)keyword->name; - if (!name) break; + if ( !name ) + break; - if ( cur[0] == name[0] && - len == (FT_Int)strlen((const char*)name) ) + if ( cur[0] == name[0] && + len == (FT_Int)strlen( (const char*)name ) ) { FT_Int n; + + for ( n = 1; n < len; n++ ) - if (cur[n] != name[n]) + if ( cur[n] != name[n] ) break; - if (n >= len) + if ( n >= len ) { - /* we found it - run the parsing callback !! */ + /* we found it -- run the parsing callback! */ parser->cursor = cur2; skip_whitespace( parser ); parser->error = t1_load_keyword( face, loader, keyword ); - if (parser->error) + if ( parser->error ) return parser->error; cur = parser->cursor; @@ -1345,16 +1533,18 @@ return parser->error; } + static - void t1_init_loader( Z1_Loader* loader, T1_Face face ) + void t1_init_loader( Z1_Loader* loader, + T1_Face face ) { - FT_UNUSED(face); + FT_UNUSED( face ); - MEM_Set( loader, 0, sizeof(*loader) ); + MEM_Set( loader, 0, sizeof ( *loader ) ); loader->num_glyphs = 0; loader->num_chars = 0; - /* initialize the tables - simply set their 'init' field to 0 */ + /* initialize the tables -- simply set their `init' field to 0 */ loader->encoding_table.init = 0; loader->charstrings.init = 0; loader->glyph_names.init = 0; @@ -1362,11 +1552,13 @@ loader->fontdata = 0; } + static - void t1_done_loader( Z1_Loader* loader ) + void t1_done_loader( Z1_Loader* loader ) { Z1_Parser* parser = &loader->parser; + /* finalize tables */ Z1_Release_Table( &loader->encoding_table ); Z1_Release_Table( &loader->charstrings ); @@ -1377,13 +1569,15 @@ Z1_Done_Parser( parser ); } + LOCAL_FUNC FT_Error Z1_Open_Face( T1_Face face ) { - Z1_Loader loader; - Z1_Parser* parser; - T1_Font* type1 = &face->type1; - FT_Error error; + Z1_Loader loader; + Z1_Parser* parser; + T1_Font* type1 = &face->type1; + FT_Error error; + t1_init_loader( &loader, face ); @@ -1392,30 +1586,35 @@ parser = &loader.parser; error = Z1_New_Parser( parser, face->root.stream, face->root.memory ); - if (error) goto Exit; + if ( error ) + goto Exit; error = parse_dict( face, &loader, parser->base_dict, parser->base_len ); - if (error) goto Exit; + if ( error ) + goto Exit; error = Z1_Get_Private_Dict( parser ); - if (error) goto Exit; + if ( error ) + goto Exit; - error = parse_dict( face, &loader, parser->private_dict, parser->private_len ); - if (error) goto Exit; + error = parse_dict( face, &loader, parser->private_dict, + parser->private_len ); + if ( error ) + goto Exit; - /* now, propagate the subrs, charstrings and glyphnames tables */ - /* to the Type1 data */ + /* now, propagate the subrs, charstrings, and glyphnames tables */ + /* to the Type1 data */ type1->num_glyphs = loader.num_glyphs; if ( !loader.subrs.init ) { - FT_ERROR(( "T1.Open_Face: no subrs array in face !!\n" )); + FT_ERROR(( "Z1_Open_Face: no subrs array in face!\n" )); error = T1_Err_Invalid_File_Format; } if ( !loader.charstrings.init ) { - FT_ERROR(( "T1.Open_Face: no charstrings array in face !!\n" )); + FT_ERROR(( "Z1_Open_Face: no charstrings array in face!\n" )); error = T1_Err_Invalid_File_Format; } @@ -1430,8 +1629,8 @@ type1->charstrings = loader.charstrings.elements; type1->charstrings_len = loader.charstrings.lengths; - /* we copy the glyph names "block" and "elements" fields */ - /* but the "lengths" field must be released later.. */ + /* we copy the glyph names `block' and `elements' fields; */ + /* the `lengths' field must be released later */ type1->glyph_names_block = loader.glyph_names.block; type1->glyph_names = (FT_String**)loader.glyph_names.elements; loader.glyph_names.block = 0; @@ -1445,8 +1644,9 @@ FT_Byte* char_name; FT_Byte* glyph_name; - /* OK, we do the following : for each element in the encoding */ - /* table, lookup the index of the glyph having the same name */ + + /* OK, we do the following: for each element in the encoding */ + /* table, look up the index of the glyph having the same name */ /* the index is then stored in type1.encoding.char_index, and */ /* a the name to type1.encoding.char_name */ @@ -1460,7 +1660,7 @@ type1->encoding.char_name [charcode] = ".notdef"; char_name = loader.encoding_table.elements[charcode]; - if (char_name) + if ( char_name ) for ( index = 0; index < type1->num_glyphs; index++ ) { glyph_name = (FT_Byte*)type1->glyph_names[index]; @@ -1485,3 +1685,6 @@ t1_done_loader( &loader ); return error; } + + +/* END */