ref: 0f991b4312c1662a82fed697bb14d5f1bfcb69c6
parent: e1d5dd78f4a75697a2584deac4af71dd21939f6a
author: David Turner <[email protected]>
date: Wed Jun 7 16:04:34 EDT 2000
new version of the CFF driver, this one works :-)
--- a/include/freetype/internal/t2types.h
+++ b/include/freetype/internal/t2types.h
@@ -167,6 +167,11 @@
CFF_Top_Dict top_dict;
CFF_Private private_dict;
+ FT_UInt num_global_subrs;
+ FT_UInt num_local_subrs;
+ FT_Byte** global_subrs;
+ FT_Byte** local_subrs;
+
} CFF_Font;
#ifdef __cplusplus
--- a/src/cff/cff.c
+++ b/src/cff/cff.c
@@ -45,5 +45,6 @@
#include <t2parse.c> /* token parser */
#include <t2load.c> /* tables loader */
#include <t2objs.c> /* object management */
+#include <t2gload.c> /* glyph loader */
/* END */
--- a/src/cff/t2driver.c
+++ b/src/cff/t2driver.c
@@ -288,19 +288,15 @@
if ( size )
{
/* these two object must have the same parent */
- if ( size->face != slot->face )
+ if ( size->face != slot->root.face )
return FT_Err_Invalid_Face_Handle;
}
/* now load the glyph outline if necessary */
-#if 1 /* XXXX: TODO */
- error = FT_Err_Unimplemented_Feature;
-#else
- error = T2_Load_Glyph( size, slot, glyph_index, load_flags );
-#endif
+ error = T2_Load_Glyph( slot, size, glyph_index, load_flags );
+
/* force drop-out mode to 2 - irrelevant now */
/* slot->outline.dropout_mode = 2; */
-
return error;
}
@@ -382,7 +378,7 @@
sizeof ( T2_DriverRec ),
sizeof ( TT_FaceRec ),
sizeof ( FT_SizeRec ),
- sizeof ( FT_GlyphSlotRec ),
+ sizeof ( T2_GlyphSlotRec ),
"cff", /* driver name */
100, /* driver version == 1.0 */
--- a/src/cff/t2gload.c
+++ b/src/cff/t2gload.c
@@ -22,1156 +22,1562 @@
#include <freetype/internal/sfnt.h>
#include <freetype/tttags.h>
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1gload
#include <t2gload.h>
+ typedef enum T2_Operator_
+ {
+ t2_op_unknown = 0,
+ t2_op_rmoveto,
+ t2_op_hmoveto,
+ t2_op_vmoveto,
+ t2_op_rlineto,
+ t2_op_hlineto,
+ t2_op_vlineto,
+ t2_op_rrcurveto,
+ t2_op_hhcurveto,
+ t2_op_hvcurveto,
+ t2_op_rcurveline,
+ t2_op_rlinecurve,
+ t2_op_vhcurveto,
+ t2_op_vvcurveto,
+ t2_op_flex,
+ t2_op_hflex,
+ t2_op_hflex1,
+ t2_op_flex1,
+ t2_op_endchar,
+ t2_op_hstem,
+ t2_op_vstem,
+ t2_op_hstemhm,
+ t2_op_vstemhm,
+ t2_op_hintmask,
+ t2_op_cntrmask,
+ t2_op_abs,
+ t2_op_add,
+ t2_op_sub,
+ t2_op_div,
+ t2_op_neg,
+ t2_op_random,
+ t2_op_mul,
+ t2_op_sqrt,
+ t2_op_blend,
+ t2_op_drop,
+ t2_op_exch,
+ t2_op_index,
+ t2_op_roll,
+ t2_op_dup,
+ t2_op_put,
+ t2_op_get,
+ t2_op_store,
+ t2_op_load,
+ t2_op_and,
+ t2_op_or,
+ t2_op_not,
+ t2_op_eq,
+ t2_op_ifelse,
+ t2_op_callsubr,
+ t2_op_callgsubr,
+ t2_op_return,
+ /* do not remove */
+ t2_op_max
+
+ } T2_Operator;
+
+ #define T2_COUNT_CHECK_WIDTH 0x80
+ #define T2_COUNT_EXACT 0x40
+ #define T2_COUNT_CLEAR_STACK 0x20
+
+ static const FT_Byte t2_argument_counts[] =
+ {
+ 0, /* unknown */
+
+ 2 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, /* rmoveto */
+ 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT,
+ 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT,
+
+ 0 | T2_COUNT_CLEAR_STACK, /* rlineto */
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+
+ 0 | T2_COUNT_CLEAR_STACK, /* rrcurveto */
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+
+ 13, /* flex */
+ 7,
+ 9,
+ 11,
+
+ 0, /* enchar */
+
+ 2 | T2_COUNT_CHECK_WIDTH, /* hstem */
+ 2 | T2_COUNT_CHECK_WIDTH,
+ 2 | T2_COUNT_CHECK_WIDTH,
+ 2 | T2_COUNT_CHECK_WIDTH,
+
+ 0, /* hintmask */
+ 0, /* cntrmask */
+
+ 1, /* abs */
+ 2,
+ 2,
+ 2,
+ 1,
+ 0,
+ 2,
+ 1,
+
+ 1, /* blend */
+
+ 1, /* drop */
+ 2,
+ 1,
+ 2,
+ 1,
+
+ 2, /* put */
+ 1,
+ 4,
+ 3,
+
+ 2, /* and */
+ 2,
+ 1,
+ 2,
+ 4,
+
+ 1, /* callsubr */
+ 1,
+ 0
+ };
+
/* required for the tracing mode */
#undef FT_COMPONENT
#define FT_COMPONENT trace_ttgload
- /*************************************************************************/
- /* */
- /* Composite font flags. */
- /* */
-#define ARGS_ARE_WORDS 0x001
-#define ARGS_ARE_XY_VALUES 0x002
-#define ROUND_XY_TO_GRID 0x004
-#define WE_HAVE_A_SCALE 0x008
-/* reserved 0x010 */
-#define MORE_COMPONENTS 0x020
-#define WE_HAVE_AN_XY_SCALE 0x040
-#define WE_HAVE_A_2X2 0x080
-#define WE_HAVE_INSTR 0x100
-#define USE_MY_METRICS 0x200
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** GENERIC CHARSTRINGS PARSING *********/
+ /********** *********/
+ /********** *********/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+/*********************************************************************
+ *
+ * <Function>
+ * T2_Init_Builder
+ *
+ * <Description>
+ * Initialise a given glyph builder.
+ *
+ * <Input>
+ * builder :: glyph builder to initialise
+ * face :: current face object
+ * size :: current size object
+ * glyph :: current glyph object
+ *
+ *********************************************************************/
-
- /*************************************************************************/
- /* Returns the horizontal or vertical metrics in font units for a */
- /* given glyph. The metrics are the left side bearing (resp. top */
- /* side bearing) and advance width (resp. advance height). */
- /* */
- LOCAL_FUNC
- void T2_Get_Metrics( TT_HoriHeader* header,
- FT_UInt index,
- FT_Short* bearing,
- FT_UShort* advance )
+ static
+ void T2_Init_Builder( T2_Builder* builder,
+ TT_Face face,
+ T2_Size size,
+ T2_GlyphSlot glyph )
{
- TT_LongMetrics* longs_m;
- TT_UShort k = header->number_Of_HMetrics;
+ builder->path_begun = 0;
+ builder->load_points = 1;
+ builder->face = face;
+ builder->glyph = glyph;
+ builder->memory = face->root.memory;
- if ( index < k )
+ if (glyph)
{
- longs_m = (TT_LongMetrics*)header->long_metrics + index;
- *bearing = longs_m->bearing;
- *advance = longs_m->advance;
+ builder->base = glyph->root.outline;
+ builder->max_points = glyph->max_points;
+ builder->max_contours = glyph->max_contours;
}
- else
+
+ if (size)
{
- *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];
- *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;
+ builder->scale_x = size->metrics.x_scale;
+ builder->scale_y = size->metrics.y_scale;
}
- }
+ builder->pos_x = 0;
+ builder->pos_y = 0;
- /*************************************************************************/
- /* Returns the horizontal metrics in font units for a given glyph. */
- /* If `check' is true, take care of monospaced fonts by returning the */
- /* advance width maximum. */
- /* */
- static
- void Get_HMetrics( T2_Face face,
- FT_UInt index,
- FT_Bool check,
- FT_Short* lsb,
- FT_UShort* aw )
- {
- T2_Get_Metrics( &face->horizontal, index, lsb, aw );
+ builder->left_bearing.x = 0;
+ builder->left_bearing.y = 0;
+ builder->advance.x = 0;
+ builder->advance.y = 0;
- if ( check && face->postscript.isFixedPitch )
- *aw = face->horizontal.advance_Width_Max;
+ builder->base.n_points = 0;
+ builder->base.n_contours = 0;
+ builder->current = builder->base;
}
- /*************************************************************************/
- /* Returns the advance width table for a given pixel size if it is */
- /* found in the font's `hdmx' table (if any). */
- /* */
+/*********************************************************************
+ *
+ * <Function>
+ * T2_Done_Builder
+ *
+ * <Description>
+ * 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.
+ *
+ * <Input>
+ * builder :: glyph builder to initialise
+ *
+ *********************************************************************/
+
static
- FT_Byte* Get_Advance_Widths( T2_Face face,
- FT_UShort ppem )
+ void T2_Done_Builder( T2_Builder* builder )
{
- FT_UShort n;
+ T2_GlyphSlot glyph = builder->glyph;
- for ( n = 0; n < face->hdmx.num_records; n++ )
- if ( face->hdmx.records[n].ppem == ppem )
- return face->hdmx.records[n].widths;
-
- return NULL;
+ if (glyph)
+ {
+ glyph->root.outline = builder->base;
+ glyph->max_points = builder->max_points;
+ glyph->max_contours = builder->max_contours;
+ }
}
-#define cur_to_org( n, zone ) \
- MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( TT_Vector ) )
-#define org_to_cur( n, zone ) \
- MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( TT_Vector ) )
+/*********************************************************************
+ *
+ * <Function>
+ * T2_Init_Decoder
+ *
+ * <Description>
+ * Initialise a given Type 2 decoder for parsing
+ *
+ * <Input>
+ * decoder :: Type 1 decoder to initialise
+ * funcs :: hinter functions interface
+ *
+ *********************************************************************/
-
- /*************************************************************************/
- /* Translates an array of coordinates. */
- /* */
- static
- void translate_array( FT_UInt n,
- FT_Vector* coords,
- FT_Pos delta_x,
- FT_Pos delta_y )
+ static FT_Int t2_compute_bias( FT_UInt num_subrs )
{
- FT_UInt k;
-
- if ( delta_x )
- for ( k = 0; k < n; k++ )
- coords[k].x += delta_x;
-
- if ( delta_y )
- for ( k = 0; k < n; k++ )
- coords[k].y += delta_y;
+ FT_Int result;
+
+ if (num_subrs < 1240)
+ result = 107;
+ else if (num_subrs < 33900)
+ result = 1131;
+ else
+ result = 32768;
+
+ return result;
}
-
- /*************************************************************************/
- /* Mounts one glyph zone on top of another. This is needed to */
- /* assemble composite glyphs. */
- /* */
- static
- void mount_zone( FT_GlyphZone* source,
- FT_GlyphZone* target )
+ LOCAL_FUNC
+ void T2_Init_Decoder( T2_Decoder* decoder,
+ TT_Face face,
+ T2_Size size,
+ T2_GlyphSlot slot )
{
- FT_UInt np;
- FT_Int nc;
+ CFF_Font* cff = (CFF_Font*)face->other;
+
+ /* clear everything */
+ MEM_Set( decoder, 0, sizeof(*decoder) );
- np = source->n_points;
- nc = source->n_contours;
-
- target->org = source->org + np;
- target->cur = source->cur + np;
- target->tags = source->tags + np;
-
- target->contours = source->contours + nc;
-
- target->n_points = 0;
- target->n_contours = 0;
+ /* initialise builder */
+ T2_Init_Builder( &decoder->builder, face, size, slot );
+
+ /* initialise Type2 decoder */
+ decoder->num_locals = cff->num_local_subrs;
+ decoder->num_globals = cff->num_global_subrs;
+ decoder->locals = cff->local_subrs;
+ decoder->globals = cff->global_subrs;
+ decoder->locals_bias = t2_compute_bias( decoder->num_locals );
+ decoder->globals_bias = t2_compute_bias( decoder->num_globals );
+
+ decoder->glyph_width = cff->private_dict.default_width;
+ decoder->nominal_width = cff->private_dict.nominal_width;
}
-#undef IS_HINTED
-#define IS_HINTED(flags) ((flags & FT_LOAD_NO_HINTING) == 0)
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Load_Simple_Glyph */
- /* */
- /* <Description> */
- /* Loads a simple (i.e, non-composite) glyph. This function is used */
- /* for the `Load_Simple' state of TT_Load_Glyph(). All composite */
- /* glyphs elements will be loaded with routine. */
- /* */
+ /* check that there is enough room for "count" more points */
static
- FT_Error Load_Simple( T2_Loader* load,
- FT_UInt byte_count,
- FT_Int n_contours,
- FT_Bool debug )
+ FT_Error check_points( T2_Builder* builder,
+ FT_Int count )
{
- FT_Error error;
- FT_Stream stream = load->stream;
- FT_GlyphZone* zone = &load->zone;
- T2_Face face = load->face;
+ FT_Outline* base = &builder->base;
+ FT_Outline* outline = &builder->current;
- FT_UShort n_ins;
- FT_Int n, n_points;
+ if (!builder->load_points)
+ return FT_Err_Ok;
- /*********************************************************************/
- /* simple check */
+ count += base->n_points + outline->n_points;
- if ( n_contours > load->left_contours )
+ /* realloc points table if necessary */
+ if ( count >= builder->max_points )
{
- FT_TRACE0(( "ERROR: Glyph index %ld has %d contours > left %d\n",
- load->glyph_index,
- n_contours,
- load->left_contours ));
- return TT_Err_Too_Many_Contours;
- }
+ FT_Error error;
+ FT_Memory memory = builder->memory;
+ FT_Int increment = outline->points - base->points;
+ FT_Int current = builder->max_points;
- /* preparing the execution context */
- mount_zone( &load->base, zone );
+ while ( builder->max_points < count )
+ builder->max_points += 8;
- /*********************************************************************/
- /* reading the contours endpoints */
+ if ( REALLOC_ARRAY( base->points, current,
+ builder->max_points, FT_Vector ) ||
- if ( ACCESS_Frame( byte_count ) )
- return error;
-
- for ( n = 0; n < n_contours; n++ )
- zone->contours[n] = GET_UShort();
-
- n_points = 0;
- if ( n_contours > 0 )
- n_points = zone->contours[n_contours - 1] + 1;
-
-
- /*********************************************************************/
- /* reading the bytecode instructions */
-
- n_ins = GET_UShort();
- load->face->root.glyph->control_len = n_ins;
-
- if ( n_points > load->left_points )
- {
- FT_TRACE0(( "ERROR: Too many points in glyph %ld\n", load->glyph_index ));
- error = TT_Err_Too_Many_Points;
- goto Fail;
- }
-
- FT_TRACE4(( "Instructions size : %d\n", n_ins ));
-
- if ( n_ins > face->max_profile.maxSizeOfInstructions )
- {
- FT_TRACE0(( "ERROR: Too many instructions!\n" ));
- error = TT_Err_Too_Many_Ins;
- goto Fail;
- }
-
- if (stream->cursor + n_ins > stream->limit)
- {
- FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
- error = TT_Err_Too_Many_Ins;
- goto Fail;
- }
-
- stream->cursor += n_ins;
-
- /*********************************************************************/
- /* reading the point tags */
-
- {
- FT_Byte* flag = load->zone.tags;
- FT_Byte* limit = flag + n_points;
- FT_Byte c, count;
-
- for (; flag < limit; flag++)
+ REALLOC_ARRAY( base->tags, current,
+ builder->max_points, FT_Byte ) )
{
- *flag = c = GET_Byte();
- if ( c & 8 )
- {
- for ( count = GET_Byte(); count > 0; count-- )
- *++flag = c;
- }
+ builder->error = error;
+ return error;
}
- }
- /*********************************************************************/
- /* reading the X coordinates */
-
- {
- FT_Vector* vec = zone->org;
- FT_Vector* limit = vec + n_points;
- FT_Byte* flag = zone->tags;
- FT_Pos x = 0;
-
- for ( ; vec < limit; vec++, flag++ )
- {
- FT_Pos y = 0;
-
- if ( *flag & 2 )
- {
- y = GET_Byte();
- if ((*flag & 16) == 0) y = -y;
- }
- else if ((*flag & 16) == 0)
- y = GET_Short();
-
- x += y;
- vec->x = x;
- }
+ outline->points = base->points + increment;
+ outline->tags = base->tags + increment;
}
+ return FT_Err_Ok;
+ }
- /*********************************************************************/
- /* reading the Y coordinates */
+ /* add a new point, do not check room */
+ static
+ void add_point( T2_Builder* builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag )
+ {
+ FT_Outline* outline = &builder->current;
+
+ if (builder->load_points)
{
- FT_Vector* vec = zone->org;
- FT_Vector* limit = vec + n_points;
- FT_Byte* flag = zone->tags;
- FT_Pos x = 0;
+ FT_Vector* point = outline->points + outline->n_points;
+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
- for ( ; vec < limit; vec++, flag++ )
- {
- FT_Pos y = 0;
+ point->x = x >> 16;
+ point->y = y >> 16;
+ *control = ( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
- if ( *flag & 4 )
- {
- y = GET_Byte();
- if ((*flag & 32) == 0) y = -y;
- }
- else if ((*flag & 32) == 0)
- y = GET_Short();
-
- x += y;
- vec->y = x;
- }
+ builder->last = *point;
}
- FORGET_Frame();
+ outline->n_points++;
+ }
- /*********************************************************************/
- /* Add shadow points */
- /* Now add the two shadow points at n and n + 1. */
- /* We need the left side bearing and advance width. */
+ /* check room for a new on-curve point, then add it */
+ static
+ FT_Error add_point1( T2_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error;
- {
- FT_Vector* pp1;
- FT_Vector* pp2;
+ error = check_points(builder,1);
+ if (!error)
+ add_point( builder, x, y, 1 );
- /* pp1 = xMin - lsb */
- pp1 = zone->org + n_points;
- pp1->x = load->bbox.xMin - load->left_bearing;
- pp1->y = 0;
+ return error;
+ }
- /* pp2 = pp1 + aw */
- pp2 = pp1 + 1;
- pp2->x = pp1->x + load->advance;
- pp2->y = 0;
- /* clear the touch tags */
- for ( n = 0; n < n_points; n++ )
- zone->tags[n] &= FT_Curve_Tag_On;
+ /* check room for a new contour, then add it */
+ static
+ FT_Error add_contour( T2_Builder* builder )
+ {
+ FT_Outline* base = &builder->base;
+ FT_Outline* outline = &builder->current;
- zone->tags[n_points ] = 0;
- zone->tags[n_points + 1] = 0;
+ if (!builder->load_points)
+ {
+ outline->n_contours++;
+ return FT_Err_Ok;
}
- /* Note that we return two more points that are not */
- /* part of the glyph outline. */
- zone->n_points = n_points;
- zone->n_contours = n_contours;
- n_points += 2;
-
- /*******************************************/
- /* now eventually scale and hint the glyph */
-
- if (load->load_flags & FT_LOAD_NO_SCALE)
+ /* realloc contours array if necessary */
+ if ( base->n_contours + outline->n_contours >= builder->max_contours &&
+ builder->load_points )
{
- /* no scaling, just copy the orig arrays into the cur ones */
- org_to_cur( n_points, zone );
- }
- else
- {
- FT_Vector* vec = zone->org;
- FT_Vector* limit = vec + n_points;
- FT_Fixed x_scale = load->size->root.metrics.x_scale;
- FT_Fixed y_scale = load->size->root.metrics.y_scale;
+ FT_Error error;
+ FT_Memory memory = builder->memory;
+ FT_Int increment = outline->contours - base->contours;
+ FT_Int current = builder->max_contours;
- /* first scale the glyph points */
- for (; vec < limit; vec++)
- {
- vec->x = FT_MulFix( vec->x, x_scale );
- vec->y = FT_MulFix( vec->y, y_scale );
- }
+ builder->max_contours += 4;
- /* if hinting, round pp1, and shift the glyph accordingly */
- if ( !IS_HINTED(load->load_flags) )
+ if ( REALLOC_ARRAY( base->contours,
+ current, builder->max_contours, FT_Short ) )
{
- org_to_cur( n_points, zone );
+ builder->error = error;
+ return error;
}
- else
- {
- FT_Pos x = zone->org[n_points-2].x;
- x = ((x + 32) & -64) - x;
- translate_array( n_points, zone->org, x, 0 );
- org_to_cur( n_points, zone );
-
- zone->cur[n_points-1].x = (zone->cur[n_points-1].x + 32) & -64;
-
- }
+ outline->contours = base->contours + increment;
}
- /* save glyph phantom points */
- if ( !load->preserve_pps )
- {
- load->pp1 = zone->cur[n_points - 2];
- load->pp2 = zone->cur[n_points - 1];
- }
+ if (outline->n_contours > 0)
+ outline->contours[ outline->n_contours-1 ] = outline->n_points-1;
+ outline->n_contours++;
return FT_Err_Ok;
-
- Fail:
- FORGET_Frame();
- return error;
}
-
-
-
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* load_opentype_glyph */
- /* */
- /* <Description> */
- /* Loads a given truetype glyph. Handles composites and uses a */
- /* T2_Loader object.. */
- /* */
+ /* if a path was begun, add its first on-curve point */
static
- FT_Error load_opentype_glyph( T2_Loader* loader,
- FT_UInt glyph_index )
+ FT_Error start_point( T2_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
{
- FT_Stream stream = loader->stream;
- FT_Error error;
- T2_Face face = loader->face;
- FT_ULong offset;
- FT_Int num_subglyphs = 0, contours_count;
- FT_UInt index, num_points, num_contours, count;
- FT_Fixed x_scale, y_scale;
- FT_ULong ins_offset;
-
- /* check glyph index */
- index = glyph_index;
- if ( index >= (TT_UInt)face->root.num_glyphs )
+ /* test wether we're building a new contour */
+ if (!builder->path_begun)
{
- error = TT_Err_Invalid_Glyph_Index;
- goto Fail;
- }
+ FT_Error error;
- loader->glyph_index = glyph_index;
- num_contours = 0;
- num_points = 0;
- ins_offset = 0;
-
- x_scale = 0x10000;
- y_scale = 0x10000;
- if ( (loader->load_flags & FT_LOAD_NO_SCALE)==0 )
- {
- x_scale = loader->size->root.metrics.x_scale;
- y_scale = loader->size->root.metrics.y_scale;
+ builder->path_begun = 1;
+ error = add_contour( builder );
+ if (error) return error;
}
+ return add_point1( builder, x, y );
+ }
- /* get horizontal metrics */
- {
- FT_Short left_bearing;
- FT_UShort advance_width;
- Get_HMetrics( face, index,
- (FT_Bool)!(loader->load_flags &
- FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
- &left_bearing,
- &advance_width );
+ /* close the current contour */
+ static
+ void close_contour( T2_Builder* builder )
+ {
+ FT_Outline* outline = &builder->current;
- loader->left_bearing = left_bearing;
- loader->advance = advance_width;
- }
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours-1] = outline->n_points-1;
+ }
- /* load glyph header */
- offset = face->glyph_locations[index];
- count = 0;
- if (index < (TT_UInt)face->num_locations-1)
- count = face->glyph_locations[index+1] - offset;
+/*********************************************************************
+ *
+ * <Function>
+ * T2_Parse_CharStrings
+ *
+ * <Description>
+ * Parses a given Type 1 charstrings program
+ *
+ * <Input>
+ * decoder :: current Type 1 decoder
+ * charstring_base :: base of the charstring stream
+ * charstring_len :: length in bytes of the charstring stream
+ * num_subrs :: number of sub-routines
+ * subrs_base :: array of sub-routines addresses
+ * subrs_len :: array of sub-routines lengths
+ *
+ * <Return>
+ * Error code. 0 means success.
+ *
+ *********************************************************************/
- if (count == 0)
- {
- /* as described by Frederic Loyer, these are spaces, and */
- /* not the unknown glyph. */
- loader->bbox.xMin = 0;
- loader->bbox.xMax = 0;
- loader->bbox.yMin = 0;
- loader->bbox.yMax = 0;
+#define USE_ARGS(n) top -= n; if (top < decoder->stack) goto Stack_Underflow
- loader->pp1.x = 0;
- loader->pp2.x = loader->advance;
- if ( (loader->load_flags & FT_LOAD_NO_SCALE)==0 )
- loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+ LOCAL_FUNC
+ FT_Error T2_Parse_CharStrings( T2_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len )
+ {
+ FT_Error error;
+ T2_Decoder_Zone* zone;
+ FT_Byte* ip;
+ FT_Byte* limit;
+ T2_Builder* builder = &decoder->builder;
+ FT_Outline* outline;
+ FT_Pos x, y;
+ FT_Fixed seed;
+ FT_Fixed* stack;
- goto Load_End;
- }
+ /* set default width */
+ decoder->num_hints = 0;
+ decoder->read_width = 1;
+
+ /* compute random seed from stack address of parameter */
+ seed = (FT_Fixed)(char*)&seed ^
+ (FT_Fixed)(char*)&decoder ^
+ (FT_Fixed)(char*)&charstring_base;
+ seed = (seed ^ (seed >> 10) ^ (seed >> 20)) & 0xFFFF;
+ if (seed == 0)
+ seed = 0x7384;
+
+ /* First of all, initialise the decoder */
+ decoder->top = decoder->stack;
+ decoder->zone = decoder->zones;
+ zone = decoder->zones;
+ stack = decoder->top;
- offset = loader->glyf_offset + offset;
+ builder->path_begun = 0;
- /* read first glyph header */
- if ( FILE_Seek( offset ) || ACCESS_Frame( 10L ) )
- goto Fail;
+ zone->base = charstring_base;
+ limit = zone->limit = charstring_base + charstring_len;
+ ip = zone->cursor = zone->base;
- contours_count = GET_Short();
+ error = FT_Err_Ok;
+ outline = &builder->current;
+
+ x = builder->pos_x;
+ y = builder->pos_y;
- loader->bbox.xMin = GET_Short();
- loader->bbox.yMin = GET_Short();
- loader->bbox.xMax = GET_Short();
- loader->bbox.yMax = GET_Short();
-
- FORGET_Frame();
-
- FT_TRACE6(( "Glyph %ld\n", index ));
- FT_TRACE6(( " # of contours : %d\n", num_contours ));
- FT_TRACE6(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
- loader->bbox.xMax ));
- FT_TRACE6(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
- loader->bbox.yMax ));
- FT_TRACE6(( "-" ));
-
- count -= 10;
-
- if ( contours_count > loader->left_contours )
+ /* now, execute loop */
+ while ( ip < limit )
{
- FT_TRACE0(( "ERROR: Too many contours for glyph %ld\n", index ));
- error = TT_Err_Too_Many_Contours;
- goto Fail;
- }
+ T2_Operator op;
+ FT_Byte v;
+ FT_Byte count;
- loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
- loader->pp1.y = 0;
- loader->pp2.x = loader->pp1.x + loader->advance;
- loader->pp2.y = 0;
-
- if ((loader->load_flags & FT_LOAD_NO_SCALE)==0)
- {
- loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
- loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
- }
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
- /**********************************************************************/
- /* if it is a simple glyph, load it */
- if (contours_count >= 0)
- {
- FT_UInt num_base_points;
-
- error = Load_Simple( loader, count, contours_count, 0 );
- if ( error ) goto Fail;
-
- /* Note: We could have put the simple loader source there */
- /* but the code is fat enough already :-) */
- num_points = loader->zone.n_points;
- num_contours = loader->zone.n_contours;
-
- num_base_points = loader->base.n_points;
+ /********************************************************************/
+ /* */
+ /* Decode operator or operand */
+ /* */
+ /* */
+ v = *ip++;
+ if (v >= 32 || v == 28)
{
- FT_UInt k;
- for ( k = 0; k < num_contours; k++ )
- loader->zone.contours[k] += num_base_points;
- }
-
- loader->base.n_points += num_points;
- loader->base.n_contours += num_contours;
-
- loader->zone.n_points = 0;
- loader->zone.n_contours = 0;
-
- loader->left_points -= num_points;
- loader->left_contours -= num_contours;
- }
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
- /************************************************************************/
- else /* otherwise, load a composite !! */
- {
- /* for each subglyph, read composite header */
- T2_GlyphSlot glyph = loader->glyph;
- FT_SubGlyph* subglyph = glyph->subglyphs + glyph->num_subglyphs;
-
- if (ACCESS_Frame(count)) goto Fail;
-
- num_subglyphs = 0;
- do
- {
- TT_Fixed xx, xy, yy, yx;
- FT_UInt total_subglyphs;
-
- /* grow the 'glyph->subglyphs' table if necessary */
- total_subglyphs = glyph->num_subglyphs + num_subglyphs;
- if ( total_subglyphs >= glyph->max_subglyphs )
- {
- FT_UInt new_max = glyph->max_subglyphs;
- FT_Memory memory = loader->face->root.memory;
-
- while (new_max <= total_subglyphs)
- new_max += 4;
-
- if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
- new_max, FT_SubGlyph ) )
- goto Fail;
-
- glyph->max_subglyphs = new_max;
- subglyph = glyph->subglyphs + glyph->num_subglyphs + num_subglyphs;
- }
-
- subglyph->arg1 = subglyph->arg2 = 0;
-
- subglyph->flags = GET_UShort();
- subglyph->index = GET_UShort();
-
- /* read arguments */
- if (subglyph->flags & ARGS_ARE_WORDS)
+ FT_Int shift = 16;
+ FT_Long val;
+
+ /* this is an operand, push it on the stack */
+ if ( v == 28)
{
- subglyph->arg1 = GET_Short();
- subglyph->arg2 = GET_Short();
+ if ( ip+1 >= limit ) goto Syntax_Error;
+ val = (FT_Short)(((FT_Int)ip[0] << 8) + ip[1]);
+ ip += 2;
}
- else
+ else if ( v < 247 )
+ val = v - 139;
+ else if ( v < 251 )
{
- subglyph->arg1 = GET_Char();
- subglyph->arg2 = GET_Char();
+ if ( ip >= limit ) goto Syntax_Error;
+ val = (v-247)*256 + *ip++ + 108;
}
-
- /* read transform */
- xx = yy = 0x10000;
- xy = yx = 0;
-
- if (subglyph->flags & WE_HAVE_A_SCALE)
+ else if ( v < 255 )
{
- xx = (TT_Fixed)GET_Short() << 2;
- yy = xx;
+ if ( ip >= limit ) goto Syntax_Error;
+ val = -((v-251)*256) - *ip++ - 108;
}
- else if (subglyph->flags & WE_HAVE_AN_XY_SCALE)
+ else
{
- xx = (TT_Fixed)GET_Short() << 2;
- yy = (TT_Fixed)GET_Short() << 2;
+ if ( ip + 3 >= limit ) goto Syntax_Error;
+ val = ((FT_Long)ip[0] << 24) |
+ ((FT_Long)ip[1] << 16) |
+ ((FT_Long)ip[2] << 8) | ip[3];
+ ip += 4;
+ shift = 0;
}
- else if (subglyph->flags & WE_HAVE_A_2X2)
- {
- xx = (TT_Fixed)GET_Short() << 2;
- xy = (TT_Fixed)GET_Short() << 2;
- yx = (TT_Fixed)GET_Short() << 2;
- yy = (TT_Fixed)GET_Short() << 2;
- }
-
- subglyph->transform.xx = xx;
- subglyph->transform.xy = xy;
- subglyph->transform.yx = yx;
- subglyph->transform.yy = yy;
-
- subglyph++;
- num_subglyphs++;
+ if (decoder->top - stack >= T2_MAX_OPERANDS)
+ goto Stack_Overflow;
+
+ val <<= shift;
+ *decoder->top ++ = val;
+
+ #ifdef FT_DEBUG_LEVEL_TRACE
+ if (!(val & 0xFFFF))
+ FT_TRACE4(( " %d", (FT_Int)(val >> 16) ));
+ else
+ FT_TRACE4(( " %.2f", val/65536.0 ));
+ #endif
}
- while (subglyph[-1].flags & MORE_COMPONENTS);
-
- FORGET_Frame();
-
- /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
- /* "as is" in the glyph slot (the client application will be */
- /* responsible for interpreting this data..) */
- if ( loader->load_flags & FT_LOAD_NO_RECURSE )
+ else
{
- /* set up remaining glyph fields */
- glyph->num_subglyphs += num_subglyphs;
- glyph->format = ft_glyph_format_composite;
- goto Load_End;
- }
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
- /*********************************************************************/
- /* Now, read each subglyph independently.. */
- {
- FT_Int n, num_base_points, num_new_points;
-
- subglyph = glyph->subglyphs + glyph->num_subglyphs;
- glyph->num_subglyphs += num_subglyphs;
-
- for ( n = 0; n < num_subglyphs; n++, subglyph++ )
+ FT_Fixed* args = decoder->top;
+ FT_Int num_args = args - decoder->stack;
+ FT_Int req_args;
+
+ /* find operator */
+ op = t2_op_unknown;
+ switch (v)
{
- FT_Vector pp1, pp2;
- FT_Pos x, y;
+ case 1: op = t2_op_hstem; break;
+ case 3: op = t2_op_vstem; break;
+ case 4: op = t2_op_vmoveto; break;
+ case 5: op = t2_op_rlineto; break;
+ case 6: op = t2_op_hlineto; break;
+ case 7: op = t2_op_vlineto; break;
+ case 8: op = t2_op_rrcurveto; break;
+ case 10: op = t2_op_callsubr; break;
+ case 11: op = t2_op_return; break;
+ case 12:
+ {
+ if (ip >= limit) goto Syntax_Error;
+ v = *ip++;
+ switch (v)
+ {
+ case 3: op = t2_op_and; break;
+ case 4: op = t2_op_or; break;
+ case 5: op = t2_op_not; break;
+ case 8: op = t2_op_store; break;
+ case 9: op = t2_op_abs; break;
+ case 10: op = t2_op_add; break;
+ case 11: op = t2_op_sub; break;
+ case 12: op = t2_op_div; break;
+ case 13: op = t2_op_load; break;
+ case 14: op = t2_op_neg; break;
+ case 15: op = t2_op_eq; break;
+ case 18: op = t2_op_drop; break;
+ case 20: op = t2_op_put; break;
+ case 21: op = t2_op_get; break;
+ case 22: op = t2_op_ifelse; break;
+ case 23: op = t2_op_random; break;
+ case 24: op = t2_op_mul; break;
+ case 26: op = t2_op_sqrt; break;
+ case 27: op = t2_op_dup; break;
+ case 28: op = t2_op_exch; break;
+ case 29: op = t2_op_index; break;
+ case 30: op = t2_op_roll; break;
+ case 34: op = t2_op_hflex; break;
+ case 35: op = t2_op_flex; break;
+ case 36: op = t2_op_hflex1; break;
+ case 37: op = t2_op_flex1; break;
+ default:
+ /* decrement ip for syntax error message */
+ ip--;
+ }
+ }
+ break;
+
+ case 14: op = t2_op_endchar; break;
+ case 16: op = t2_op_blend; break;
+ case 18: op = t2_op_hstemhm; break;
+ case 19: op = t2_op_hintmask; break;
+ case 20: op = t2_op_cntrmask; break;
+ case 21: op = t2_op_rmoveto; break;
+ case 22: op = t2_op_hmoveto; break;
+ case 23: op = t2_op_vstemhm; break;
+ case 24: op = t2_op_rcurveline; break;
+ case 25: op = t2_op_rlinecurve; break;
+ case 26: op = t2_op_vvcurveto; break;
+ case 27: op = t2_op_hhcurveto; break;
+ case 29: op = t2_op_callgsubr; break;
+ case 30: op = t2_op_vhcurveto; break;
+ case 31: op = t2_op_hvcurveto; break;
+ default:
+ ;
+ }
+ if ( op == t2_op_unknown )
+ goto Syntax_Error;
- pp1 = loader->pp1;
- pp2 = loader->pp2;
-
- num_base_points = loader->base.n_points;
-
- error = load_truetype_glyph( loader, subglyph->index );
- if (error) goto Fail;
-
- if ( subglyph->flags & USE_MY_METRICS )
+ /* check arguments */
+ req_args = count = t2_argument_counts[op];
+ if (req_args & T2_COUNT_CHECK_WIDTH)
+ {
+ args = stack;
+ if ( decoder->read_width )
{
- pp1 = loader->pp1;
- pp2 = loader->pp2;
+ decoder->glyph_width = decoder->nominal_width + (stack[0] >> 16);
+ decoder->read_width = 0;
+ num_args--;
+ args++;
}
- else
- {
- loader->pp1 = pp1;
- loader->pp2 = pp2;
- }
+ req_args = 0;
+ }
+
+ req_args &= 15;
+ if (num_args < req_args) goto Stack_Underflow;
+ args -= req_args;
+ num_args -= req_args;
+
+ switch (op)
+ {
+ case t2_op_hstem:
+ case t2_op_vstem:
+ case t2_op_hstemhm:
+ case t2_op_vstemhm:
+ {
+ /* if the number of arguments is no even, the first one */
+ /* is simply the glyph width.. encoded as the difference */
+ /* to nominalWidthX */
+ FT_TRACE4(( op == t2_op_hstem ? " hstem" :
+ op == t2_op_vstem ? " vstem" :
+ op == t2_op_hstemhm ? " hstemhm" :
+ " vstemhm" ));
+ decoder->num_hints += num_args/2;
+ args = stack;
+ }
+ break;
+
+ case t2_op_hintmask:
+ case t2_op_cntrmask:
+ {
+ FT_TRACE4(( op == t2_op_hintmask ? " hintmask" : " cntrmask" ));
+ decoder->num_hints += num_args/2;
+ ip += (decoder->num_hints+7) >> 3;
+ if (ip >= limit) goto Syntax_Error;
+ args = stack;
+ }
+ break;
+
+ case t2_op_rmoveto:
+ {
+ FT_TRACE4(( " rmoveto" ));
+ close_contour( builder );
+ builder->path_begun = 0;
+ x += args[0];
+ y += args[1];
+ args = stack;
+ }
+ break;
+
+ case t2_op_vmoveto:
+ {
+ FT_TRACE4(( " vmoveto" ));
+ close_contour( builder );
+ builder->path_begun = 0;
+ y += args[0];
+ args = stack;
+ }
+ break;
+
+ case t2_op_hmoveto:
+ {
+ FT_TRACE4(( " vmoveto" ));
+ close_contour( builder );
+ builder->path_begun = 0;
+ x += args[0];
+ args = stack;
+ }
+ break;
+
+ case t2_op_rlineto:
+ {
+ FT_TRACE4(( " rlineto" ));
- num_points = loader->base.n_points;
- num_contours = loader->base.n_contours;
+ if ( start_point ( builder, x, y ) ||
+ check_points( builder, num_args/2 ) ) goto Memory_Error;
- num_new_points = num_points - num_base_points;
+ if ( num_args < 2 || num_args & 1 ) goto Stack_Underflow;
+ args = stack;
+ while ( args < decoder->top )
+ {
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 1 );
+ args += 2;
+ }
+ args = stack;
+ }
+ break;
- /********************************************************/
- /* now perform the transform required for this subglyph */
-
- if ( subglyph->flags & ( WE_HAVE_A_SCALE |
- WE_HAVE_AN_XY_SCALE |
- WE_HAVE_A_2X2 ) )
- {
- FT_Vector* cur = loader->zone.cur;
- FT_Vector* org = loader->zone.org;
- FT_Vector* limit = cur + num_new_points;
-
- for ( ; cur < limit; cur++, org++ )
+ case t2_op_hlineto:
+ case t2_op_vlineto:
{
- TT_Pos nx, ny;
+ FT_Int phase = ( op == t2_op_hlineto );
- nx = FT_MulFix( cur->x, subglyph->transform.xx ) +
- FT_MulFix( cur->y, subglyph->transform.yx );
+ FT_TRACE4(( op == t2_op_hlineto ? " hlineto" : " vlineto" ));
- ny = FT_MulFix( cur->x, subglyph->transform.xy ) +
- FT_MulFix( cur->y, subglyph->transform.yy );
+ if ( start_point ( builder, x, y ) ||
+ check_points( builder, num_args ) ) goto Memory_Error;
- cur->x = nx;
- cur->y = ny;
+ args = stack;
+ while (args < decoder->top )
+ {
+ if (phase) x += args[0];
+ else y += args[0];
+
+ if (add_point1( builder, x, y )) goto Memory_Error;
+ args++;
+ phase ^= 1;
+ }
+ args = stack;
+ }
+ break;
- nx = FT_MulFix( org->x, subglyph->transform.xx ) +
- FT_MulFix( org->y, subglyph->transform.yx );
+ case t2_op_rrcurveto:
+ {
+ FT_TRACE4(( " rrcurveto" ));
- ny = FT_MulFix( org->x, subglyph->transform.xy ) +
- FT_MulFix( org->y, subglyph->transform.yy );
+ /* check number of arguments, must be a multiple of 6 */
+ if (num_args % 6 != 0) goto Stack_Underflow;
+
+ if ( start_point ( builder, x, y ) ||
+ check_points( builder, num_args/2 ) ) goto Memory_Error;
+
+ args = stack;
+ while (args < decoder->top)
+ {
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 0 );
+ x += args[2];
+ y += args[3];
+ add_point( builder, x, y, 0 );
+ x += args[4];
+ y += args[5];
+ add_point( builder, x, y, 1 );
+ args += 6;
+ }
+ args = stack;
+ }
+ break;
+
+ case t2_op_vvcurveto:
+ {
+ FT_TRACE4(( " vvcurveto" ));
+
+ if ( start_point ( builder, x, y ) ) goto Memory_Error;
+
+ args = stack;
+ if (num_args & 1)
+ {
+ x += args[0];
+ args++;
+ num_args--;
+ }
+ if (num_args % 4 != 0) goto Stack_Underflow;
+ if (check_points( builder, 3*(num_args/4) )) goto Memory_Error;
- org->x = nx;
- org->y = ny;
+ while (args < decoder->top)
+ {
+ y += args[0];
+ add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ add_point( builder, x, y, 0 );
+ y += args[3];
+ add_point( builder, x, y, 1 );
+ args += 4;
+ }
+ args = stack;
}
- }
+ break;
- /* apply offset */
+ case t2_op_hhcurveto:
+ {
+ FT_TRACE4(( " hhcurveto" ));
+
+ if ( start_point ( builder, x, y ) ) goto Memory_Error;
+ args = stack;
+ if (num_args & 1)
+ {
+ y += args[0];
+ args++;
+ num_args--;
+ }
+ if (num_args % 4 != 0) goto Stack_Underflow;
+ if (check_points( builder, 3*(num_args/4) )) goto Memory_Error;
- if ( !(subglyph->flags & ARGS_ARE_XY_VALUES) )
- {
- FT_Int k = subglyph->arg1;
- FT_UInt l = subglyph->arg2;
+ while (args < decoder->top)
+ {
+ x += args[0];
+ add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ add_point( builder, x, y, 0 );
+ x += args[3];
+ add_point( builder, x, y, 1 );
+ args += 4;
+ }
+ args = stack;
+ }
+ break;
- if ( k >= num_base_points ||
- l >= (TT_UInt)num_new_points )
+ case t2_op_vhcurveto:
+ case t2_op_hvcurveto:
{
- error = TT_Err_Invalid_Composite;
- goto Fail;
+ FT_Int phase;
+
+ FT_TRACE4(( op == t2_op_vhcurveto ? " vhcurveto" : " hvcurveto" ));
+
+ if ( start_point ( builder, x, y ) ) goto Memory_Error;
+ args = stack;
+ if (num_args < 4 || (num_args % 4) > 1 ) goto Stack_Underflow;
+ if (check_points( builder, (num_args/4)*3 )) goto Stack_Underflow;
+ phase = ( op == t2_op_hvcurveto );
+ while (num_args >= 4)
+ {
+ num_args -= 4;
+ if (phase)
+ {
+ x += args[0];
+ add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ add_point( builder, x, y, 0 );
+ y += args[3];
+ if (num_args == 1)
+ x += args[4];
+ add_point( builder, x, y, 1 );
+ }
+ else
+ {
+ y += args[0];
+ add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ add_point( builder, x, y, 0 );
+ x += args[3];
+ if (num_args == 1)
+ y += args[4];
+ add_point( builder, x, y, 1 );
+ }
+ args += 4;
+ phase ^= 1;
+ }
+ args = stack;
}
+ break;
- l += num_base_points;
+ case t2_op_rlinecurve:
+ case t2_op_rcurveline:
+ {
+ FT_Int mod6 = num_args % 6;
+
+ FT_TRACE4(( op == t2_op_rcurveline ? " rcurveline" :
+ " rlinecurve" ));
+
+ if ( num_args < 8 || (mod6 != 0 && mod6 != 2) )
+ goto Stack_Underflow;
- x = loader->base.cur[k].x - loader->base.cur[l].x;
- y = loader->base.cur[k].y - loader->base.cur[l].y;
- }
- else
- {
- x = subglyph->arg1;
- y = subglyph->arg2;
-
- if (!(loader->load_flags & FT_LOAD_NO_SCALE))
+ if ( start_point ( builder, x, y ) ||
+ check_points( builder, (num_args/6)*3 + mod6/2 ) )
+ goto Memory_Error;
+
+ args = stack;
+ if (op == t2_op_rlinecurve && mod6)
+ {
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 1 );
+ args += 2;
+ num_args -= 2;
+ }
+ while (num_args >= 6)
+ {
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 0 );
+ x += args[2];
+ y += args[3];
+ add_point( builder, x, y, 0 );
+ x += args[4];
+ y += args[5];
+ add_point( builder, x, y, 1 );
+ args += 6;
+ num_args -= 6;
+ }
+ if ( op == t2_op_rcurveline && num_args)
+ {
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 1 );
+ }
+ args = stack;
+ }
+ break;
+
+ case t2_op_endchar:
+ {
+ FT_TRACE4(( " 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 !! */
+ FT_TRACE4(( "\n\n" ));
+ return FT_Err_Ok;
+ }
+
+ case t2_op_abs:
+ {
+ FT_TRACE4(( " abs" ));
+ if (args[0] < 0)
+ args[0] = -args[0];
+ args++;
+ }
+ break;
+
+ case t2_op_add:
+ {
+ FT_TRACE4(( " add" ));
+ args[0] += args[1];
+ args++;
+ }
+ break;
+
+ case t2_op_sub:
+ {
+ FT_TRACE4(( " sub" ));
+ args[0] -= args[1];
+ args++;
+ }
+ break;
+
+ case t2_op_div:
+ {
+ FT_TRACE4(( " div" ));
+ args[0] = FT_DivFix( args[0], args[1] );
+ args++;
+ }
+ break;
+
+ case t2_op_neg:
+ {
+ FT_TRACE4(( " neg" ));
+ args[0] = -args[0];
+ args++;
+ }
+ break;
+
+ case t2_op_random:
+ {
+ FT_Fixed rand;
+
+ FT_TRACE4(( " rand" ));
+ rand = seed;
+ if (rand >= 0x8000)
+ rand++;
+
+ args[0] = rand;
+ seed = FT_MulFix( seed, 0x10000 - seed );
+ if (seed == 0) seed += 0x2873;
+ args++;
+ }
+ break;
+
+ case t2_op_mul:
+ {
+ FT_TRACE4(( " mul" ));
+ args[0] = FT_MulFix( args[0], args[1] );
+ args++;
+ }
+ break;
+
+ case t2_op_sqrt:
+ {
+ FT_TRACE4(( " sqrt" ));
+ if (args[0] > 0)
+ {
+ FT_Int count = 9;
+ FT_Fixed root = args[0];
+ FT_Fixed new_root;
+
+ for (;;)
+ {
+ new_root = ( root + FT_DivFix(args[0],root) + 1 ) >> 1;
+ if (new_root == root || count <= 0)
+ break;
+ root = new_root;
+ }
+ args[0] = new_root;
+ }
+ else
+ args[0] = 0;
+ args++;
+ }
+ break;
+
+ case t2_op_drop:
{
- x = FT_MulFix( x, x_scale );
- y = FT_MulFix( y, y_scale );
-
- if ( subglyph->flags & ROUND_XY_TO_GRID )
- {
- x = (x + 32) & -64;
- y = (y + 32) & -64;
- }
+ /* nothing */
+ FT_TRACE4(( " drop" ));
+ }
+ break;
+
+ case t2_op_exch:
+ {
+ FT_Fixed tmp;
+ FT_TRACE4(( " exch" ));
+ tmp = args[0];
+ args[0] = args[1];
+ args[1] = tmp;
+ args += 2;
+ }
+ break;
+
+ case t2_op_index:
+ {
+ FT_Int index = args[0] >> 16;
+ FT_TRACE4(( " index" ));
+ if (index < 0)
+ index = 0;
+ else if (index > num_args-2)
+ index = num_args-2;
+ args[0] = args[-(index+1)];
+ args++;
+ }
+ break;
+
+ case t2_op_roll:
+ {
+ FT_Int count = (FT_Int)(args[0] >> 16);
+ FT_Int index = (FT_Int)(args[1] >> 16);
+
+ FT_TRACE4(( " roll" ));
+
+ if (count <= 0)
+ count = 1;
+
+ args -= count;
+ if (args < stack) goto Stack_Underflow;
+ if (index >= 0)
+ {
+ while (index > 0)
+ {
+ FT_Fixed tmp = args[count-1];
+ FT_Int i;
+ for ( i = count-2; i >= 0; i-- )
+ args[i+1] = args[i];
+ args[0] = tmp;
+ index--;
+ }
+ }
+ else
+ {
+ while (index < 0)
+ {
+ FT_Fixed tmp = args[0];
+ FT_Int i;
+ for ( i = 0; i < count-1; i++ )
+ args[i] = args[i+1];
+ args[count-1] = tmp;
+ index++;
+ }
+ }
+ args += count;
}
- }
-
- translate_array( num_new_points, loader->zone.cur, x, y );
- cur_to_org( num_new_points, &loader->zone );
- }
+ break;
+
+ case t2_op_dup:
+ {
+ FT_TRACE4(( " dup" ));
+ args[1] = args[0];
+ args++;
+ }
+ break;
+
+ case t2_op_put:
+ {
+ FT_Fixed val = args[0];
+ FT_Int index = (FT_Int)(args[1] >> 16);
+
+ FT_TRACE4(( " put" ));
+ if (index >= 0 && index < decoder->len_buildchar)
+ decoder->buildchar[index] = val;
+ }
+ break;
+
+ case t2_op_get:
+ {
+ FT_Int index = (FT_Int)(args[0] >> 16);
+ FT_Fixed val = 0;
+ FT_TRACE4(( " get" ));
+
+ if (index >= 0 && index < decoder->len_buildchar)
+ val = decoder->buildchar[index];
+
+ args[0] = val;
+ args++;
+ }
+ break;
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
+ case t2_op_store:
+ FT_TRACE4(( " store "));
+ goto Unimplemented;
+
+ case t2_op_load:
+ FT_TRACE4(( " load" ));
+ goto Unimplemented;
- /* we have finished loading all sub-glyphs, now, look for */
- /* instructions for this composite !! */
+ case t2_op_and:
+ {
+ FT_Fixed cond = args[0] && args[1];
+ FT_TRACE4(( " and" ));
+ args[0] = cond ? 0x10000 : 0;
+ args++;
+ }
+ break;
- }
- /* end of composite loading */
- }
+ case t2_op_or:
+ {
+ FT_Fixed cond = args[0] || args[1];
+ FT_TRACE4(( " or" ));
+ args[0] = cond ? 0x10000 : 0;
+ args++;
+ }
+ break;
+
+ case t2_op_eq:
+ {
+ FT_Fixed cond = !args[0];
+ FT_TRACE4(( " eq" ));
+ args[0] = cond ? 0x10000 : 0;
+ args++;
+ }
+ break;
+
+ case t2_op_ifelse:
+ {
+ FT_Fixed cond = args[2] <= args[3];
+ FT_TRACE4(( " ifelse" ));
+ if (!cond)
+ args[0] = args[1];
+ args++;
+ }
+ break;
+
+ case t2_op_callsubr:
+ {
+ FT_UInt index = (FT_UInt)((args[0] >> 16) + decoder->locals_bias);
+
+ FT_TRACE4(( " callsubr(%d)", index ));
+ if (index >= decoder->num_locals)
+ {
+ FT_ERROR(( "T2.Parse_Charstrings: invalid local subr index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "T2.Parse_CharStrings : too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = decoder->locals[index];
+ zone->limit = decoder->locals[index+1];
+ zone->cursor = zone->base;
+
+ if (!zone->base)
+ {
+ FT_ERROR(( "T2.Parse_CharStrings : invoking empty subrs !!\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ }
+ break;
+
+ case t2_op_callgsubr:
+ {
+ FT_UInt index = (FT_UInt)((args[0] >> 16) + decoder->globals_bias);
+
+ FT_TRACE4(( " callgsubr(%d)", index ));
+ if (index >= decoder->num_globals)
+ {
+ FT_ERROR(( "T2.Parse_Charstrings: invalid global subr index\n" ));
+ goto Syntax_Error;
+ }
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
+ if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "T2.Parse_CharStrings : too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = decoder->globals[index];
+ zone->limit = decoder->globals[index+1];
+ zone->cursor = zone->base;
+
+ if (!zone->base)
+ {
+ FT_ERROR(( "T2.Parse_CharStrings : invoking empty subrs !!\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ }
+ break;
+
+ case t2_op_return:
+ {
+ FT_TRACE4(( " return" ));
+ if ( decoder->zone <= decoder->zones )
+ {
+ FT_ERROR(( "T2.Parse_CharStrings : unexpected return\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone--;
+ zone = decoder->zone;
+ ip = zone->cursor;
+ limit = zone->limit;
+ }
+ break;
- Load_End:
- error = FT_Err_Ok;
+ default:
+
+ Unimplemented:
+ FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
+ if (ip[-1] == 12)
+ {
+ FT_ERROR(( " %d", ip[0] ));
+ }
+ FT_ERROR(( "\n" ));
+ return FT_Err_Unimplemented_Feature;
+ }
+ decoder->top = args;
+
+ } /* general operator processing */
- Fail:
+ } /* while ip < limit */
+ FT_TRACE4(( "..end..\n\n" ));
return error;
- }
+ Syntax_Error:
+ return FT_Err_Invalid_File_Format;
+ Stack_Underflow:
+ return T2_Err_Too_Few_Arguments;
+ Stack_Overflow:
+ return T2_Err_Stack_Overflow;
+
+ Memory_Error:
+ return builder->error;
+ }
- static
- void compute_glyph_metrics( T2_Loader* loader,
- FT_UInt glyph_index )
- {
- FT_UInt num_points = loader->base.n_points;
- FT_UInt num_contours = loader->base.n_contours;
- FT_BBox bbox;
- T2_Face face = loader->face;
- FT_Fixed x_scale, y_scale;
- T2_GlyphSlot glyph = loader->glyph;
- T2_Size size = loader->size;
- /* when a simple glyph was loaded, the value of */
- /* "base.n_points" and "base.n_contours" is 0, we must */
- /* take those in the "zone" instead.. */
- if ( num_points == 0 && num_contours == 0 )
- {
- num_points = loader->zone.n_points;
- num_contours = loader->zone.n_contours;
- }
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** 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. *********/
+ /********** *********/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
- x_scale = 0x10000;
- y_scale = 0x10000;
- if ( (loader->load_flags & FT_LOAD_NO_SCALE) == 0)
- {
- x_scale = size->root.metrics.x_scale;
- y_scale = size->root.metrics.y_scale;
- }
+#if 0 /* unused until we support pure CFF fonts */
+ LOCAL_FUNC
+ FT_Error T2_Compute_Max_Advance( TT_Face face,
+ FT_Int *max_advance )
+ {
+ FT_Error error = 0;
+ T2_Decoder decoder;
+ FT_Int glyph_index;
+ CFF_Font* cff = (CFF_Font*)face->other;
- if ( glyph->format != ft_glyph_format_composite )
- {
- FT_UInt u;
- for ( u = 0; u < num_points + 2; u++ )
- {
- glyph->outline.points[u] = loader->base.cur[u];
- glyph->outline.tags [u] = loader->base.tags[u];
- }
+ *max_advance = 0;
- for ( u = 0; u < num_contours; u++ )
- glyph->outline.contours[u] = loader->base.contours[u];
+ /* Initialise load decoder */
+ T2_Init_Decoder( &decoder, face, 0, 0 );
- /* glyph->outline.second_pass = TRUE; */
- glyph->outline.flags &= ~ft_outline_single_pass;
- glyph->outline.n_points = num_points;
- glyph->outline.n_contours = num_contours;
+ decoder.builder.metrics_only = 1;
+ decoder.builder.load_points = 0;
- /* translate array so that (0,0) is the glyph's origin */
- translate_array( (TT_UShort)(num_points + 2),
- glyph->outline.points,
- -loader->pp1.x,
- 0 );
-
- FT_Outline_Get_CBox( &glyph->outline, &bbox );
-
- if ( IS_HINTED(loader->load_flags) )
+ /* For each glyph, parse the glyph charstring and extract */
+ /* the advance width.. */
+ for ( glyph_index = 0; glyph_index < face->root.num_glyphs; glyph_index++ )
+ {
+ FT_Byte* charstring;
+ FT_ULong charstring_len;
+
+ /* now get load the unscaled outline */
+ error = T2_Access_Element( &cff->charstrings_index, glyph_index,
+ &charstring, &charstring_len );
+ if (!error)
{
- /* grid-fit the bounding box */
- bbox.xMin &= -64;
- bbox.yMin &= -64;
- bbox.xMax = (bbox.xMax + 63) & -64;
- bbox.yMax = (bbox.yMax + 63) & -64;
+ error = T2_Parse_CharStrings( &decoder, charstring, charstring_len );
+
+ T2_Forget_Element( &cff->charstrings_index, &charstring );
}
+ /* ignore the error if one occured - skip to next glyph */
+ error = 0;
}
- else
- bbox = loader->bbox;
- /* get the device-independent scaled horizontal metrics */
- /* take care of fixed-pitch fonts... */
- {
- FT_Pos left_bearing;
- FT_Pos advance;
+ *max_advance = decoder.builder.advance.x;
+ return FT_Err_Ok;
+ }
+#endif
- left_bearing = loader->left_bearing;
- advance = loader->advance;
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** UNHINTED GLYPH LOADER *********/
+ /********** *********/
+ /********** The following code is in charge of loading a *********/
+ /********** single outline. It completely ignores hinting *********/
+ /********** and is used when FT_LOAD_NO_HINTING is set. *********/
+ /********** *********/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
- /* the flag FT_LOAD_NO_ADVANCE_CHECK was introduced to */
- /* correctly support DynaLab fonts, who have an incorrect */
- /* "advance_Width_Max" field !! It is used, to my knowledge */
- /* exclusively in the X-TrueType font server.. */
- /* */
- if ( face->postscript.isFixedPitch &&
- (loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH) == 0 )
- advance = face->horizontal.advance_Width_Max;
- if ( !(loader->load_flags & FT_LOAD_NO_SCALE) )
- {
- left_bearing = FT_MulFix( left_bearing, x_scale );
- advance = FT_MulFix( advance, x_scale );
- }
+ LOCAL_FUNC
+ FT_Error T2_Load_Glyph( T2_GlyphSlot glyph,
+ T2_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags )
+ {
+ FT_Error error;
+ T2_Decoder decoder;
+ TT_Face face = (TT_Face)glyph->root.face;
+ FT_Bool hinting;
+ CFF_Font* cff = (CFF_Font*)face->other;
- glyph->metrics2.horiBearingX = left_bearing;
- glyph->metrics2.horiAdvance = advance;
- }
+ if (load_flags & FT_LOAD_NO_RECURSE)
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
- glyph->metrics.horiBearingX = bbox.xMin;
- glyph->metrics.horiBearingY = bbox.yMax;
- glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
+ glyph->x_scale = size->metrics.x_scale;
+ glyph->y_scale = size->metrics.y_scale;
- /* Now take care of vertical metrics. In the case where there is */
- /* no vertical information within the font (relatively common), make */
- /* up some metrics by `hand'... */
+ glyph->root.outline.n_points = 0;
+ glyph->root.outline.n_contours = 0;
- {
- FT_Short top_bearing; /* vertical top side bearing (EM units) */
- FT_UShort advance_height; /* vertical advance height (EM units) */
+ hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
+ ( load_flags & FT_LOAD_NO_HINTING ) == 0;
- FT_Pos left; /* scaled vertical left side bearing */
- FT_Pos Top; /* scaled original vertical top side bearing */
- FT_Pos top; /* scaled vertical top side bearing */
- FT_Pos advance; /* scaled vertical advance height */
+ glyph->root.format = ft_glyph_format_none;
+ {
+ FT_Byte* charstring;
+ FT_ULong charstring_len;
+
+ T2_Init_Decoder( &decoder, face, size, glyph );
- /* Get the unscaled `tsb' and `ah' */
- if ( face->vertical_info &&
- face->vertical.number_Of_VMetrics > 0 )
- {
- /* Don't assume that both the vertical header and vertical */
- /* metrics are present in the same font :-) */
+ decoder.builder.no_recurse = (FT_Bool)!!(load_flags & FT_LOAD_NO_RECURSE);
- T2_Get_Metrics( (TT_HoriHeader*)&face->vertical,
- glyph_index,
- &top_bearing,
- &advance_height );
- }
- else
+ /* now load the unscaled outline */
+ error = T2_Access_Element( &cff->charstrings_index, glyph_index,
+ &charstring, &charstring_len );
+ if (!error)
{
- /* Make up the distances from the horizontal header.. */
-
- /* NOTE: The OS/2 values are the only `portable' ones, */
- /* which is why we use them, when there is an */
- /* OS/2 table in the font. Otherwise, we use the */
- /* values defined in the horizontal header.. */
- /* */
- /* NOTE2: The sTypoDescender is negative, which is why */
- /* we compute the baseline-to-baseline distance */
- /* here with: */
- /* ascender - descender + linegap */
- /* */
- if ( face->os2.version != 0xFFFF )
- {
- top_bearing = face->os2.sTypoLineGap / 2;
- advance_height = (TT_UShort)(face->os2.sTypoAscender -
- face->os2.sTypoDescender +
- face->os2.sTypoLineGap);
- }
- else
- {
- top_bearing = face->horizontal.Line_Gap / 2;
- advance_height = (TT_UShort)(face->horizontal.Ascender +
- face->horizontal.Descender +
- face->horizontal.Line_Gap);
- }
+ error = T2_Parse_CharStrings( &decoder, charstring, charstring_len );
+
+ T2_Forget_Element( &cff->charstrings_index, &charstring );
}
- /* We must adjust the top_bearing value from the bounding box given
- in the glyph header to te bounding box calculated with
- TT_Get_Outline_BBox() */
+ /* save new glyph tables */
+ T2_Done_Builder( &decoder.builder );
+ }
- /* scale the metrics */
- if ( !(loader->load_flags & FT_LOAD_NO_SCALE) )
+ /* Now, set the metrics.. - this is rather simple, as : */
+ /* the left side bearing is the xMin, and the top side */
+ /* bearing the yMax.. */
+ if (!error)
+ {
+ /* for composite glyphs, return only the left side bearing and the */
+ /* advance width.. */
+ if ( load_flags & FT_LOAD_NO_RECURSE )
{
- Top = FT_MulFix( top_bearing, y_scale );
- top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
- - bbox.yMax;
- advance = FT_MulFix( advance_height, y_scale );
+#if 0
+ glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+ glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
+#else
+ glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+ glyph->root.metrics.horiAdvance = decoder.glyph_width;
+#endif
}
else
{
- Top = top_bearing;
- top = top_bearing + loader->bbox.yMax - bbox.yMax;
- advance = advance_height;
- }
+ FT_BBox cbox;
+ FT_Glyph_Metrics* metrics = &glyph->root.metrics;
- glyph->metrics2.vertBearingY = Top;
- glyph->metrics2.vertAdvance = advance;
+ /* copy the _unscaled_ advance width */
+#if 0
+ metrics->horiAdvance = decoder.builder.advance.x;
+#else
+ metrics->horiAdvance = decoder.glyph_width;
+#endif
+ /* make up vertical metrics */
+ metrics->vertBearingX = 0;
+ metrics->vertBearingY = 0;
+ metrics->vertAdvance = 0;
- /* XXX: for now, we have no better algorithm for the lsb, but it */
- /* should work fine. */
- /* */
- left = ( bbox.xMin - bbox.xMax ) / 2;
+ glyph->root.format = ft_glyph_format_outline;
- /* grid-fit them if necessary */
- if ( IS_HINTED(loader->load_flags) )
- {
- left &= -64;
- top = (top + 63) & -64;
- advance = (advance + 32) & -64;
- }
+ glyph->root.outline.flags &= ft_outline_owner;
+ if ( size && size->metrics.y_ppem < 24 )
+ glyph->root.outline.flags |= ft_outline_high_precision;
- glyph->metrics.vertBearingX = left;
- glyph->metrics.vertBearingY = top;
- glyph->metrics.vertAdvance = advance;
- }
+ glyph->root.outline.flags |= ft_outline_reverse_fill;
- /* Adjust advance width to the value contained in the hdmx table. */
- if ( !face->postscript.isFixedPitch && size &&
- IS_HINTED(loader->load_flags) )
- {
- FT_Byte* widths = Get_Advance_Widths( face,
- size->root.metrics.x_ppem );
- if ( widths )
- glyph->metrics.horiAdvance = widths[glyph_index] << 6;
- }
+ /*
+ glyph->root.outline.second_pass = TRUE;
+ glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
+ glyph->root.outline.dropout_mode = 2;
+ */
- /* set glyph dimensions */
- glyph->metrics.width = bbox.xMax - bbox.xMin;
- glyph->metrics.height = bbox.yMax - bbox.yMin;
- }
+ if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
+ {
+ /* scale the outline and the metrics */
+ FT_Int n;
+ FT_Outline* cur = &decoder.builder.base;
+ FT_Vector* vec = cur->points;
+ FT_Fixed x_scale = glyph->x_scale;
+ FT_Fixed y_scale = glyph->y_scale;
+ /* First of all, scale the points */
+ for ( n = cur->n_points; n > 0; n--, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+ /* Then scale the metrics */
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+ metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+ metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale );
+ }
+ /* apply the font matrix */
+ /* FT_Outline_Transform( &glyph->root.outline, cff->font_matrix ); */
+ /* compute the other metrics */
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+ /* grid fit the bounding box if necessary */
+ if (hinting)
+ {
+ cbox.xMin &= -64;
+ cbox.yMin &= -64;
+ cbox.xMax = ( cbox.xMax+63 ) & -64;
+ cbox.yMax = ( cbox.yMax+63 ) & -64;
+ }
+ metrics->width = cbox.xMax - cbox.xMin;
+ metrics->height = cbox.yMax - cbox.yMin;
-
-
-
- LOCAL_FUNC
- FT_Error TT_Load_Glyph( T2_Size size,
- T2_GlyphSlot glyph,
- FT_UShort glyph_index,
- FT_UInt load_flags )
- {
- SFNT_Interface* sfnt;
- T2_Face face;
- FT_Stream stream;
- FT_Memory memory;
- FT_Error error;
- T2_Loader loader;
- FT_GlyphZone* zone;
-
- face = (TT_Face)glyph->face;
- sfnt = (SFNT_Interface*)face->sfnt;
- stream = face->root.stream;
- memory = face->root.memory;
- error = 0;
-
- if ( !size || (load_flags & FT_LOAD_NO_SCALE) ||
- (load_flags & FT_LOAD_NO_RECURSE ))
- {
- size = NULL;
- load_flags |= FT_LOAD_NO_SCALE |
- FT_LOAD_NO_HINTING |
- FT_LOAD_NO_BITMAP;
- }
-
- glyph->num_subglyphs = 0;
-
-#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
- /*********************************************************************/
- /* Try to load embedded bitmap if any */
- if ( size && (load_flags & FT_LOAD_NO_BITMAP) == 0 && sfnt->load_sbits )
- {
- TT_SBit_Metrics metrics;
-
- error = sfnt->load_sbit_image( face,
- size->root.metrics.x_ppem,
- size->root.metrics.y_ppem,
- glyph_index,
- load_flags,
- stream,
- &glyph->bitmap,
- &metrics );
- if ( !error )
- {
- glyph->outline.n_points = 0;
- glyph->outline.n_contours = 0;
-
- glyph->metrics.width = (FT_Pos)metrics.width << 6;
- glyph->metrics.height = (FT_Pos)metrics.height << 6;
-
- glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
- glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
- glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
-
- glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
- glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
- glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
-
- glyph->format = ft_glyph_format_bitmap;
- return error;
+ metrics->horiBearingX = cbox.xMin;
+ metrics->horiBearingY = cbox.yMax;
}
}
-#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
-
- if ( load_flags & FT_LOAD_NO_OUTLINE )
- return ( error ? error : TT_Err_Unavailable_Bitmap );
-
- /* seek to the beginning of the glyph table. For Type 43 fonts */
- /* the table might be accessed from a Postscript stream or something */
- /* else... */
- error = face->goto_table( face, TTAG_glyf, stream, 0 );
- if (error)
- {
- FT_ERROR(( "TT.GLoad: could not access glyph table\n" ));
- goto Exit;
- }
-
- MEM_Set( &loader, 0, sizeof(loader) );
-
- /* update the glyph zone bounds */
- zone = &((TT_Driver)face->root.driver)->zone;
- error = FT_Update_GlyphZone( zone,
- face->root.max_points,
- face->root.max_contours );
- if (error)
- {
- FT_ERROR(( "TT.GLoad: could not update loader glyph zone\n" ));
- goto Exit;
- }
- loader.base = *zone;
-
- loader.zone.n_points = 0;
- loader.zone.n_contours = 0;
-
- /* clear all outline flags, except the "owner" one */
- glyph->outline.flags &= ft_outline_owner;
-
- if (size && size->root.metrics.y_ppem < 24 )
- glyph->outline.flags |= ft_outline_high_precision;
-
- /************************************************************************/
- /* let's initialise the rest of our loader now */
- loader.left_points = face->root.max_points;
- loader.left_contours = face->root.max_contours;
- loader.load_flags = load_flags;
-
- loader.face = face;
- loader.size = size;
- loader.glyph = glyph;
- loader.stream = stream;
-
- loader.glyf_offset = FILE_Pos();
-
- /* Main loading loop */
- glyph->format = ft_glyph_format_outline;
- glyph->num_subglyphs = 0;
- error = load_truetype_glyph( &loader, glyph_index );
- if (!error)
- compute_glyph_metrics( &loader, glyph_index );
-
- Exit:
return error;
}
-
-
/* END */
--- a/src/cff/t2gload.h
+++ b/src/cff/t2gload.h
@@ -25,109 +25,159 @@
extern "C" {
#endif
- typedef struct T2_Loader_
+ #define T2_MAX_OPERANDS 48
+ #define T2_MAX_SUBRS_CALLS 32
+
+/*************************************************************************/
+/* */
+/* <Structure> T2_Builder */
+/* */
+/* <Description> */
+/* a structure used during glyph loading to store its outline. */
+/* */
+/* <Fields> */
+/* system :: current system object */
+/* face :: current face object */
+/* glyph :: current glyph slot */
+/* */
+/* current :: current glyph outline */
+/* base :: base glyph outline */
+/* */
+/* max_points :: maximum points in builder outline */
+/* max_contours :: maximum contours in builder outline */
+/* */
+/* last :: last point position */
+/* */
+/* scale_x :: horizontal scale ( FUnits to sub-pixels ) */
+/* scale_y :: vertical scale ( FUnits to sub-pixels ) */
+/* pos_x :: horizontal translation (composite glyphs) */
+/* pos_y :: vertical translation (composite glyph) */
+/* */
+/* left_bearing :: left side bearing point */
+/* advance :: horizontal advance vector */
+/* */
+/* path_begun :: flag, indicates that a new path has begun */
+/* load_points :: flag, if not set, no points are loaded */
+/* */
+/* 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.. */
+/* */
+
+ typedef struct T2_Builder_
{
- T2_Face face;
- T2_Size size;
- T2_GlyphSlot glyph;
+ FT_Memory memory;
+ TT_Face face;
+ T2_GlyphSlot glyph;
- FT_ULong load_flags;
- FT_UInt glyph_index;
+ FT_Outline current; /* the current glyph outline */
+ FT_Outline base; /* the composite glyph outline */
- FT_Stream stream;
- FT_Int byte_len;
- FT_Int left_points;
- FT_Int left_contours;
+ FT_Int max_points; /* capacity of base outline in points */
+ FT_Int max_contours; /* capacity of base outline in contours */
- FT_BBox bbox;
- FT_Int left_bearing;
- FT_Int advance;
- FT_Bool preserve_pps;
- FT_Vector pp1;
- FT_Vector pp2;
+ FT_Vector last;
- FT_ULong glyf_offset;
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
- /* the zone where we load our glyphs */
- FT_GlyphZone base;
- FT_GlyphZone zone;
+ FT_Pos pos_x;
+ FT_Pos pos_y;
- } T2_Loader;
+ FT_Vector left_bearing;
+ FT_Vector advance;
+ FT_BBox bbox; /* bounding box */
+ FT_Bool path_begun;
+ FT_Bool load_points;
+ FT_Bool no_recurse;
-#if 0
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T2_Get_Metrics */
- /* */
- /* <Description> */
- /* Returns the horizontal or vertical metrics in font units for a */
- /* given glyph. The metrics are the left side bearing (resp. top */
- /* side bearing) and advance width (resp. advance height). */
- /* */
- /* <Input> */
- /* header :: A pointer to either the horizontal or vertical metrics */
- /* structure. */
- /* */
- /* index :: The glyph index. */
- /* */
- /* <Output> */
- /* bearing :: The bearing, either left side or top side. */
- /* */
- /* advance :: The advance width resp. advance height. */
- /* */
- /* <Note> */
- /* This function will much probably move to another component in the */
- /* near future, but I haven't decided which yet. */
- /* */
+ FT_Error error; /* only used for memory errors */
+ FT_Bool metrics_only;
+
+ } T2_Builder;
+
+
+ /* execution context charstring zone */
+ typedef struct T2_Decoder_Zone_
+ {
+ FT_Byte* base;
+ FT_Byte* limit;
+ FT_Byte* cursor;
+
+ } T2_Decoder_Zone;
+
+
+ typedef struct T2_Decoder_
+ {
+ T2_Builder builder;
+ CFF_Font* cff;
+
+ FT_Fixed stack[ T2_MAX_OPERANDS+1 ];
+ FT_Fixed* top;
+
+ T2_Decoder_Zone zones[ T2_MAX_SUBRS_CALLS+1 ];
+ T2_Decoder_Zone* zone;
+
+ FT_Int flex_state;
+ FT_Int num_flex_vectors;
+ FT_Vector flex_vectors[7];
+
+ FT_Pos glyph_width;
+ FT_Pos nominal_width;
+
+ FT_Bool read_width;
+ FT_Int num_hints;
+ FT_Fixed* buildchar;
+ FT_Int len_buildchar;
+
+ FT_UInt num_locals;
+ FT_UInt num_globals;
+
+ FT_Int locals_bias;
+ FT_Int globals_bias;
+
+ FT_Byte** locals;
+ FT_Byte** globals;
+
+
+ } T2_Decoder;
+
+
+
LOCAL_DEF
- void T2_Get_Metrics( TT_HoriHeader* header,
- FT_UInt index,
- FT_Short* bearing,
- FT_UShort* advance );
+ void T2_Init_Decoder( T2_Decoder* decoder,
+ TT_Face face,
+ T2_Size size,
+ T2_GlyphSlot slot );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T2_Load_Glyph */
- /* */
- /* <Description> */
- /* A function used to load a single glyph within a given glyph slot, */
- /* for a given size. */
- /* */
- /* <Input> */
- /* glyph :: A handle to a target slot object where the glyph */
- /* will be loaded. */
- /* */
- /* size :: A handle to the source face size at which the glyph */
- /* must be scaled/loaded. */
- /* */
- /* glyph_index :: The index of the glyph in the font file. */
- /* */
- /* load_flags :: A flag indicating what to load for this glyph. The */
- /* FT_LOAD_XXX constants can be used to control the */
- /* glyph loading process (e.g., whether the outline */
- /* should be scaled, whether to load bitmaps or not, */
- /* whether to hint the outline, etc). */
- /* <Output> */
- /* result :: A set of bit flags indicating the type of data that */
- /* was loaded in the glyph slot (outline or bitmap, */
- /* etc). */
- /* */
- /* You can set this field to 0 if you don't want this */
- /* information. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+#if 0 /* unused until we support pure CFF fonts */
+ /* Compute the maximum advance width of a font through quick parsing */
LOCAL_DEF
- FT_Error T2_Load_Glyph( T2_Size size,
- T2_GlyphSlot glyph,
- FT_UShort glyph_index,
- FT_UInt load_flags );
+ FT_Error T2_Compute_Max_Advance( TT_Face face,
+ FT_Int *max_advance );
#endif
+
+ /* This function is exported, because it is used by the T1Dump utility */
+ LOCAL_DEF
+ FT_Error T2_Parse_CharStrings( T2_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len );
+
+
+
+ LOCAL_DEF
+ FT_Error T2_Load_Glyph( T2_GlyphSlot glyph,
+ T2_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags );
+
+
+
#ifdef __cplusplus
}
--- a/src/cff/t2load.c
+++ b/src/cff/t2load.c
@@ -25,7 +25,7 @@
#include <freetype/tttags.h>
#include <t2load.h>
#include <t2parse.h>
-#include <freetype/internal/t2errors.h>
+#include <t2errors.h>
#undef FT_COMPONENT
#define FT_COMPONENT trace_ttload
@@ -53,6 +53,7 @@
FT_UShort count;
MEM_Set( index, 0, sizeof(*index) );
+ index->stream = stream;
if ( !READ_UShort( count ) &&
count > 0 )
{
@@ -127,7 +128,36 @@
static
- FT_Error t2_access_element( CFF_Index* index,
+ FT_Error t2_explicit_cff_index( CFF_Index* index,
+ FT_Byte** *table )
+ {
+ FT_Error error = 0;
+ FT_Memory memory = index->stream->memory;
+ FT_UInt n, offset, old_offset;
+ FT_Byte** t;
+
+ *table = 0;
+ if ( index->count > 0 && !ALLOC_ARRAY( t, index->count+1, FT_Byte* ) )
+ {
+ old_offset = 1;
+ for ( n = 0; n <= index->count; n++ )
+ {
+ offset = index->offsets[n];
+ if (!offset)
+ offset = old_offset;
+
+ t[n] = index->bytes + offset - 1;
+
+ old_offset = offset;
+ }
+ *table = t;
+ }
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error T2_Access_Element( CFF_Index* index,
FT_UInt element,
FT_Byte* *pbytes,
FT_ULong *pbyte_len )
@@ -187,8 +217,8 @@
}
- static
- void t2_forget_element( CFF_Index* index,
+ LOCAL_FUNC
+ void T2_Forget_Element( CFF_Index* index,
FT_Byte* *pbytes )
{
if (index->bytes == 0)
@@ -199,8 +229,8 @@
}
- static
- FT_String* t2_get_name( CFF_Index* index,
+ LOCAL_FUNC
+ FT_String* T2_Get_Name( CFF_Index* index,
FT_UInt element )
{
FT_Memory memory = index->stream->memory;
@@ -209,7 +239,7 @@
FT_Error error;
FT_String* name = 0;
- error = t2_access_element( index, element, &bytes, &byte_len );
+ error = T2_Access_Element( index, element, &bytes, &byte_len );
if (error) goto Exit;
if ( !ALLOC( name, byte_len+1 ) )
@@ -217,14 +247,14 @@
MEM_Copy( name, bytes, byte_len );
name[byte_len] = 0;
}
- t2_forget_element( index, &bytes );
-
+ T2_Forget_Element( index, &bytes );
+
Exit:
return name;
}
-#if 0
+#if 0 /* unused until we fully support pure-CFF fonts */
LOCAL_FUNC
FT_String* T2_Get_String( CFF_Index* index,
FT_UInt sid,
@@ -232,7 +262,7 @@
{
/* if it's not a standard string, return it */
if ( sid > 390 )
- return t2_get_name( index, sid - 390 );
+ return T2_Get_Name( index, sid - 390 );
/* that's a standard string, fetch a copy from the psnamed module */
{
@@ -318,21 +348,40 @@
FT_Byte* dict;
FT_ULong dict_len;
CFF_Index* index = &font->top_dict_index;
+ CFF_Top_Dict* top = &font->top_dict;
/* parse the top-level font dictionary */
T2_Parser_Init( &parser, T2CODE_TOPDICT, &font->top_dict );
+
+ /* set defaults */
+ memset( top, 0, sizeof(*top) );
+ top->underline_position = -100;
+ top->underline_thickness = 50;
+ top->charstring_type = 2;
+ top->font_matrix.xx = 0x10000;
+ top->font_matrix.yy = 0x10000;
+ top->cid_count = 8720;
- error = t2_access_element( index, face_index, &dict, &dict_len ) ||
+ error = T2_Access_Element( index, face_index, &dict, &dict_len ) ||
T2_Parser_Run( &parser, dict, dict + dict_len );
- t2_forget_element( &font->top_dict_index, &dict );
+ T2_Forget_Element( &font->top_dict_index, &dict );
if (error) goto Exit;
/* parse the private dictionary, if any */
if (font->top_dict.private_offset && font->top_dict.private_size)
{
- T2_Parser_Init( &parser, T2CODE_PRIVATE, &font->private_dict );
+ CFF_Private* priv = &font->private_dict;
+ /* set defaults */
+ priv->blue_shift = 7;
+ priv->blue_fuzz = 1;
+ priv->lenIV = -1;
+ priv->expansion_factor = (FT_Fixed)0.06*0x10000;
+ priv->blue_scale = (FT_Fixed)0.039625*0x10000;
+
+ T2_Parser_Init( &parser, T2CODE_PRIVATE, priv );
+
if ( FILE_Seek( base_offset + font->top_dict.private_offset ) ||
ACCESS_Frame( font->top_dict.private_size ) )
goto Exit;
@@ -357,10 +406,28 @@
error = t2_new_cff_index( &font->charstrings_index, stream, 0 );
if (error) goto Exit;
+
+ /* read the local subrs */
+ if ( FILE_Seek( base_offset + font->top_dict.private_offset +
+ font->private_dict.local_subrs_offset ) )
+ goto Exit;
+
+ error = t2_new_cff_index( &font->local_subrs_index, stream, 1 );
+ if (error) goto Exit;
+
+ /* explicit the global and local subrs */
+ font->num_local_subrs = font->local_subrs_index.count;
+ font->num_global_subrs = font->global_subrs_index.count;
+
+ error = t2_explicit_cff_index( &font->global_subrs_index,
+ &font->global_subrs ) ||
+ t2_explicit_cff_index( &font->local_subrs_index,
+ &font->local_subrs );
+ if (error) goto Exit;
}
/* get the font name */
- font->font_name = t2_get_name( &font->name_index, face_index );
+ font->font_name = T2_Get_Name( &font->name_index, face_index );
Exit:
return error;
@@ -369,11 +436,17 @@
LOCAL_FUNC
void T2_Done_CFF_Font( CFF_Font* font )
{
+ FT_Memory memory = font->memory;
+
t2_done_cff_index( &font->global_subrs_index );
t2_done_cff_index( &font->string_index );
t2_done_cff_index( &font->top_dict_index );
t2_done_cff_index( &font->name_index );
t2_done_cff_index( &font->charstrings_index );
+
+ FREE( font->local_subrs );
+ FREE( font->global_subrs );
+ FREE( font->font_name );
}
--- a/src/cff/t2load.h
+++ b/src/cff/t2load.h
@@ -25,6 +25,28 @@
extern "C" {
#endif
+ LOCAL_FUNC
+ FT_String* T2_Get_Name( CFF_Index* index,
+ FT_UInt element );
+
+#if 0 /* will be used later for pure-CFF font support */
+ LOCAL_DEF
+ FT_String* T2_Get_String( CFF_Index* index,
+ FT_UInt sid,
+ PSNames_Interface* interface );
+#endif
+
+ LOCAL_DEF
+ FT_Error T2_Access_Element( CFF_Index* index,
+ FT_UInt element,
+ FT_Byte* *pbytes,
+ FT_ULong *pbyte_len );
+
+ LOCAL_DEF
+ void T2_Forget_Element( CFF_Index* index,
+ FT_Byte* *pbytes );
+
+
#ifdef __cplusplus
}
#endif
--- a/src/cff/t2objs.c
+++ b/src/cff/t2objs.c
@@ -104,6 +104,7 @@
{
CFF_Font* cff;
FT_Memory memory = face->root.memory;
+ FT_Face root;
if ( ALLOC( cff, sizeof(*cff) ) )
goto Exit;
@@ -110,6 +111,12 @@
face->other = cff;
error = T2_Load_CFF_Font( stream, face_index, cff );
+ if (error) goto Exit;
+
+ /* complement the root flags with some interesting information */
+ /* note that for OpenType/CFF, there is no need to do this, but */
+ /* this will be necessary for pure CFF fonts through.. */
+ root = &face->root;
}
Exit:
@@ -258,17 +265,13 @@
LOCAL_FUNC
FT_Error T2_Init_GlyphSlot( T2_GlyphSlot slot )
{
- /* allocate the outline space */
- FT_Face face = slot->face;
- FT_Library library = face->driver->library;
+ FT_Library library = slot->root.face->driver->library;
- FT_TRACE4(( "TT.Init_GlyphSlot: Creating outline maxp = %d, maxc = %d\n",
- face->max_points, face->max_contours ));
+ slot->max_points = 0;
+ slot->max_contours = 0;
+ slot->root.bitmap.buffer = 0;
- return FT_Outline_New( library,
- face->max_points + 2,
- face->max_contours,
- &slot->outline );
+ return FT_Outline_New( library, 0, 0, &slot->root.outline );
}
@@ -286,13 +289,13 @@
LOCAL_FUNC
void T2_Done_GlyphSlot( T2_GlyphSlot slot )
{
- FT_Library library = slot->face->driver->library;
+ FT_Library library = slot->root.face->driver->library;
FT_Memory memory = library->memory;
- if (slot->flags & ft_glyph_own_bitmap)
- FREE( slot->bitmap.buffer );
+ if (slot->root.flags & ft_glyph_own_bitmap)
+ FREE( slot->root.bitmap.buffer );
- FT_Outline_Done( library, &slot->outline );
+ FT_Outline_Done( library, &slot->root.outline );
return;
}
--- a/src/cff/t2objs.h
+++ b/src/cff/t2objs.h
@@ -65,7 +65,21 @@
/* This is a direct typedef of FT_GlyphSlot, as there is nothing */
/* specific about the OpenType glyph slot. */
/* */
- typedef FT_GlyphSlot T2_GlyphSlot;
+
+ typedef struct T2_GlyphSlotRec_
+ {
+ FT_GlyphSlotRec root;
+
+ FT_Bool hint;
+ FT_Bool scaled;
+
+ FT_Int max_points;
+ FT_Int max_contours;
+
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+
+ } T2_GlyphSlotRec, *T2_GlyphSlot;
--- a/src/cff/t2parse.c
+++ b/src/cff/t2parse.c
@@ -64,7 +64,7 @@
if (v == 28)
{
if ( p+2 > limit ) goto Bad;
- val = ((FT_Long)p[0] << 8) | p[1];
+ val = (FT_Short)(((FT_Int)p[0] << 8) | p[1]);
p += 2;
}
else if (v == 29)
@@ -261,10 +261,10 @@
error = T2_Err_Stack_Underflow;
if (parser->top >= parser->stack + 4)
{
- bbox->xMin = t2_parse_fixed( data++ );
- bbox->yMin = t2_parse_fixed( data++ );
- bbox->xMax = t2_parse_fixed( data++ );
- bbox->yMax = t2_parse_fixed( data );
+ bbox->xMin = t2_parse_num( data++ );
+ bbox->yMin = t2_parse_num( data++ );
+ bbox->xMax = t2_parse_num( data++ );
+ bbox->yMax = t2_parse_num( data );
error = 0;
}
return error;
@@ -281,8 +281,8 @@
error = T2_Err_Stack_Underflow;
if (parser->top >= parser->stack + 2)
{
- dict->private_offset = t2_parse_num( data++ );
- dict->private_size = t2_parse_num( data );
+ dict->private_size = t2_parse_num( data++ );
+ dict->private_offset = t2_parse_num( data );
error = 0;
}
return error;
@@ -319,7 +319,7 @@
#define T2_REF(s,f) (((s*)0)->f)
#define T2_FIELD_CALLBACK( code, name ) \
- { t2_kind_callback, code, 0, 0, parse_ ## name, 0, 0 },
+ { t2_kind_callback, code | T2CODE, 0, 0, parse_ ## name, 0, 0 },
#undef T2_FIELD
#define T2_FIELD( code, name, kind ) \
@@ -363,7 +363,7 @@
while (p < limit)
{
FT_Byte v = *p;
- if ( v >= 27 || v != 31 )
+ if ( v >= 27 && v != 31 )
{
/* its a number, we'll push its position on the stack */
if (parser->top - parser->stack >= T2_MAX_STACK_DEPTH)
@@ -404,6 +404,7 @@
/* first of all, a trivial check */
if ( num_args < 1 ) goto Stack_Underflow;
+ *parser->top = p;
code = v;
if (v == 12)
{
@@ -476,16 +477,14 @@
error = field->reader( parser );
if (error) goto Exit;
}
- /* clear stack */
- parser->top = parser->stack;
+ goto Found;
}
- goto Found; /* exit loop */
}
/* this is an unknown operator, or it is unsupported, we will ignore */
/* it for now... */
-
- Found:
+
+ Found:
/* clear stack */
parser->top = parser->stack;
}