From 0dd343480186b918e3b7ef71b9d4bb8260f48cea Mon Sep 17 00:00:00 2001 From: David Turner Date: Wed, 2 Feb 2000 12:20:53 +0000 Subject: [PATCH] The Type 1 experimental driver was updated - small reduction of the code size of "t1encode.c" - removed the hinter (not useful with the upcoming auto-hinter..) - updated "t1load.c" to reduce warnings with Visual C++ - considerably changed the glyph loader (it is simpler) Beware, this code is still experimental, and is _not_ debugged. I don't even guarantee that it works for now - David --- src/type1z/rules.mk | 11 +- src/type1z/t1encode.c | 54 +- src/type1z/t1encode.h | 13 +- src/type1z/t1gload.c | 1624 +++++++++++++++-------------------------- src/type1z/t1gload.h | 230 +----- src/type1z/t1load.c | 28 +- src/type1z/t1objs.c | 36 +- src/type1z/t1tokens.h | 8 +- src/type1z/type1z.c | 3 - 9 files changed, 637 insertions(+), 1370 deletions(-) diff --git a/src/type1z/rules.mk b/src/type1z/rules.mk index fb69d2105..d4bc25d11 100644 --- a/src/type1z/rules.mk +++ b/src/type1z/rules.mk @@ -106,13 +106,10 @@ T1Z_COMPILE := $(FT_COMPILE) $(T1Z_INCLUDE:%=$I%) # Type1 driver sources (i.e., C files) # T1Z_DRV_SRC := $(T1Z_DIR_)t1parse.c \ - $(T1Z_DIR_)t1load.c -# $(T1Z_DIR_)t1parse.c \ -# $(T1Z_DIR_)t1tokens.c \ -# $(T1Z_DIR_)t1driver.c \ -# $(T1Z_DIR_)t1encode.c \ -# $(T1Z_DIR_)t1hinter.c \ -# $(T1Z_DIR_)t1gload.c + $(T1Z_DIR_)t1load.c \ + $(T1Z_DIR_)t1driver.c \ + $(T1Z_DIR_)t1encode.c \ + $(T1Z_DIR_)t1gload.c # Type1 driver headers diff --git a/src/type1z/t1encode.c b/src/type1z/t1encode.c index 9c91027a7..d4bdfde4a 100644 --- a/src/type1z/t1encode.c +++ b/src/type1z/t1encode.c @@ -184,14 +184,14 @@ /* */ /* t1_standard_encoding[33] == 2 */ /* */ - /* which means that the glyph name for character code 32 is */ + /* which means that the glyph name for character code 33 is */ /* */ /* t1_standard_strings[2] == "exclam" */ /* */ /* (this correspond to the exclamation mark `!'). */ /* */ LOCAL_FUNC - T1_Short t1_standard_encoding[256] = + T1_Byte t1_standard_encoding[256] = { /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -240,7 +240,7 @@ /* */ /* t1_expert_encoding[33] == 229 */ /* */ - /* which means that the glyph name for character code 32 is */ + /* which means that the glyph name for character code 33 is */ /* */ /* t1_standard_strings[229] == "exclamsmall" */ /* */ @@ -281,52 +281,4 @@ 373, 374, 375, 376, 377, 378 }; - - /*************************************************************************/ - /* */ - /* t1_expert_subset_encoding: */ - /* */ - /* A simple table used to encode the Adobe ExpertEncoding subset */ - /* defined in the CFF specification. It will probably evolve into */ - /* another form sooner or later, as we deal with charsets */ - /* differently than with encodings. */ - /* */ - LOCAL_FUNC - FT_Short t1_expert_subset_encoding[256] = - { - /* 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 231, 232, 0, 0, - 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, - /* 50 */ - 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, - 249, 250, 251, 252, 0, 253, 254, 255, 256, 257, - 0, 0, 0, 258, 0, 0, 259, 260, 261, 262, - 0, 0, 263, 264, 265, 0, 266, 109, 110, 267, - 268, 269, 0, 270, 0, 272, 0, 0, 0, 0, - /* 100 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 300, 301, 302, 303, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 150 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 304, 305, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 314, 315, - 0, 0, 0, 0, 0, 0, 0, 0, 158, 155, - 163, 0, 320, 321, 322, 323, 324, 325, 0, 0, - /* 200 */ - 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, - 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, - 343, 344, 345, 346, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 250 */ - 0, 0, 0, 0, 0, 0 - }; - - /* END */ diff --git a/src/type1z/t1encode.h b/src/type1z/t1encode.h index 0f5c0d7c0..7162509a6 100644 --- a/src/type1z/t1encode.h +++ b/src/type1z/t1encode.h @@ -56,7 +56,7 @@ /* (this correspond to the exclamation mark `!'). */ /* */ LOCAL_DEF - T1_Short t1_standard_encoding[256]; + T1_Byte t1_standard_encoding[256]; /*************************************************************************/ @@ -79,17 +79,6 @@ T1_Short t1_expert_encoding[256]; - /*************************************************************************/ - /* */ - /* t1_expert_subset_encoding: */ - /* */ - /* A simple table used to encode the Adobe ExpertEncoding subset */ - /* defined in the CFF specification. It will probably evolve into */ - /* another form sooner or later, as we deal with charsets */ - /* differently than with encodings. */ - /* */ - LOCAL_DEF - T1_Short t1_expert_subset_encoding[256]; #endif /* T1ENCODE_H */ diff --git a/src/type1z/t1gload.c b/src/type1z/t1gload.c index 05cd0a26b..0b1d8f4f5 100644 --- a/src/type1z/t1gload.c +++ b/src/type1z/t1gload.c @@ -20,10 +20,6 @@ #include #include -#ifndef T1_CONFIG_OPTION_DISABLE_HINTER -#include -#endif - /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ @@ -49,23 +45,19 @@ * face :: current face object * size :: current size object * glyph :: current glyph object - * funcs :: glyph builder functions (or "methods"). * *********************************************************************/ - EXPORT_FUNC - void T1_Init_Builder( T1_Builder* builder, - T1_Face face, - T1_Size size, - T1_GlyphSlot glyph, - const T1_Builder_Funcs* funcs ) + LOCAL_FUNC + void T1_Init_Builder( T1_Builder* builder, + T1_Face face, + T1_Size size, + T1_GlyphSlot glyph ) { - builder->funcs = *funcs; builder->path_begun = 0; builder->load_points = 1; builder->face = face; - builder->size = size; builder->glyph = glyph; builder->memory = face->root.memory; @@ -93,9 +85,6 @@ builder->base.n_points = 0; builder->base.n_contours = 0; builder->current = builder->base; - - builder->pass = 0; - builder->hint_point = 0; } @@ -114,7 +103,7 @@ * *********************************************************************/ - EXPORT_FUNC + LOCAL_FUNC void T1_Done_Builder( T1_Builder* builder ) { T1_GlyphSlot glyph = builder->glyph; @@ -144,13 +133,10 @@ *********************************************************************/ EXPORT_FUNC - void T1_Init_Decoder( T1_Decoder* decoder, - const T1_Hinter_Funcs* funcs ) + void T1_Init_Decoder( T1_Decoder* decoder ) { - decoder->hinter = *funcs; /* copy hinter interface */ - decoder->top = 0; - decoder->zone = 0; - + decoder->top = 0; + decoder->zone = 0; decoder->flex_state = 0; decoder->num_flex_vectors = 0; @@ -159,6 +145,150 @@ } + /* check that there is enough room for "count" more points */ + static + T1_Error check_points( T1_Builder* builder, + T1_Int count ) + { + FT_Outline* base = &builder->base; + FT_Outline* outline = &builder->current; + + if (!builder->load_points) + return T1_Err_Ok; + + count += base->n_points + outline->n_points; + + /* realloc points table if necessary */ + if ( count >= builder->max_points ) + { + T1_Error error; + FT_Memory memory = builder->memory; + T1_Int increment = outline->points - base->points; + T1_Int current = builder->max_points; + + while ( builder->max_points < count ) + builder->max_points += 8; + + if ( REALLOC_ARRAY( base->points, current, + builder->max_points, T1_Vector ) || + + REALLOC_ARRAY( base->flags, current, + builder->max_points, T1_Byte ) ) + { + builder->error = error; + return error; + } + + outline->points = base->points + increment; + outline->flags = base->flags + increment; + } + return T1_Err_Ok; + } + + + /* add a new point, do not check room */ + static + void add_point( T1_Builder* builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ) + { + FT_Outline* outline = &builder->current; + + if (builder->load_points) + { + FT_Vector* point = outline->points + outline->n_points; + FT_Byte* control = (FT_Byte*)outline->flags + outline->n_points; + + point->x = x; + point->y = y; + *control = ( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic ); + + builder->last = *point; + } + + outline->n_points++; + } + + + /* check room for a new on-curve point, then add it */ + static + T1_Error add_point1( T1_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + T1_Error error; + + error = check_points(builder,1); + if (!error) + add_point( builder, x, y, 1 ); + + return error; + } + + + /* check room for a new contour, then add it */ + static + T1_Error add_contour( T1_Builder* builder ) + { + FT_Outline* base = &builder->base; + FT_Outline* outline = &builder->current; + + if (!builder->load_points) + { + outline->n_contours++; + return T1_Err_Ok; + } + + /* realloc contours array if necessary */ + if ( base->n_contours + outline->n_contours >= builder->max_contours && + builder->load_points ) + { + T1_Error error; + FT_Memory memory = builder->memory; + T1_Int increment = outline->contours - base->contours; + T1_Int current = builder->max_contours; + + builder->max_contours += 4; + + if ( REALLOC_ARRAY( base->contours, + current, builder->max_contours, T1_Short ) ) + { + builder->error = error; + return error; + } + + outline->contours = base->contours + increment; + } + + if (outline->n_contours > 0) + outline->contours[ outline->n_contours-1 ] = outline->n_points-1; + + return T1_Err_Ok; + } + + + /* if a path was begun, add its first on-curve point */ + static + T1_Error start_point( T1_Builder* builder, + T1_Pos x, + T1_Pos y ) + { + return builder->path_begun && add_point1( builder, x, y ); + } + + + /* close the current contour */ + static + void close_contour( T1_Builder* builder ) + { + FT_Outline* outline = &builder->current; + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours-1] = outline->n_points-1; + } + + /********************************************************************* * * @@ -195,7 +325,7 @@ { T1_String* name = (T1_String*)face->type1.glyph_names[n]; - if ( name && strcmp(name,glyph_name) == 0 ) + if ( name && name[0] == glyph_name[0] && strcmp(name,glyph_name) == 0 ) return n; } @@ -203,6 +333,7 @@ } + /********************************************************************* * * @@ -293,6 +424,7 @@ if (error) return error; /* adjust contours in accented character outline */ + if (decoder->builder.load_points) { T1_Int n; @@ -306,75 +438,13 @@ decoder->builder.advance = advance; /* Finally, move the accent */ - FT_Translate_Outline( cur, adx - asb, ady ); + if (decoder->builder.load_points) + FT_Translate_Outline( cur, adx - asb, ady ); (void)asb; /* ignore this parameter */ return T1_Err_Ok; } -/********************************************************************* - * - * - * t1operator_flex - * - * - * Implements the "flex" Type 1 operator for a Type 1 decoder - * - * - * decoder :: current Type 1 decoder - * threshold :: threshold - * end_x :: position of final flex point - * end_y :: position of final flex point - * - * - * Error code. 0 means success. - * - *********************************************************************/ - - static - T1_Error t1operator_flex( T1_Decoder* decoder, - T1_Pos threshold, - T1_Pos end_x, - T1_Pos end_y ) - { - T1_Vector vec; - T1_Vector* flex = decoder->flex_vectors; - T1_Int n; - - /* we don't even try to test the threshold in the non-hinting */ - /* builder, even if the flex operator is said to be a path */ - /* construction statement in the specification. This is better */ - /* left to the hinter.. */ - - flex = decoder->flex_vectors; - vec = *flex++; - - for ( n = 0; n < 6; n++ ) - { - flex->x += vec.x; - flex->y += vec.y; - - vec = *flex++; - } - - - (void)threshold; - (void)end_x; - (void)end_y; - - flex = decoder->flex_vectors; - - return decoder->builder.funcs.rcurve_to( &decoder->builder, - flex[0].x, flex[0].y, - flex[1].x, flex[1].y, - flex[2].x, flex[2].y ) || - - decoder->builder.funcs.rcurve_to( &decoder->builder, - flex[3].x, flex[3].y, - flex[4].x, flex[4].y, - flex[5].x, flex[5].y ); - } - /********************************************************************* * @@ -397,6 +467,8 @@ * *********************************************************************/ +#define USE_ARGS(n) top -= n; if (top < decoder->stack) goto Stack_Underflow + EXPORT_FUNC T1_Error T1_Parse_CharStrings( T1_Decoder* decoder, T1_Byte* charstring_base, @@ -410,38 +482,8 @@ T1_Byte* ip; T1_Byte* limit; T1_Builder* builder = &decoder->builder; - T1_Builder_Funcs* builds = &builder->funcs; - T1_Hinter_Funcs* hints = &decoder->hinter; - - static const T1_Int args_count[ op_max ] = - { - 0, /* none */ - 0, /* endchar */ - 2, /* hsbw */ - 5, /* seac */ - 4, /* sbw */ - 0, /* closepath */ - 1, /* hlineto */ - 1, /* hmoveto */ - 4, /* hvcurveto */ - 2, /* rlineto */ - 2, /* rmoveto */ - 6, /* rrcurveto */ - 4, /* vhcurveto */ - 1, /* vlineto */ - 1, /* vmoveto */ - 0, /* dotsection */ - 2, /* hstem */ - 6, /* hstem3 */ - 2, /* vstem */ - 6, /* vstem3 */ - 2, /* div */ - -1, /* callothersubr */ - 1, /* callsubr */ - 0, /* pop */ - 0, /* return */ - 2 /* setcurrentpoint */ - }; + FT_Outline* outline; + T1_Pos x, y; /* First of all, initialise the decoder */ decoder->top = decoder->stack; @@ -454,38 +496,226 @@ limit = zone->limit = charstring_base + charstring_len; ip = zone->cursor = zone->base; - error = T1_Err_Ok; + error = T1_Err_Ok; + outline = &builder->current; + + x = builder->pos_x; + y = builder->pos_y; /* now, execute loop */ while ( ip < limit ) { T1_Int* top = decoder->top; - T1_Operator op = op_none; - T1_Long value = 0; /* First of all, decompress operator or value */ switch (*ip++) { - case 1: op = op_hstem; break; + case 1: /* hstem */ + case 3: /* vstem */ + { + Clear_Stack: + top = decoder->stack; + break; + } + + case 4: /* vmoveto */ + { + USE_ARGS(1); + y += top[0]; + builder->path_begun = 1; + goto Clear_Stack; + } + + case 5: /* rlineto */ + { + if ( start_point( builder, x, y ) ) goto Memory_Error; + + USE_ARGS(2); + x += top[0]; + y += top[1]; + Add_Line: + if (add_point1( builder, top[0], top[1] )) goto Memory_Error; + goto Clear_Stack; + } + + case 6: /* hlineto */ + { + if ( start_point( builder, x, y ) ) goto Memory_Error; + + USE_ARGS(1); + x += top[0]; + goto Add_Line; + } + + case 7: /* vlineto */ + { + if ( start_point( builder, x, y ) ) goto Memory_Error; + + USE_ARGS(1); + y += top[0]; + goto Add_Line; + } + + case 8: /* rrcurveto */ + { + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) goto Memory_Error; + + USE_ARGS(6); + x += top[0]; + y += top[1]; + add_point( builder, x, y, 0 ); + + x += top[2]; + y += top[3]; + add_point( builder, x, y, 0 ); + + x += top[4]; + y += top[5]; + add_point( builder, x, y, 1 ); + goto Clear_Stack; + } + + case 9: /* closepath */ + { + close_contour( builder ); + builder->path_begun = 0; + } + break; + + case 10: /* callsubr */ + { + T1_Int index; + + USE_ARGS(1); + + index = top[0]; + if ( index < 0 || index >= num_subrs ) + { + FT_ERROR(( "T1.Parse_CharStrings : invalid subrs index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "T1.Parse_CharStrings : too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ - case 3: op = op_vstem; break; - case 4: op = op_vmoveto; break; - case 5: op = op_rlineto; break; - case 6: op = op_hlineto; break; - case 7: op = op_vlineto; break; - case 8: op = op_rrcurveto; break; - case 9: op = op_closepath; break; - case 10: op = op_callsubr; break; - case 11: op = op_return; break; + zone++; + zone->base = subrs_base[index]; + zone->limit = zone->base + subrs_len[index]; + zone->cursor = zone->base; + + if (!zone->base) + { + FT_ERROR(( "T1.Parse_CharStrings : invoking empty subrs !!\n" )); + goto Syntax_Error; + } - case 13: op = op_hsbw; break; - case 14: op = op_endchar; break; + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + + /* do not clear stack */ + } + break; + + case 11: /* return */ + { + if ( zone <= decoder->zones ) + { + FT_ERROR(( "T1.Parse_CharStrings : unexpected return\n" )); + goto Syntax_Error; + } - case 21: op = op_rmoveto; break; - case 22: op = op_hmoveto; break; + zone--; + ip = zone->cursor; + limit = zone->limit; + decoder->zone = zone; + } + break; + + case 13: /* hsbw */ + { + USE_ARGS(2); + builder->left_bearing.x += top[0]; + builder->advance.x = top[1]; + builder->advance.y = 0; + + builder->last.x = x = top[0]; + builder->last.y = y = 0; + + /* the "metrics_only" indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it.. so exit immediately */ + if (builder->metrics_only) + return T1_Err_Ok; + + goto Clear_Stack; + } - case 30: op = op_vhcurveto; break; - case 31: op = op_hvcurveto; break; + case 14: /* endchar */ + { + close_contour( builder ); + + /* add current outline to the glyph slot */ + builder->base.n_points += builder->current.n_points; + builder->base.n_contours += builder->current.n_contours; + + /* return now !! */ + return T1_Err_Ok; + } + + case 21: /* rmoveto */ + { + USE_ARGS(2); + x += top[0]; + y += top[1]; + goto Clear_Stack; + } + + case 22: /* hmoveto */ + { + USE_ARGS(1); + x += top[0]; + goto Clear_Stack; + } + + case 30: /* vhcurveto */ + { + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) goto Memory_Error; + + USE_ARGS(4); + y += top[0]; + add_point( builder, x, y, 0 ); + x += top[1]; + y += top[2]; + add_point( builder, x, y, 0 ); + x += top[3]; + add_point( builder, x, y, 1 ); + goto Clear_Stack; + } + + case 31: /* hvcurveto */ + { + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) goto Memory_Error; + + USE_ARGS(4); + x += top[0]; + add_point( builder, x, y, 0 ); + x += top[1]; + y += top[2]; + add_point( builder, x, y, 0 ); + y += top[3]; + add_point( builder, x, y, 1 ); + goto Clear_Stack; + } + case 12: { @@ -497,15 +727,145 @@ switch (*ip++) { - case 0: op = op_dotsection; break; - case 1: op = op_vstem3; break; - case 2: op = op_hstem3; break; - case 6: op = op_seac; break; - case 7: op = op_sbw; break; - case 12: op = op_div; break; - case 16: op = op_callothersubr; break; - case 17: op = op_pop; break; - case 33: op = op_setcurrentpoint; break; + case 0: /* dotsection */ + case 1: /* vstem3 */ + case 2: /* hstem3 */ + goto Clear_Stack; + + case 6: /* seac */ + { + USE_ARGS(5); + + /* return immediately to implement an accented character */ + return t1operator_seac( decoder, + top[0], top[1], top[3], + top[4], top[5] ); + } + + case 7: /* sbw */ + { + USE_ARGS(4); + builder->left_bearing.x += top[0]; + builder->left_bearing.y += top[1]; + builder->advance.x = top[2]; + builder->advance.y = top[3]; + + builder->last.x = x = top[0]; + builder->last.y = y = top[1]; + + /* the "metrics_only" indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it.. so exit immediately */ + if (builder->metrics_only) + return T1_Err_Ok; + + goto Clear_Stack; + } + + case 12: /* div */ + { + USE_ARGS(2); + top[0] /= top[1]; + top++; + } + break; + + case 16: /* callothersubr */ + { + USE_ARGS(1); + switch (top[0]) + { + case 1: /* start flex feature ---------------------- */ + { + decoder->flex_state = 1; + decoder->num_flex_vectors = 0; + if ( start_point(builder, x, y) || + check_points(builder,6) ) goto Memory_Error; + } + break; + + case 2: /* add flex vectors ------------------------ */ + { + T1_Int index; + + /* note that we should not add a point for index 0 */ + /* this will move our current position to the flex */ + /* point without adding any point to the outline */ + index = decoder->num_flex_vectors++; + if (index > 0 && index < 7) + add_point( builder, + x, + y, + (T1_Byte)( index==3 || index==6 ) ); + } + break; + + case 0: /* end flex feature ------------------------- */ + { + USE_ARGS(3); /* ignore parameters */ + + if ( decoder->flex_state == 0 || + decoder->num_flex_vectors != 7 ) + { + FT_ERROR(( "T1.Parse_CharStrings: unexpected flex end\n" )); + goto Syntax_Error; + } + + /* now consume the remaining "pop pop setcurpoint" */ + if ( ip+6 > limit || + ip[0] != 12 || ip[1] != 17 || /* pop */ + ip[2] != 12 || ip[3] != 17 || /* pop */ + ip[4] != 12 || ip[5] != 33 ) /* setcurpoint */ + { + FT_ERROR(( "T1.Parse_CharStrings: invalid flex charstring\n" )); + goto Syntax_Error; + } + + ip += 6; + decoder->flex_state = 0; + decoder->top = top; + + goto Clear_Stack; + } + + case 3: /* change hints ---------------------------- */ + { + /* eat the following "pop" */ + if (ip+2 > limit) + { + FT_ERROR(( "T1.Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + if (ip[0] != 12 || ip[1] != 17) + { + FT_ERROR(( "T1.Parse_CharStrings: 'pop' expected, found (%d %d)\n", + ip[0], ip[1] )); + goto Syntax_Error; + } + ip += 2; + goto Clear_Stack; + } + + default: + FT_ERROR(( "T1.Parse_CharStrings: invalid othersubr %d !!\n", + top[0] )); + goto Syntax_Error; + } + } + + case 17: /* pop - should not happen !! */ + { + FT_ERROR(( "T1.Parse_CharStrings : 'pop' should not happen !!\n" )); + goto Syntax_Error; + } + + case 33: /* setcurrentpoint */ + { + FT_ERROR(( "T1.Parse_CharStrings : 'setcurrentpoint' should not happen !!\n" )); + goto Syntax_Error; + } default: FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+%d)\n", @@ -513,7 +873,7 @@ goto Syntax_Error; } } - break; + break; /* escape - 12 */ case 255: /* four bytes integer */ { @@ -523,556 +883,106 @@ goto Syntax_Error; } - value = ((long)ip[0] << 24) | - ((long)ip[1] << 16) | - ((long)ip[2] << 8) | - ip[3]; + *top++ = ((long)ip[0] << 24) | + ((long)ip[1] << 16) | + ((long)ip[2] << 8) | + ip[3]; ip += 4; } break; default: - if (ip[-1] >= 32) { - if (ip[-1] < 247) - value = (long)ip[-1] - 139; + T1_Long v, v2; + + v = ip[-1]; + if (v < 32) + { + FT_ERROR(( "T1.Parse_CharStrings : invalid byte (%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + /* compute value ---- */ + /* */ + if (v < 247) /* 1-byte value */ + v -= 139; else { - if (++ip > limit) + if (++ip > limit) /* 2-bytes value, check limits */ { FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" )); goto Syntax_Error; } - - if (ip[-2] < 251) - value = ((long)(ip[-2]-247) << 8) + ip[-1] + 108; + + v2 = ip[-1] + 108; + if (v < 251) + v = ((v-247) << 8) + v2; else - value = -((((long)ip[-2]-251) << 8) + ip[-1] + 108 ); + v = -(((v-251) << 8) + v2); } - } - else - { - FT_ERROR(( "T1.Parse_CharStrings : invalid byte (%d)\n", - ip[-1] )); - goto Syntax_Error; - } - } - - /* push value if needed */ - if ( op == op_none ) - { - if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) - { - FT_ERROR(( "T1.Parse_CharStrings : Stack overflow !!\n" )); - goto Syntax_Error; - } - - *top++ = value; - decoder->top = top; - } - - else if ( op == op_callothersubr ) /* check arguments differently */ - { - if ( top - decoder->stack < 2) - goto Stack_Underflow; - - top -= 2; - - switch (top[1]) - { - case 1: /* start flex feature ----------------------------- */ + + /* store value - is there enough room ?*/ + if ( top >= decoder->stack + T1_MAX_CHARSTRINGS_OPERANDS ) { - if (top[0] != 0) goto Unexpected_OtherSubr; - - decoder->flex_state = 1; - decoder->num_flex_vectors = 0; - decoder->flex_vectors[0].x = 0; - decoder->flex_vectors[0].y = 0; + FT_ERROR(( "T1.Parse_CharStrings : Stack overflow !!\n" )); + goto Syntax_Error; } - break; - - - case 2: /* add flex vector ------------------------------- */ - { - T1_Int index; - T1_Vector* flex; + + *top++ = v; + decoder->top = top; + } + } /* big switch */ + + } /* while ip < limit */ + return error; - if (top[0] != 0) goto Unexpected_OtherSubr; + Syntax_Error: + return T1_Err_Syntax_Error; - top -= 2; - if (top < decoder->stack) goto Stack_Underflow; + Stack_Underflow: + return T1_Err_Stack_Underflow; + + Memory_Error: + return builder->error; + } - index = decoder->num_flex_vectors++; - if (index >= 7) - { - FT_ERROR(( "T1.Parse_CharStrings: too many flex vectors !\n" )); - goto Syntax_Error; - } - flex = decoder->flex_vectors + index; - flex->x += top[0]; - flex->y += top[1]; - } - break; + /**********************************************************************/ + /**********************************************************************/ + /**********************************************************************/ + /********** *********/ + /********** *********/ + /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the maximum advance width of the font. It *********/ + /********** quickly process each glyph charstring to *********/ + /********** extract the value from either a "sbw" or "seac" *********/ + /********** operator. *********/ + /********** *********/ + /**********************************************************************/ + /**********************************************************************/ + /**********************************************************************/ + LOCAL_FUNC + T1_Error T1_Compute_Max_Advance( T1_Face face, + T1_Int *max_advance ) + { + T1_Error error; + T1_Decoder decoder; + T1_Int glyph_index; + T1_Font* type1 = &face->type1; - case 0: /* end flex feature ------------------------------ */ - { - if ( decoder->flex_state == 0 || - decoder->num_flex_vectors != 7 ) - { - FT_ERROR(( "T1.Parse_CharStrings: unexpected flex end\n" )); - goto Syntax_Error; - } + *max_advance = 0; - if (top[0] != 3) goto Unexpected_OtherSubr; + /* Initialise load decoder */ + T1_Init_Decoder( &decoder ); + T1_Init_Builder( &decoder.builder, face, 0, 0 ); - top -= 3; - if (top < decoder->stack) goto Stack_Underflow; - - /* now consume the remaining "pop pop setcurrentpoint" */ - if ( ip+6 > limit || - ip[0] != 12 || ip[1] != 17 || /* pop */ - ip[2] != 12 || ip[3] != 17 || /* pop */ - ip[4] != 12 || ip[5] != 33 ) /* setcurrentpoint */ - { - FT_ERROR(( "T1.Parse_CharStrings: invalid flex charstring\n" )); - goto Syntax_Error; - } - - decoder->flex_state = 0; - decoder->top = top; - - error = t1operator_flex( decoder, top[0], top[1], top[2] ); - } - break; - - - case 3: /* change hints ------------------------------------ */ - { - if (top[0] != 1) goto Unexpected_OtherSubr; - - /* eat the following "pop" */ - if (ip+2 > limit) - { - FT_ERROR(( "T1.Parse_CharStrings: invalid escape (12+%d)\n", - ip[-1] )); - goto Syntax_Error; - } - - if (ip[0] != 12 || ip[1] != 17) - { - FT_ERROR(( "T1.Parse_CharStrings: 'pop' expected, found (%d %d)\n", - ip[0], ip[1] )); - goto Syntax_Error; - } - - ip += 2; - error = hints->change_hints(builder); - } - break; - - - default: - /* invalid OtherSubrs call */ - Unexpected_OtherSubr: - FT_ERROR(( "T1.Parse_CharStrings: unexpected OtherSubrs [%d %d]\n", - top[0], top[1] )); - goto Syntax_Error; - } - decoder->top = top; - } - else - { - T1_Int num_args = args_count[op]; - - if ( top - decoder->stack < num_args ) - goto Stack_Underflow; - - top -= num_args; - - switch (op) - { - case op_endchar: - error = builds->end_char( builder ); - break; - - case op_hsbw: - error = builds->set_bearing_point( builder, top[0], 0, - top[1], 0 ); - break; - - case op_seac: - /* return immediately after the processing */ - return t1operator_seac( decoder, top[0], top[1], - top[2], top[3], top[4] ); - - case op_sbw: - error = builds->set_bearing_point( builder, top[0], top[1], - top[2], top[3] ); - break; - - case op_closepath: - error = builds->close_path( builder ); - break; - - case op_hlineto: - error = builds->rline_to( builder, top[0], 0 ); - break; - - case op_hmoveto: - error = builds->rmove_to( builder, top[0], 0 ); - break; - - case op_hvcurveto: - error = builds->rcurve_to( builder, top[0], 0, - top[1], top[2], - 0, top[3] ); - break; - - case op_rlineto: - error = builds->rline_to( builder, top[0], top[1] ); - break; - - case op_rmoveto: - /* ignore operator when in flex mode */ - if (decoder->flex_state == 0) - error = builds->rmove_to( builder, top[0], top[1] ); - else - top += 2; - break; - - case op_rrcurveto: - { - error = builds->rcurve_to( builder, top[0], top[1], - top[2], top[3], - top[4], top[5] ); - } - break; - - case op_vhcurveto: - error = builds->rcurve_to( builder, 0, top[0], - top[1], top[2], - top[3], 0 ); - break; - - case op_vlineto: - error = builds->rline_to( builder, 0, top[0] ); - break; - - case op_vmoveto: - error = builds->rmove_to( builder, 0, top[0] ); - break; - - case op_dotsection: - error = hints->dot_section( builder ); - break; - - case op_hstem: - error = hints->stem( builder, top[0], top[1], 0 ); - break; - - case op_hstem3: - error = hints->stem3( builder, top[0], top[1], top[2], - top[3], top[4], top[5], 0 ); - break; - - case op_vstem: - error = hints->stem( builder, top[0], top[1], 1 ); - break; - - case op_vstem3: - error = hints->stem3( builder, top[0], top[1], top[2], - top[3], top[4], top[5], 1 ); - break; - - case op_div: - if (top[1]) - *top++ = top[0] / top[1]; - else - { - FT_ERROR(( "T1.Parse_CHarStrings : division by 0\n" )); - goto Syntax_Error; - } - break; - - case op_callsubr: - { - T1_Int index = top[0]; - - if ( index < 0 || index >= num_subrs ) - { - FT_ERROR(( "T1.Parse_CharStrings : invalid subrs index\n" )); - goto Syntax_Error; - } - - if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) - { - FT_ERROR(( "T1.Parse_CharStrings : too many nested subrs\n" )); - goto Syntax_Error; - } - - zone->cursor = ip; /* save current instruction pointer */ - - zone++; - zone->base = subrs_base[index]; - zone->limit = zone->base + subrs_len[index]; - zone->cursor = zone->base; - - if (!zone->base) - { - FT_ERROR(( "T1.Parse_CharStrings : invoking empty subrs !!\n" )); - goto Syntax_Error; - } - - decoder->zone = zone; - ip = zone->base; - limit = zone->limit; - } - break; - - case op_pop: - FT_ERROR(( "T1.Parse_CharStrings : unexpected POP\n" )); - goto Syntax_Error; - - - case op_return: - if ( zone <= decoder->zones ) - { - FT_ERROR(( "T1.Parse_CharStrings : unexpected return\n" )); - goto Syntax_Error; - } - - zone--; - ip = zone->cursor; - limit = zone->limit; - decoder->zone = zone; - break; - - case op_setcurrentpoint: - FT_ERROR(( "T1.Parse_CharStrings : unexpected SETCURRENTPOINT\n" )); - goto Syntax_Error; - break; - - default: - FT_ERROR(( "T1.Parse_CharStrings : unhandled opcode %d\n", op )); - goto Syntax_Error; - } - - decoder->top = top; - } - } - - return error; - - Syntax_Error: - return T1_Err_Syntax_Error; - - Stack_Underflow: - return T1_Err_Stack_Underflow; - } - - - -/*************************************************************************/ -/* */ -/* T1_Add_Points */ -/* */ -/* */ -/* Checks that there is enough room in the current load glyph outline */ -/* to accept "num_points" additional outline points. If not, this */ -/* function grows the load outline's arrays accordingly.. */ -/* */ -/* */ -/* builder :: pointer to glyph builder object */ -/* num_points :: number of points that will be added later */ -/* */ -/* */ -/* Type1 error code. 0 means success */ -/* */ -/* */ -/* This function does NOT update the points count in the glyph builder*/ -/* This must be done by the caller itself, after this function is */ -/* invoked.. */ -/* */ - LOCAL_FUNC - T1_Error T1_Add_Points( T1_Builder* builder, - T1_Int num_points ) - { - T1_Int new_points; - - new_points = builder->base.n_points + - builder->current.n_points + - num_points; - - if ( new_points > builder->max_points ) - { - FT_Memory memory = builder->memory; - T1_Error error; - T1_Int increment = builder->current.points - builder->base.points; - T1_Int current = builder->max_points; - - while ( builder->max_points < new_points ) - builder->max_points += 16; - - if ( REALLOC_ARRAY( builder->base.points, - current, builder->max_points, T1_Vector ) || - - REALLOC_ARRAY( builder->base.flags, - current, builder->max_points, T1_Byte ) ) - return error; - - builder->current.points = builder->base.points + increment; - builder->current.flags = builder->base.flags + increment; - } - - return T1_Err_Ok; - } - -/*************************************************************************/ -/* */ -/* T1_Add_Contours */ -/* */ -/* */ -/* Checks that there is enough room in the current load glyph outline */ -/* to accept "num_contours" additional contours. If not, this func */ -/* the load outline's arrays accordingly.. */ -/* */ -/* */ -/* builder :: pointer to glyph builder object */ -/* num_contours :: number of contours that will be added later */ -/* */ -/* */ -/* Type1 error code. 0 means success */ -/* */ -/* */ -/* This function does NOT update the contours count in the load glyph */ -/* This must be done by the caller itself, after this function is */ -/* invoked.. */ -/* */ - LOCAL_FUNC - T1_Error T1_Add_Contours( T1_Builder* builder, - T1_Int num_contours ) - { - T1_Int new_contours; - - new_contours = builder->base.n_contours + - builder->current.n_contours + - num_contours; - - if ( new_contours > builder->max_contours && builder->load_points ) - { - T1_Error error; - FT_Memory memory = builder->memory; - T1_Int increment = builder->current.contours - builder->base.contours; - T1_Int current = builder->max_contours; - - while ( builder->max_contours < new_contours ) - builder->max_contours += 4; - - if ( REALLOC_ARRAY( builder->base.contours, - current, builder->max_contours, T1_Short ) ) - return error; - - builder->current.contours = builder->base.contours + increment; - } - - return T1_Err_Ok; - } - - - /**********************************************************************/ - /**********************************************************************/ - /**********************************************************************/ - /********** *********/ - /********** *********/ - /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ - /********** *********/ - /********** The following code is in charge of computing *********/ - /********** the maximum advance width of the font. It *********/ - /********** quickly process each glyph charstring to *********/ - /********** extract the value from either a "sbw" or "seac" *********/ - /********** operator. *********/ - /********** *********/ - /**********************************************************************/ - /**********************************************************************/ - /**********************************************************************/ - - - - static - T1_Error maxadv_sbw( T1_Decoder* decoder, - T1_Pos sbx, - T1_Pos sby, - T1_Pos wx, - T1_Pos wy ) - { - if (wx > decoder->builder.advance.x) - decoder->builder.advance.x = wx; - - (void)sbx; - (void)sby; - (void)wy; - return -1; /* return an error code to exit the Type 1 parser */ - /* immediately. */ - } - - - static - T1_Int maxadv_error( void ) - { - /* we should never reach this code, unless with a buggy font */ - return -2; - } - - /* the maxadv_gbuilder_interface is used when computing the maximum */ - /* advance width of all glyphs in a given font. We only process the */ - /* 'sbw' operator here, and return an error for all others.. */ - - /* Note that "seac" is processed by the T1_Decoder */ - static - const T1_Builder_Funcs maxadv_builder_interface = - { - (T1_Builder_EndChar) maxadv_error, - (T1_Builder_Sbw) maxadv_sbw, - (T1_Builder_ClosePath) maxadv_error, - (T1_Builder_RLineTo) maxadv_error, - (T1_Builder_RMoveTo) maxadv_error, - (T1_Builder_RCurveTo) maxadv_error - }; - - - /* the maxadv_interface is used when computing the maximum advance */ - /* with of the set of glyphs in a given font file. We only process */ - /* the "seac" operator and return immediately.. */ - static - const T1_Hinter_Funcs maxadv_hinter_interface = - { - (T1_Hinter_DotSection) maxadv_error, - (T1_Hinter_ChangeHints) maxadv_error, - (T1_Hinter_Stem) maxadv_error, - (T1_Hinter_Stem3) maxadv_error, - }; - - - - LOCAL_FUNC - T1_Error T1_Compute_Max_Advance( T1_Face face, - T1_Int *max_advance ) - { - T1_Error error; - T1_Decoder decoder; - T1_Int glyph_index; - T1_Font* type1 = &face->type1; - - *max_advance = 0; - - /* Initialise load decoder */ - T1_Init_Decoder( &decoder, &maxadv_hinter_interface ); - - T1_Init_Builder( &decoder.builder, face, 0, 0, - &maxadv_builder_interface ); + decoder.builder.metrics_only = 1; + decoder.builder.load_points = 0; /* For each glyph, parse the glyph charstring and extract */ /* the advance width.. */ @@ -1105,304 +1015,11 @@ /********** single outline. It completely ignores hinting *********/ /********** and is used when FT_LOAD_NO_HINTING is set. *********/ /********** *********/ - /********** The Type 1 hinter is located in "t1hint.c" *********/ - /********** *********/ /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ - - static - T1_Error close_open_path( T1_Builder* builder ) - { - T1_Error error; - FT_Outline* cur = &builder->current; - T1_Int num_points; - T1_Int first_point; - - /* Some fonts, like Hershey, are made of "open paths" which are */ - /* now managed directly by FreeType. In this case, it is necessary */ - /* to close the path by duplicating its points in reverse order, */ - /* which is precisely the purpose of this function */ - - /* first compute the number of points to duplicate.. */ - if (cur->n_contours > 1) - first_point = cur->contours[ cur->n_contours-2 ]+1; - else - first_point = 0; - - num_points = cur->n_points - first_point - 2; - if ( num_points > 0 ) - { - T1_Vector* source_point; - char* source_flags; - T1_Vector* point; - char* flags; - - error = T1_Add_Points( builder, num_points ); - if (error) return error; - - point = cur->points + cur->n_points; - flags = cur->flags + cur->n_points; - - source_point = point - 2; - source_flags = flags - 2; - - cur->n_points += num_points; - - if ( builder->load_points ) - do - { - *point++ = *source_point--; - *flags++ = *source_flags--; - num_points--; - } - while (num_points > 0); - } - - builder->path_begun = 0; - return T1_Err_Ok; - } - - - static - T1_Error gload_closepath( T1_Builder* builder ) - { - FT_Outline* cur = &builder->current; - - /* save current contour, if any */ - if ( cur->n_contours > 0 ) - cur->contours[cur->n_contours-1] = cur->n_points-1; - -#ifndef T1_CONFIG_OPTION_DISABLE_HINTER - /* hint latest points if needed - this is not strictly required */ - /* there, but it helps for debugging, and doesn't affect performance */ - if ( builder->pass == 1 ) - T1_Hint_Points( builder ); -#endif - - builder->path_begun = 0; - return T1_Err_Ok; - } - - - - static - T1_Error gload_endchar( T1_Builder* builder ) - { - FT_Outline* cur = &builder->current; - T1_Error error; - - /* close path if needed */ - if (builder->path_begun) - { - error = close_open_path( builder ); - if (error) return error; - } - - error = gload_closepath( builder ); - - builder->base.n_points += cur->n_points; - builder->base.n_contours += cur->n_contours; - - return error; - } - - - - static - T1_Error gload_sbw( T1_Builder* builder, - T1_Pos sbx, - T1_Pos sby, - T1_Pos wx, - T1_Pos wy ) - { - builder->left_bearing.x += sbx; - builder->left_bearing.y += sby; - builder->advance.x = wx; - builder->advance.y = wy; - - builder->last.x = sbx; - builder->last.y = sby; - return 0; - } - - - - - static - T1_Error gload_rlineto( T1_Builder* builder, - T1_Pos dx, - T1_Pos dy ) - { - T1_Error error; - FT_Outline* cur = &builder->current; - T1_Vector vec; - - /* grow buffer if necessary */ - error = T1_Add_Points ( builder, 1 ); - if (error) return error; - - if ( builder->load_points ) - { - /* save point */ - vec.x = builder->last.x + dx; - vec.y = builder->last.y + dy; - - cur->points[cur->n_points] = vec; - cur->flags [cur->n_points] = FT_Curve_Tag_On; - - builder->last = vec; - } - cur->n_points++; - - builder->path_begun = 1; - return T1_Err_Ok; - } - - - static - T1_Error gload_rmoveto( T1_Builder* builder, - T1_Pos dx, - T1_Pos dy ) - { - T1_Error error; - FT_Outline* cur = &builder->current; - T1_Vector vec; - - /* in the case where "path_begun" is set, we have a rmoveto */ - /* after some normal path definition. When the face's paint */ - /* type is set to 1, this means that we have an "open path", */ - /* also called a 'stroke'. The FreeType raster doesn't support */ - /* opened path, so we'll close it explicitely there.. */ - if ( builder->path_begun && builder->face->type1.paint_type == 1 ) - { - if ( builder->face->type1.paint_type == 1 ) - { - error = close_open_path( builder ); - if (error) return error; - } - } - - /* grow buffer if necessary */ - error = T1_Add_Contours( builder, 1 ) || - T1_Add_Points ( builder, 1 ); - if (error) return error; - - /* save current contour, if any */ - if ( cur->n_contours > 0 ) - cur->contours[cur->n_contours-1] = cur->n_points-1; - - if ( builder->load_points ) - { - /* save point */ - vec.x = builder->last.x + dx; - vec.y = builder->last.y + dy; - cur->points[cur->n_points] = vec; - cur->flags [cur->n_points] = FT_Curve_Tag_On; - - builder->last = vec; - } - - cur->n_contours++; - cur->n_points++; - - return T1_Err_Ok; - } - - - static - T1_Error gload_rrcurveto( T1_Builder* builder, - T1_Pos dx1, - T1_Pos dy1, - T1_Pos dx2, - T1_Pos dy2, - T1_Pos dx3, - T1_Pos dy3 ) - { - T1_Error error; - FT_Outline* cur = &builder->current; - T1_Vector vec; - T1_Vector* points; - char* flags; - - /* grow buffer if necessary */ - error = T1_Add_Points ( builder, 3 ); - if (error) return error; - - if ( builder->load_points ) - { - /* save point */ - points = cur->points + cur->n_points; - flags = cur->flags + cur->n_points; - - vec.x = builder->last.x + dx1; - vec.y = builder->last.y + dy1; - points[0] = vec; flags[0] = FT_Curve_Tag_Cubic; - - vec.x += dx2; - vec.y += dy2; - points[1] = vec; flags[1] = FT_Curve_Tag_Cubic; - - vec.x += dx3; - vec.y += dy3; - points[2] = vec; flags[2] = FT_Curve_Tag_On; - - builder->last = vec; - } - - cur->n_points += 3; - builder->path_begun = 1; - return T1_Err_Ok; - } - - - - - static - T1_Error gload_ignore( void ) - { - return 0; - } - - - static - const T1_Builder_Funcs gload_builder_interface = - { - gload_endchar, - gload_sbw, - gload_closepath, - gload_rlineto, - gload_rmoveto, - gload_rrcurveto - }; - - - static - const T1_Builder_Funcs gload_builder_interface_null = - { - (T1_Builder_EndChar) gload_ignore, - (T1_Builder_Sbw) gload_sbw, /* record left bearing */ - (T1_Builder_ClosePath) gload_ignore, - (T1_Builder_RLineTo) gload_ignore, - (T1_Builder_RMoveTo) gload_ignore, - (T1_Builder_RCurveTo) gload_ignore - }; - - - static - const T1_Hinter_Funcs gload_hinter_interface = - { - (T1_Hinter_DotSection) gload_ignore, /* dotsection */ - (T1_Hinter_ChangeHints) gload_ignore, /* changehints */ - (T1_Hinter_Stem) gload_ignore, /* hstem & vstem */ - (T1_Hinter_Stem3) gload_ignore, /* hstem3 & vestem3 */ - }; - - - - LOCAL_FUNC T1_Error T1_Load_Glyph( T1_GlyphSlot glyph, T1_Size size, @@ -1426,66 +1043,9 @@ glyph->root.format = ft_glyph_format_none; -#ifndef T1_CONFIG_OPTION_DISABLE_HINTER - /*****************************************************************/ - /* */ - /* Hinter overview : */ - /* */ - /* This is a two-pass hinter. On the first pass, the hints */ - /* are all recorded by the hinter, and no point is loaded */ - /* in the outline. */ - /* */ - /* When the first pass is finished, all stems hints are */ - /* grid-fitted at once. */ - /* */ - /* Then, a second pass is performed to load the outline */ - /* points as well as hint/scale them correctly. */ - /* */ - - if ( hinting ) { - /* Pass 1 - don't record points, simply stem hints */ - T1_Init_Decoder( &decoder, &t1_hinter_funcs ); - T1_Init_Builder( &decoder.builder, face, size, glyph, - &gload_builder_interface_null ); - - glyph->hints->hori_stems.num_stems = 0; - glyph->hints->vert_stems.num_stems = 0; - - error = T1_Parse_CharStrings( &decoder, - type1->charstrings [glyph_index], - type1->charstrings_len[glyph_index], - type1->num_subrs, - type1->subrs, - type1->subrs_len ); - - /* All right, pass 1 is finished, now grid-fit all stem hints */ - T1_Hint_Stems( &decoder.builder ); - - /* Pass 2 - record and scale/hint the points */ - T1_Init_Decoder( &decoder, &t1_hinter_funcs ); - T1_Init_Builder( &decoder.builder, face, size, glyph, - &gload_builder_interface ); - - decoder.builder.pass = 1; - - error = T1_Parse_CharStrings( &decoder, - type1->charstrings [glyph_index], - type1->charstrings_len[glyph_index], - type1->num_subrs, - type1->subrs, - type1->subrs_len ); - - /* save new glyph tables */ - T1_Done_Builder( &decoder.builder ); - } - else -#endif - { - T1_Init_Decoder( &decoder, &gload_hinter_interface ); - - T1_Init_Builder( &decoder.builder, face, size, glyph, - &gload_builder_interface ); + T1_Init_Decoder( &decoder ); + T1_Init_Builder( &decoder.builder, face, size, glyph ); /* now load the unscaled outline */ error = T1_Parse_CharStrings( &decoder, @@ -1499,7 +1059,6 @@ T1_Done_Builder( &decoder.builder ); } - /* Now, set the metrics.. - this is rather simple, as : */ /* the left side bearing is the xMin, and the top side */ /* bearing the yMax.. */ @@ -1539,14 +1098,7 @@ glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 ); glyph->root.outline.dropout_mode = 2; - if ( hinting ) - { - /* adjust the advance width */ - /* XXX : TODO : consider stem hints grid-fit */ - metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, - glyph->x_scale ); - } - else if ( (load_flags & FT_LOAD_NO_SCALE) == 0 ) + if ( (load_flags & FT_LOAD_NO_SCALE) == 0 ) { /* scale the outline and the metrics */ T1_Int n; @@ -1573,10 +1125,8 @@ metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale ); - } } - return error; } diff --git a/src/type1z/t1gload.h b/src/type1z/t1gload.h index f635b8197..d880c8ad0 100644 --- a/src/type1z/t1gload.h +++ b/src/type1z/t1gload.h @@ -42,57 +42,6 @@ #endif -/*************************************************************************/ -/* */ -/* T1_Builder_Funcs */ -/* */ -/* */ -/* a structure used to store the address of various functions */ -/* used by a glyph builder to implement the outline's "path */ -/* construction". */ -/* */ -/* */ - typedef struct T1_Builder_ T1_Builder; - - typedef T1_Error (*T1_Builder_EndChar)( T1_Builder* loader ); - - typedef T1_Error (*T1_Builder_Sbw) ( T1_Builder* loader, - T1_Pos sbx, - T1_Pos sby, - T1_Pos wx, - T1_Pos wy ); - - typedef T1_Error (*T1_Builder_ClosePath)( T1_Builder* loader ); - - typedef T1_Error (*T1_Builder_RLineTo)( T1_Builder* loader, - T1_Pos dx, - T1_Pos dy ); - - typedef T1_Error (*T1_Builder_RMoveTo)( T1_Builder* loader, - T1_Pos dx, - T1_Pos dy ); - - typedef T1_Error (*T1_Builder_RCurveTo)( T1_Builder* loader, - T1_Pos dx1, - T1_Pos dy1, - T1_Pos dx2, - T1_Pos dy2, - T1_Pos dx3, - T1_Pos dy3 ); - - typedef struct T1_Builder_Funcs_ - { - T1_Builder_EndChar end_char; - T1_Builder_Sbw set_bearing_point; - T1_Builder_ClosePath close_path; - T1_Builder_RLineTo rline_to; - T1_Builder_RMoveTo rmove_to; - T1_Builder_RCurveTo rcurve_to; - - } T1_Builder_Funcs; - - - /*************************************************************************/ /* */ /* T1_Builder */ @@ -103,7 +52,6 @@ /* */ /* system :: current system object */ /* face :: current face object */ -/* size :: current size object */ /* glyph :: current glyph slot */ /* */ /* current :: current glyph outline */ @@ -125,22 +73,18 @@ /* path_begun :: flag, indicates that a new path has begun */ /* load_points :: flag, if not set, no points are loaded */ /* */ -/* pass :: pass number for multi-pass hinters */ -/* */ -/* funcs :: table of builder functions used to perform */ -/* the outline's path construction */ -/* */ -/* hint_point :: index of next point to hint.. */ -/* */ -/* */ +/* error :: an error code that is only used to report */ +/* memory allocation problems.. */ /* */ +/* metrics_only :: a boolean indicating that we only want to */ +/* compute the metrics of a given glyph, not load */ +/* all of its points.. */ /* */ - struct T1_Builder_ + typedef struct T1_Builder_ { FT_Memory memory; T1_Face face; - T1_Size size; T1_GlyphSlot glyph; FT_Outline current; /* the current glyph outline */ @@ -163,88 +107,11 @@ T1_BBox bbox; /* bounding box */ T1_Bool path_begun; T1_Bool load_points; - - T1_Int pass; - T1_Int hint_point; - - /* path construction function interface */ - T1_Builder_Funcs funcs; - }; - - -/*************************************************************************/ -/* */ -/* T1_Hinter_Funcs */ -/* */ -/* */ -/* a structure used to store the address of various functions */ -/* used by a Type 1 hinter to perform outline hinting. */ -/* */ - - typedef T1_Error (*T1_Hinter_ChangeHints)( T1_Builder* builder ); - - typedef T1_Error (*T1_Hinter_DotSection)( T1_Builder* builder ); - - typedef T1_Error (*T1_Hinter_Stem)( T1_Builder* builder, - T1_Pos pos, - T1_Pos width, - T1_Bool vertical ); - - - typedef T1_Error (*T1_Hinter_Stem3)( T1_Builder* builder, - T1_Pos pos0, - T1_Pos width0, - T1_Pos pos1, - T1_Pos width1, - T1_Pos pos2, - T1_Pos width2, - T1_Bool vertical ); - - typedef struct T1_Hinter_Func_ - { - T1_Hinter_ChangeHints change_hints; - T1_Hinter_DotSection dot_section; - T1_Hinter_Stem stem; - T1_Hinter_Stem3 stem3; - - } T1_Hinter_Funcs; - - - - typedef enum T1_Operator_ - { - op_none = 0, - op_endchar, - op_hsbw, - op_seac, - op_sbw, - op_closepath, - op_hlineto, - op_hmoveto, - op_hvcurveto, - op_rlineto, - op_rmoveto, - op_rrcurveto, - op_vhcurveto, - op_vlineto, - op_vmoveto, - op_dotsection, - op_hstem, - op_hstem3, - op_vstem, - op_vstem3, - op_div, - op_callothersubr, - op_callsubr, - op_pop, - op_return, - op_setcurrentpoint, - - op_max /* never remove this one */ - - } T1_Operator; - - + + T1_Error error; /* only used for memory errors */ + T1_Bool metrics_only; + + } T1_Builder; /* execution context charstring zone */ @@ -260,7 +127,6 @@ typedef struct T1_Decoder_ { T1_Builder builder; - T1_Hinter_Funcs hinter; T1_Int stack[ T1_MAX_CHARSTRINGS_OPERANDS ]; T1_Int* top; @@ -276,82 +142,18 @@ -/********************************************************************* - * - * - * T1_Init_Builder - * - * - * Initialise a given glyph builder. - * - * - * builder :: glyph builder to initialise - * face :: current face object - * size :: current size object - * glyph :: current glyph object - * funcs :: glyph builder functions (or "methods"). - * - * - * This function is exported for now because it is used by the - * "t1dump" utility. Later, it will be accessed through a - * format-specific extension - * - *********************************************************************/ - - EXPORT_DEF + LOCAL_DEF void T1_Init_Builder( T1_Builder* builder, T1_Face face, T1_Size size, - T1_GlyphSlot glyph, - const T1_Builder_Funcs* funcs ); + T1_GlyphSlot glyph ); -/********************************************************************* - * - * - * T1_Done_Builder - * - * - * Finalise a given glyph builder. Its content can still be - * used after the call, but the function saves important information - * within the corresponding glyph slot. - * - * - * builder :: glyph builder to initialise - * - * - * This function is exported for now because it is used by the - * "t1dump" utility. Later, it will be accessed through a - * format-specific extension - * - *********************************************************************/ - - EXPORT_DEF + LOCAL_DEF void T1_Done_Builder( T1_Builder* builder ); -/********************************************************************* - * - * - * T1_Init_Decoder - * - * - * Initialise a given Type 1 decoder for parsing - * - * - * decoder :: Type 1 decoder to initialise - * funcs :: hinter functions interface - * - * - * This function is exported for now because it is used by the - * "t1dump" utility. Later, it will be accessed through a - * format-specific extension - * - *********************************************************************/ - - EXPORT_DEF - void T1_Init_Decoder( T1_Decoder* decoder, - const T1_Hinter_Funcs* funcs ); - + LOCAL_DEF + void T1_Init_Decoder( T1_Decoder* decoder ); /* Compute the maximum advance width of a font through quick parsing */ diff --git a/src/type1z/t1load.c b/src/type1z/t1load.c index 4acec0720..2bf4ec435 100644 --- a/src/type1z/t1load.c +++ b/src/type1z/t1load.c @@ -92,13 +92,19 @@ FACE.##x = T1_ToString(&loader->parser); \ FT_TRACE2(( "type1.parse_##x##: \"%s\"\n", FACE.##x )); \ } - + +#define PARSE_NUM(s,x,t) PARSE_(x) \ + { \ + FACE.##x = (t)T1_ToInt(&loader->parser); \ + FT_TRACE2(( "type1.parse_##x##: \"%d\"\n", FACE.##x )); \ + } + #define PARSE_INT(s,x) PARSE_(x) \ { \ FACE.##x = T1_ToInt(&loader->parser); \ FT_TRACE2(( "type1.parse_##x##: \"%d\"\n", FACE.##x )); \ } - + #define PARSE_BOOL(s,x) PARSE_(x) \ { \ FACE.##x = T1_ToBool(&loader->parser); \ @@ -381,10 +387,12 @@ /* "ExpertEncoding" */ else { - if ( cur+17 < limit && strncmp( cur, "StandardEncoding", 16 ) == 0 ) + if ( cur+17 < limit && + strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) face->type1.encoding_type = t1_encoding_standard; - else if (cur+15 < limit && strncmp( cur, "ExpertEncoding", 14 ) == 0 ) + else if ( cur+15 < limit && + strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) face->type1.encoding_type = t1_encoding_expert; else @@ -515,6 +523,7 @@ #undef PARSE_STRING #undef PARSE_INT +#undef PARSE_NUM #undef PARSE_BOOL #undef PARSE_FIXED #undef PARSE_COORDS @@ -527,6 +536,7 @@ #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) @@ -589,7 +599,8 @@ name = (T1_Byte*)keyword->name; if (!name) break; - if (cur[0] == name[0] && len == strlen(name) ) + if ( cur[0] == name[0] && + len == (T1_Int)strlen((const char*)name) ) { T1_Int n; for ( n = 1; n < len; n++ ) @@ -718,11 +729,12 @@ if (char_name) for ( index = 0; index < type1->num_glyphs; index++ ) { - glyph_name = type1->glyph_names[index]; - if ( strcmp( char_name, glyph_name ) == 0 ) + glyph_name = (T1_Byte*)type1->glyph_names[index]; + if ( strcmp( (const char*)char_name, + (const char*)glyph_name ) == 0 ) { type1->encoding.char_index[charcode] = index; - type1->encoding.char_name [charcode] = glyph_name; + type1->encoding.char_name [charcode] = (char*)glyph_name; if (charcode < min_char) min_char = charcode; if (charcode > max_char) max_char = charcode; diff --git a/src/type1z/t1objs.c b/src/type1z/t1objs.c index 0d59b0f7c..f00e4caf7 100644 --- a/src/type1z/t1objs.c +++ b/src/type1z/t1objs.c @@ -21,10 +21,6 @@ #include #include -#ifndef T1_CONFIG_OPTION_DISABLE_HINTER -#include -#endif - /* Required by tracing mode */ #undef FT_COMPONENT #define FT_COMPONENT trace_t1objs @@ -55,13 +51,7 @@ LOCAL_FUNC void T1_Done_Size( T1_Size size ) { - if (size) - { -#ifndef T1_CONFIG_OPTION_DISABLE_HINTER - T1_Done_Size_Hinter( size ); -#endif - size->valid = 0; - } + (void)size; } @@ -88,13 +78,8 @@ size->valid = 0; -#ifndef T1_CONFIG_OPTION_DISABLE_HINTER - error = T1_New_Size_Hinter( size ); - return error; -#else (void)error; return T1_Err_Ok; -#endif } @@ -118,12 +103,8 @@ LOCAL_FUNC T1_Error T1_Reset_Size( T1_Size size ) { -#ifndef T1_CONFIG_OPTION_DISABLE_HINTER - return T1_Reset_Size_Hinter( size ); -#else (void)size; return 0; -#endif } @@ -312,9 +293,6 @@ FT_Memory memory = glyph->root.face->memory; FT_Library library = glyph->root.face->driver->library; -#ifndef T1_CONFIG_OPTION_DISABLE_HINTER - T1_Done_Glyph_Hinter( glyph ); -#endif /* the bitmaps are created on demand */ FREE( glyph->root.bitmap.buffer ); FT_Done_Outline( library, &glyph->root.outline ); @@ -339,22 +317,12 @@ T1_Error T1_Init_GlyphSlot( T1_GlyphSlot glyph ) { FT_Library library = glyph->root.face->driver->library; - T1_Error error; glyph->max_points = 0; glyph->max_contours = 0; glyph->root.bitmap.buffer = 0; - error = FT_New_Outline( library, 0, 0, &glyph->root.outline ); - if (error) return error; - -#ifndef T1_CONFIG_OPTION_DISABLE_HINTER - error = T1_New_Glyph_Hinter( glyph ); - if (error) - FT_Done_Outline( library, &glyph->root.outline ); -#endif - - return error; + return FT_New_Outline( library, 0, 0, &glyph->root.outline ); } diff --git a/src/type1z/t1tokens.h b/src/type1z/t1tokens.h index 4f251ed5f..94de2e27e 100644 --- a/src/type1z/t1tokens.h +++ b/src/type1z/t1tokens.h @@ -30,8 +30,8 @@ PARSE_INT("ItalicAngle",italic_angle) PARSE_BOOL("isFixedPitch",is_fixed_pitch) - PARSE_INT("UnderlinePosition",underline_position) - PARSE_INT("UnderlineThickness",underline_thickness) + PARSE_NUM("UnderlinePosition",underline_position,T1_Short) + PARSE_NUM("UnderlineThickness",underline_thickness,T1_UShort) /* define the private dict parsing callbacks */ @@ -62,8 +62,8 @@ /* define the top-level dictionary parsing callbacks */ /* PARSE_STRING( "FontName", font_name ) -- handled by special routine */ - PARSE_INT( "PaintType", paint_type ) - PARSE_INT( "FontType", font_type ) + PARSE_NUM( "PaintType", paint_type, T1_Byte ) + PARSE_NUM( "FontType", font_type, T1_Byte ) PARSE_FIXEDS2( "FontMatrix", 4, font_matrix ) /* PARSE_COORDS2( "FontBBox", 4, font_bbox ) -- handled by special func */ PARSE_INT( "StrokeWidth", stroke_width ) diff --git a/src/type1z/type1z.c b/src/type1z/type1z.c index f2d28009b..5000a8aee 100644 --- a/src/type1z/type1z.c +++ b/src/type1z/type1z.c @@ -33,9 +33,6 @@ #include #include #include -/* -#include #include #include -*/