From 0142e6aff1f0836a7ec3902969491ab6ac7182aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wu=2C=20Chia-I=20=28=E5=90=B3=E4=BD=B3=E4=B8=80=29?= Date: Tue, 16 Aug 2005 01:54:59 +0000 Subject: [PATCH] * src/truetype/ttinterp.c, src/truetype/ttinterp.h: Remove original TT_Done_Context and rename TT_Destroy_Context to TT_Done_Context with slight changes. * src/truetype/ttobjs.h (tt_slot_init): New function. * src/truetype/ttobjs.c (tt_driver_init): Initialize execution context here. (tt_slot_init): New function to create extra points for the internal glyph loader. We then use it directly, instead of face's glyph loader, when loading glyph. * src/truetype/ttdriver.c: Use tt_slot_init for glyph slot initialization. (TT_Load_Glyph): Load flag dependencies are handled here. Return error if size is NULL. * src/truetype/ttgload.c: Heavy cleanup and refactor. (TT_Hint_Glyph): New funcion to hint a zone, prepared by caller. (TT_Process_Simple_Glyph): Use loader->pp's instead of recalculating. Use TT_Hint_Glyph. No need to save/restore loader->stream before/after TT_Vary_Get_Glyph_Deltas now. (TT_LOADER_SET_PP): New macro to calculate and set the four phantom points. (TT_Process_Composite_Component, TT_Process_Composite_Glyph, load_truetype_glyph): Refactor load_truetype_glyph into these three functions. Never set exec->glyphSize to 0. (close #13107) Forget glyph frame before calling TT_Process_Simple_Glyph. (TT_Load_Glyph, load_sbit_image, tt_loader_init): Refactor TT_Load_Glyph into these three functions. Set various fields of `glyph' here, instead of in load_truetype_glyph and compute_glyph_metrics. --- ChangeLog | 35 + src/truetype/ttdriver.c | 27 +- src/truetype/ttgload.c | 1370 +++++++++++++++++++-------------------- src/truetype/ttinterp.c | 57 +- src/truetype/ttinterp.h | 7 +- src/truetype/ttobjs.c | 52 +- src/truetype/ttobjs.h | 8 + 7 files changed, 764 insertions(+), 792 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6f8f9bf92..22328c4fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2005-08-16 Chia I Wu + + * src/truetype/ttinterp.c, src/truetype/ttinterp.h: Remove original + TT_Done_Context and rename TT_Destroy_Context to TT_Done_Context with + slight changes. + + * src/truetype/ttobjs.h (tt_slot_init): New function. + + * src/truetype/ttobjs.c (tt_driver_init): Initialize execution context + here. + (tt_slot_init): New function to create extra points for the internal + glyph loader. We then use it directly, instead of face's glyph loader, + when loading glyph. + + * src/truetype/ttdriver.c: Use tt_slot_init for glyph slot + initialization. + (TT_Load_Glyph): Load flag dependencies are handled here. + Return error if size is NULL. + + * src/truetype/ttgload.c: Heavy cleanup and refactor. + (TT_Hint_Glyph): New funcion to hint a zone, prepared by caller. + (TT_Process_Simple_Glyph): Use loader->pp's instead of recalculating. + Use TT_Hint_Glyph. + No need to save/restore loader->stream before/after + TT_Vary_Get_Glyph_Deltas now. + (TT_LOADER_SET_PP): New macro to calculate and set the four phantom points. + (TT_Process_Composite_Component, TT_Process_Composite_Glyph, + load_truetype_glyph): Refactor load_truetype_glyph into these three functions. + Never set exec->glyphSize to 0. (close #13107) + Forget glyph frame before calling TT_Process_Simple_Glyph. + (TT_Load_Glyph, load_sbit_image, tt_loader_init): Refactor TT_Load_Glyph into + these three functions. + Set various fields of `glyph' here, instead of in load_truetype_glyph + and compute_glyph_metrics. + 2005-08-08 Werner Lemberg * docs/INSTALL.ANY: Updated. diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c index 1511e260f..32803f6d4 100644 --- a/src/truetype/ttdriver.c +++ b/src/truetype/ttdriver.c @@ -283,25 +283,14 @@ if ( !slot ) return TT_Err_Invalid_Slot_Handle; - /* check whether we want a scaled outline or bitmap */ - if ( !size ) - load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + if ( !size || !size->ttmetrics.valid ) + return TT_Err_Invalid_Size_Handle; - if ( load_flags & FT_LOAD_NO_SCALE ) - size = NULL; - - /* reset the size object if necessary */ - if ( size ) + if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) ) { - /* these two object must have the same parent */ - if ( size->root.face != slot->face ) - return TT_Err_Invalid_Face_Handle; - - if ( !size->ttmetrics.valid ) - { - if ( FT_SET_ERROR( tt_size_reset( size ) ) ) - return error; - } + load_flags |= FT_LOAD_NO_HINTING | + FT_LOAD_NO_BITMAP | + FT_LOAD_NO_SCALE; } /* now load the glyph outline if necessary */ @@ -409,8 +398,8 @@ tt_face_done, tt_size_init, tt_size_done, - 0, /* FT_Slot_InitFunc */ - 0, /* FT_Slot_DoneFunc */ + tt_slot_init, + 0, /* FT_Slot_DoneFunc */ Set_Char_Sizes, Set_Pixel_Sizes, diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c index 265595881..c3dbcfd74 100644 --- a/src/truetype/ttgload.c +++ b/src/truetype/ttgload.c @@ -312,13 +312,6 @@ } -#define cur_to_org( n, zone ) \ - FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) ) - -#define org_to_cur( n, zone ) \ - FT_ARRAY_COPY( (zone)->cur, (zone)->org, (n) ) - - /*************************************************************************/ /* */ /* Translates an array of coordinates. */ @@ -342,21 +335,6 @@ } - static void - tt_prepare_zone( TT_GlyphZone zone, - FT_GlyphLoad load, - FT_UInt start_point, - FT_UInt start_contour ) - { - zone->n_points = (FT_UShort)( load->outline.n_points - start_point ); - zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour ); - zone->org = load->extra_points + start_point; - zone->cur = load->outline.points + start_point; - zone->tags = (FT_Byte*)load->outline.tags + start_point; - zone->contours = (FT_UShort*)load->outline.contours + start_contour; - } - - #undef IS_HINTED #define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 ) @@ -439,7 +417,6 @@ FT_Int n_contours = load->n_contours; FT_Outline* outline; TT_Face face = (TT_Face)load->face; - TT_GlyphSlot slot = (TT_GlyphSlot)load->glyph; FT_UShort n_ins; FT_Int n, n_points; FT_Int byte_len = load->byte_len; @@ -451,6 +428,11 @@ FT_Short *cont, *cont_limit; + /* check that we can add the contours to the glyph */ + error = FT_GlyphLoader_CheckPoints( gloader, 0, n_contours ); + if ( error ) + goto Fail; + /* reading the contours' endpoints & number of points */ cont = gloader->current.outline.contours; cont_limit = cont + n_contours; @@ -467,6 +449,7 @@ if ( n_contours > 0 ) n_points = cont[-1] + 1; + /* note that we will add four phantom points later */ error = FT_GlyphLoader_CheckPoints( gloader, n_points + 4, 0 ); if ( error ) goto Fail; @@ -479,8 +462,8 @@ goto Invalid_Outline; /* reading the bytecode instructions */ - slot->control_len = 0; - slot->control_data = 0; + load->glyph->control_len = 0; + load->glyph->control_data = 0; n_ins = FT_GET_USHORT(); @@ -503,14 +486,12 @@ #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - if ( ( load->load_flags & - ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 && - load->instructions ) + if ( IS_HINTED( load->load_flags ) ) { - slot->control_len = n_ins; - slot->control_data = load->instructions; + load->glyph->control_len = n_ins; + load->glyph->control_data = load->exec->glyphIns; - FT_MEM_COPY( load->instructions, stream->cursor, (FT_Long)n_ins ); + FT_MEM_COPY( load->exec->glyphIns, stream->cursor, (FT_Long)n_ins ); } #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ @@ -723,6 +704,7 @@ gloader->current.num_subglyphs = num_subglyphs; #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + { /* we must undo the FT_FRAME_ENTER in order to point to the */ /* composite instructions, if we find some. */ @@ -731,6 +713,7 @@ loader->ins_pos = (FT_ULong)( FT_STREAM_POS() + stream->cursor - stream->limit ); } + #endif loader->byte_len = byte_len; @@ -755,6 +738,104 @@ } + static void + tt_prepare_zone( TT_GlyphZone zone, + FT_GlyphLoad load, + FT_UInt start_point, + FT_UInt start_contour ) + { + zone->n_points = (FT_UShort)( load->outline.n_points - start_point ); + zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour ); + zone->org = load->extra_points + start_point; + zone->cur = load->outline.points + start_point; + zone->tags = (FT_Byte*)load->outline.tags + start_point; + zone->contours = (FT_UShort*)load->outline.contours + start_contour; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Hint_Glyph */ + /* */ + /* */ + /* Hint the glyph using the zone prepared by the caller. Note that */ + /* the zone is supposed to include four phantom points. */ + /* */ +#define cur_to_org( n, zone ) \ + FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) ) + static FT_Error + TT_Hint_Glyph( TT_Loader loader, + FT_Bool is_composite ) + { + TT_GlyphZone zone = &loader->zone; + FT_Pos origin; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + FT_UInt n_ins; + + + n_ins = loader->glyph->control_len; + +#endif + + origin = zone->cur[zone->n_points - 4].x; + origin = FT_PIX_ROUND( origin ) - origin; + if ( origin ) + translate_array( zone->n_points, zone->cur, origin, 0 ); + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + /* save original point positioin in org */ + if ( n_ins > 0 ) + cur_to_org( zone->n_points, zone ); + +#endif + + /* round pp2 and pp4 */ + zone->cur[zone->n_points - 3].x = FT_PIX_ROUND( zone->cur[zone->n_points - 3].x ); + zone->cur[zone->n_points - 1].y = FT_PIX_ROUND( zone->cur[zone->n_points - 1].y ); + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + if ( n_ins > 0 ) + { + FT_Bool debug; + FT_Error error; + + + error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph, + loader->exec->glyphIns, n_ins ); + if ( error ) + return error; + + loader->exec->is_composite = is_composite; + loader->exec->pts = *zone; + + debug = !( loader->load_flags & FT_LOAD_NO_SCALE ) && + ( (TT_Size)loader->size )->debug; + + error = TT_Run_Context( loader->exec, debug ); + if ( error && loader->exec->pedantic_hinting ) + return error; + } + +#endif + + /* save glyph phantom points */ + if ( !loader->preserve_pps ) + { + loader->pp1 = zone->cur[zone->n_points - 4]; + loader->pp2 = zone->cur[zone->n_points - 3]; + loader->pp3 = zone->cur[zone->n_points - 2]; + loader->pp4 = zone->cur[zone->n_points - 1]; + } + + return TT_Err_Ok; + } + + /*************************************************************************/ /* */ /* */ @@ -766,95 +847,47 @@ /* interpretation. */ /* */ static FT_Error - TT_Process_Simple_Glyph( TT_Loader load, - FT_Bool debug ) + TT_Process_Simple_Glyph( TT_Loader loader ) { - FT_GlyphLoader gloader = load->gloader; - FT_Outline* outline = &gloader->current.outline; - FT_UInt n_points = outline->n_points; -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - FT_UInt n_ins; -#endif - TT_GlyphZone zone = &load->zone; + FT_GlyphLoader gloader = loader->gloader; FT_Error error = TT_Err_Ok; - - FT_UNUSED( debug ); /* used by truetype interpreter only */ + FT_Outline* outline; + FT_UInt n_points; -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - n_ins = load->glyph->control_len; -#endif + outline = &gloader->current.outline; + n_points = outline->n_points; - /* add shadow points */ + /* set phantom points */ - /* Add two horizontal shadow points at n and n+1. */ - /* We need the left side bearing and advance width. */ - /* Add two vertical shadow points at n+2 and n+3. */ - /* We need the top side bearing and advance height. */ + outline->points[n_points ] = loader->pp1; + outline->points[n_points + 1] = loader->pp2; + outline->points[n_points + 2] = loader->pp3; + outline->points[n_points + 3] = loader->pp4; - { - FT_Vector* pp1; - FT_Vector* pp2; - FT_Vector* pp3; - FT_Vector* pp4; - - - /* pp1 = xMin - lsb */ - pp1 = outline->points + n_points; - pp1->x = load->bbox.xMin - load->left_bearing; - pp1->y = 0; - - /* pp2 = pp1 + aw */ - pp2 = pp1 + 1; - pp2->x = pp1->x + load->advance; - pp2->y = 0; - - /* pp3 = top side bearing */ - pp3 = pp1 + 2; - pp3->x = 0; - pp3->y = load->top_bearing + load->bbox.yMax; - - /* pp4 = pp3 - ah */ - pp4 = pp1 + 3; - pp4->x = 0; - pp4->y = pp3->y - load->vadvance; - - outline->tags[n_points ] = 0; - outline->tags[n_points + 1] = 0; - outline->tags[n_points + 2] = 0; - outline->tags[n_points + 3] = 0; - } - - /* Note that we return four more points that are not */ - /* part of the glyph outline. */ + outline->tags[n_points ] = 0; + outline->tags[n_points + 1] = 0; + outline->tags[n_points + 2] = 0; + outline->tags[n_points + 3] = 0; n_points += 4; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( ((TT_Face)load->face)->doblend ) + if ( ((TT_Face)loader->face)->doblend ) { /* Deltas apply to the unscaled data. */ FT_Vector* deltas; - FT_Memory memory = load->face->memory; - FT_StreamRec saved_stream = *(load->stream); + FT_Memory memory = loader->face->memory; FT_UInt i; - /* TT_Vary_Get_Glyph_Deltas uses a frame, thus we have to save */ - /* (and restore) the current one */ - load->stream->cursor = 0; - load->stream->limit = 0; - - error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(load->face), - load->glyph_index, + error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face), + loader->glyph_index, &deltas, n_points ); - - *(load->stream) = saved_stream; - if ( error ) - goto Exit; + return error; for ( i = 0; i < n_points; ++i ) { @@ -867,84 +900,290 @@ #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - /* set up zone for hinting */ - tt_prepare_zone( zone, &gloader->current, 0, 0 ); - - /* eventually scale the glyph */ - if ( !( load->load_flags & FT_LOAD_NO_SCALE ) ) + /* scale the glyph */ + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) { - FT_Vector* vec = zone->cur; - FT_Vector* limit = vec + n_points; - FT_Fixed x_scale = ((TT_Size)load->size)->metrics.x_scale; - FT_Fixed y_scale = ((TT_Size)load->size)->metrics.y_scale; + FT_Vector* vec = outline->points; + FT_Vector* limit = outline->points + n_points; + FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale; + FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale; + - /* 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 ); } + + loader->pp1 = outline->points[n_points - 4]; + loader->pp2 = outline->points[n_points - 3]; + loader->pp3 = outline->points[n_points - 2]; + loader->pp4 = outline->points[n_points - 1]; } - cur_to_org( n_points, zone ); - - /* eventually hint the glyph */ - if ( IS_HINTED( load->load_flags ) ) + if ( IS_HINTED( loader->load_flags ) ) { - FT_Pos x = zone->org[n_points-4].x; - - - x = FT_PIX_ROUND( x ) - x; - translate_array( n_points, zone->org, x, 0 ); - - org_to_cur( n_points, zone ); - - zone->cur[n_points - 3].x = FT_PIX_ROUND( zone->cur[n_points - 3].x ); - zone->cur[n_points - 1].y = FT_PIX_ROUND( zone->cur[n_points - 1].y ); - -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - - /* now consider hinting */ - if ( n_ins > 0 ) - { - error = TT_Set_CodeRange( load->exec, tt_coderange_glyph, - load->exec->glyphIns, n_ins ); - if ( error ) - goto Exit; - - load->exec->is_composite = FALSE; - load->exec->pts = *zone; - load->exec->pts.n_points += 4; - - error = TT_Run_Context( load->exec, debug ); - if ( error && load->exec->pedantic_hinting ) - goto Exit; - - error = TT_Err_Ok; /* ignore bytecode errors in non-pedantic mode */ - } - -#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 ); + loader->zone.n_points += 4; + error = TT_Hint_Glyph( loader, 0 ); } - /* save glyph phantom points */ - if ( !load->preserve_pps ) - { - load->pp1 = zone->cur[n_points - 4]; - load->pp2 = zone->cur[n_points - 3]; - load->pp3 = zone->cur[n_points - 2]; - load->pp4 = zone->cur[n_points - 1]; - } - -#if defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) || \ - defined( TT_CONFIG_OPTION_GX_VAR_SUPPORT ) - Exit: -#endif - return error; } + /*************************************************************************/ + /* */ + /* */ + /* TT_Process_Composite_Component */ + /* */ + /* */ + /* Once a composite component has been loaded, it needs to be */ + /* processed. Usually, this means transforming and translating. */ + /* */ + static FT_Error + TT_Process_Composite_Component( TT_Loader loader, + FT_SubGlyph subglyph, + FT_UInt start_point, + FT_UInt num_base_points ) + { + FT_GlyphLoader gloader = loader->gloader; + FT_Vector* base_vec = gloader->base.outline.points; + FT_UInt num_points = gloader->base.outline.n_points; + FT_Bool have_scale; + FT_Pos x, y; + + + have_scale = ( subglyph->flags & ( WE_HAVE_A_SCALE | + WE_HAVE_AN_XY_SCALE | + WE_HAVE_A_2X2 ) ); + + /* perform the transform required for this subglyph */ + if ( have_scale ) + { + FT_UInt i; + + + for ( i = num_base_points; i < num_points; i++ ) + FT_Vector_Transform( base_vec + i, &subglyph->transform ); + } + + /* get offset */ + if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) + { + FT_UInt k = subglyph->arg1; + FT_UInt l = subglyph->arg2; + FT_Vector* p1; + FT_Vector* p2; + + + /* match l-th point of the newly loaded component to the k-th point of */ + /* the previously loaded components. */ + + /* change to the point numbers used by our outline */ + k += start_point; + l += num_base_points; + if ( k >= (FT_UInt)num_base_points || + l >= (FT_UInt)num_points ) + { + return TT_Err_Invalid_Composite; + } + + p1 = gloader->base.outline.points + k; + p2 = gloader->base.outline.points + l; + + x = p1->x - p2->x; + y = p1->y - p2->y; + } + else + { + x = subglyph->arg1; + y = subglyph->arg2; + + if ( !x && !y ) + return TT_Err_Ok; + +/* Use a default value dependent on */ +/* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */ +/* fonts which don't set the xxx_COMPONENT_OFFSET bit. */ + + if ( have_scale && +#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED + !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) ) +#else + ( subglyph->flags & SCALED_COMPONENT_OFFSET ) ) +#endif + { +#if 0 + +/*************************************************************************/ +/* */ +/* This algorithm is what Apple documents. But it doesn't work. */ +/* */ + int a = subglyph->transform.xx > 0 ? subglyph->transform.xx + : -subglyph->transform.xx; + int b = subglyph->transform.yx > 0 ? subglyph->transform.yx + : -subglyph->transform.yx; + int c = subglyph->transform.xy > 0 ? subglyph->transform.xy + : -subglyph->transform.xy; + int d = subglyph->transform.yy > 0 ? subglyph->transform.yy + : -subglyph->transform.yy; + int m = a > b ? a : b; + int n = c > d ? c : d; + + + if ( a - b <= 33 && a - b >= -33 ) + m *= 2; + if ( c - d <= 33 && c - d >= -33 ) + n *= 2; + x = FT_MulFix( x, m ); + y = FT_MulFix( y, n ); + +#else /* 0 */ + +/*************************************************************************/ +/* */ +/* This algorithm is a guess and works much better than the above. */ +/* */ + FT_Fixed mac_xscale = FT_SqrtFixed( + FT_MulFix( subglyph->transform.xx, + subglyph->transform.xx ) + + FT_MulFix( subglyph->transform.xy, + subglyph->transform.xy) ); + FT_Fixed mac_yscale = FT_SqrtFixed( + FT_MulFix( subglyph->transform.yy, + subglyph->transform.yy ) + + FT_MulFix( subglyph->transform.yx, + subglyph->transform.yx ) ); + + + x = FT_MulFix( x, mac_xscale ); + y = FT_MulFix( y, mac_yscale ); + +#endif /* 0 */ + + } + + if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) + { + FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale; + FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale; + + + x = FT_MulFix( x, x_scale ); + y = FT_MulFix( y, y_scale ); + + if ( subglyph->flags & ROUND_XY_TO_GRID ) + { + x = FT_PIX_ROUND( x ); + y = FT_PIX_ROUND( y ); + } + } + } + + if ( x || y ) + translate_array( num_points - num_base_points, + base_vec + num_base_points, + x, y ); + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Process_Composite_Glyph */ + /* */ + /* */ + /* This is slightly different from TT_Process_Simple_Glyph, in that */ + /* it's sole purpose is to hint the glyph. Thus this function is */ + /* only available when bytecode interpreter is enabled. */ + /* */ + static FT_Error + TT_Process_Composite_Glyph( TT_Loader loader, + FT_UInt start_point, + FT_UInt start_contour ) + { + FT_Error error; + FT_Outline* outline; + + + outline = &loader->gloader->base.outline; + + /* make room for phantom points */ + error = FT_GlyphLoader_CheckPoints( loader->gloader, outline->n_points + 4, 0 ); + if ( error ) + return error; + + outline->points[outline->n_points ] = loader->pp1; + outline->points[outline->n_points + 1] = loader->pp2; + outline->points[outline->n_points + 2] = loader->pp3; + outline->points[outline->n_points + 3] = loader->pp4; + + outline->tags[outline->n_points ] = 0; + outline->tags[outline->n_points + 1] = 0; + outline->tags[outline->n_points + 2] = 0; + outline->tags[outline->n_points + 3] = 0; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + { + FT_Stream stream = loader->stream; + FT_UShort n_ins; + + + /* TT_Load_Composite_Glyph only gives us the offset of instructions */ + /* so we read them here */ + if ( FT_STREAM_SEEK( loader->ins_pos ) || + FT_READ_USHORT( n_ins ) ) + return error; + + FT_TRACE5(( " Instructions size = %d\n", n_ins )); + + /* check it */ + if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions ) + { + FT_TRACE0(( "Too many instructions (%d)\n", n_ins )); + + return TT_Err_Too_Many_Hints; + } + else if ( n_ins == 0 ) + return TT_Err_Ok; + + if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) ) + return error; + + loader->glyph->control_data = loader->exec->glyphIns; + loader->glyph->control_len = n_ins; + } + +#endif + + tt_prepare_zone( &loader->zone, &loader->gloader->base, start_point, start_contour ); + loader->zone.n_points += 4; + + return TT_Hint_Glyph( loader, 1 ); + } + + + /* Calculate the four phantom points. */ + /* The first two stand for horizontal origin and advance. */ + /* The last two stand for vertical origin and advance. */ +#define TT_LOADER_SET_PP( loader ) \ + do { \ + (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; \ + (loader)->pp3.x = 0; \ + (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \ + (loader)->pp4.x = 0; \ + (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \ + } while ( 0 ) + + /*************************************************************************/ /* */ /* */ @@ -959,28 +1198,25 @@ FT_UInt glyph_index, FT_UInt recurse_count ) { - -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - FT_Stream stream = loader->stream; -#endif - FT_Error error; - TT_Face face = (TT_Face)loader->face; - FT_ULong offset; - FT_Int contours_count; - FT_UInt num_points, count; FT_Fixed x_scale, y_scale; - FT_GlyphLoader gloader = loader->gloader; + FT_ULong offset; + TT_Face face = (TT_Face)loader->face; + FT_GlyphLoader gloader = loader->gloader; FT_Bool opened_frame = 0; +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + FT_Vector* deltas = NULL; + +#endif + #ifdef FT_CONFIG_OPTION_INCREMENTAL + FT_StreamRec inc_stream; FT_Data glyph_data; FT_Bool glyph_data_loaded = 0; -#endif -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_Vector *deltas; #endif @@ -998,15 +1234,17 @@ } loader->glyph_index = glyph_index; - num_points = 0; - x_scale = 0x10000L; - y_scale = 0x10000L; if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) { x_scale = ((TT_Size)loader->size)->metrics.x_scale; y_scale = ((TT_Size)loader->size)->metrics.y_scale; } + else + { + x_scale = 0x10000L; + y_scale = 0x10000L; + } /* get metrics, horizontal and vertical */ { @@ -1045,16 +1283,9 @@ goto Exit; left_bearing = (FT_Short)metrics.bearing_x; advance_width = (FT_UShort)metrics.advance; - } - # if 0 + /* GWW: Do I do the same for vertical metrics ??? */ - if ( face->root.internal->incremental_interface && - face->root.internal->incremental_interface->funcs->get_glyph_metrics ) - { - FT_Incremental_MetricsRec metrics; - - metrics.bearing_x = 0; metrics.bearing_y = top_bearing; metrics.advance = advance_height; @@ -1065,9 +1296,11 @@ goto Exit; top_bearing = (FT_Short)metrics.bearing_y; advance_height = (FT_UShort)metrics.advance; - } + # endif + } + #endif /* FT_CONFIG_OPTION_INCREMENTAL */ loader->left_bearing = left_bearing; @@ -1082,16 +1315,15 @@ } } + /* Set `offset' to the start of the glyph relative to the start of */ + /* the 'glyf' table, and `byte_len' to the length of the glyph in */ + /* bytes. */ + #ifdef FT_CONFIG_OPTION_INCREMENTAL - /* Set `offset' to the start of the glyph program relative to the */ - /* start of the 'glyf' table, and `count' to the length of the */ - /* glyph program in bytes. */ - /* */ /* If we are loading glyph data via the incremental interface, set */ /* the loader stream to a memory stream reading the data returned */ /* by the interface. */ - if ( face->root.internal->incremental_interface ) { error = face->root.internal->incremental_interface->funcs->get_glyph_data( @@ -1102,7 +1334,7 @@ glyph_data_loaded = 1; offset = 0; - count = glyph_data.length; + byte_len = glyph_data.length; FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) ); FT_Stream_OpenMemory( &inc_stream, @@ -1114,23 +1346,21 @@ #endif /* FT_CONFIG_OPTION_INCREMENTAL */ - offset = tt_face_get_location( face, glyph_index, &count ); + offset = tt_face_get_location( face, glyph_index, (FT_UInt*)&loader->byte_len ); - if ( count == 0 ) + if ( loader->byte_len == 0 ) { - /* as described by Frederic Loyer, these are spaces, and */ - /* not the unknown glyph. */ + /* as described by Frederic Loyer, these are spaces or */ + /* the unknown glyph. */ loader->bbox.xMin = 0; loader->bbox.xMax = 0; loader->bbox.yMin = 0; loader->bbox.yMax = 0; - loader->pp1.x = 0; - loader->pp2.x = loader->advance; - loader->pp3.y = 0; - loader->pp4.y = loader->pp3.y-loader->vadvance; + TT_LOADER_SET_PP( loader ); #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( ((TT_Face)(loader->face))->doblend ) { /* this must be done before scaling */ @@ -1149,31 +1379,24 @@ FT_FREE( deltas ); } + #endif 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 ); + loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); } -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - - if ( loader->exec ) - loader->exec->glyphSize = 0; - -#endif - error = TT_Err_Ok; goto Exit; } - loader->byte_len = (FT_Int)count; - - offset = loader->glyf_offset + offset; - - /* access glyph frame */ - error = face->access_glyph_frame( loader, glyph_index, offset, count ); + error = face->access_glyph_frame( loader, glyph_index, + loader->glyf_offset + offset, + loader->byte_len ); if ( error ) goto Exit; @@ -1182,21 +1405,9 @@ /* read first glyph header */ error = face->read_glyph_header( loader ); if ( error ) - goto Fail; + goto Exit; - contours_count = loader->n_contours; - - count -= 10; - - 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; - - loader->pp3.x = 0; - loader->pp3.y = loader->top_bearing + loader->bbox.yMax; - loader->pp4.x = 0; - loader->pp4.y = loader->pp3.y - loader->vadvance; + TT_LOADER_SET_PP( loader ); /***********************************************************************/ /***********************************************************************/ @@ -1204,40 +1415,21 @@ /* if it is a simple glyph, load it */ - if ( contours_count >= 0 ) + if ( loader->n_contours >= 0 ) { - /* check that we can add the contours to the glyph */ - error = FT_GlyphLoader_CheckPoints( gloader, 0, contours_count ); - if ( error ) - goto Fail; - error = face->read_simple_glyph( loader ); if ( error ) - goto Fail; + goto Exit; -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - - { - TT_Size size = (TT_Size)loader->size; - - - error = TT_Process_Simple_Glyph( loader, - (FT_Bool)( size && size->debug ) ); - } - -#else - - error = TT_Process_Simple_Glyph( loader, 0 ); - -#endif + /* all data have been read */ + face->forget_glyph_frame( loader ); + opened_frame = 0; + error = TT_Process_Simple_Glyph( loader ); if ( error ) - goto Fail; + goto Exit; FT_GlyphLoader_Add( gloader ); - - /* Note: We could have put the simple loader source there */ - /* but the code is fat enough already :-) */ } /***********************************************************************/ @@ -1245,29 +1437,25 @@ /***********************************************************************/ /* otherwise, load a composite! */ - else if ( contours_count == -1 ) + else if ( loader->n_contours == -1 ) { - TT_GlyphSlot glyph = (TT_GlyphSlot)loader->glyph; FT_UInt start_point; -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER FT_UInt start_contour; FT_ULong ins_pos; /* position of composite instructions, if any */ -#endif + start_point = gloader->base.outline.n_points; + start_contour = gloader->base.outline.n_contours; + /* for each subglyph, read composite header */ - start_point = gloader->base.outline.n_points; -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - start_contour = gloader->base.outline.n_contours; -#endif - error = face->read_composite_glyph( loader ); if ( error ) - goto Fail; + goto Exit; -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + /* store the offset of instructions */ ins_pos = loader->ins_pos; -#endif + + /* all data we need are read */ face->forget_glyph_frame( loader ); opened_frame = 0; @@ -1290,7 +1478,6 @@ gloader->current.num_subglyphs + 4 )) != 0 ) goto Exit; - /* Note: No subglyph reallocation here, our pointers are stable. */ subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs; limit = gloader->current.num_subglyphs; @@ -1327,12 +1514,8 @@ /* */ if ( loader->load_flags & FT_LOAD_NO_RECURSE ) { - /* set up remaining glyph fields */ FT_GlyphLoader_Add( gloader ); - - glyph->num_subglyphs = gloader->base.num_subglyphs; - glyph->format = FT_GLYPH_FORMAT_COMPOSITE; - glyph->subglyphs = gloader->base.subglyphs; + loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE; goto Exit; } @@ -1341,21 +1524,21 @@ /*********************************************************************/ /*********************************************************************/ - /* Now, read each subglyph independently. */ { - FT_Int n, num_base_points, num_new_points; + FT_Int n, num_base_points; FT_SubGlyph subglyph = 0; + FT_UInt num_points = start_point; FT_UInt num_subglyphs = gloader->current.num_subglyphs; FT_UInt num_base_subgs = gloader->base.num_subglyphs; FT_GlyphLoader_Add( gloader ); + /* read each subglyph independently */ for ( n = 0; n < (FT_Int)num_subglyphs; n++ ) { - FT_Vector pp1, pp2, pp3, pp4; - FT_Pos x, y; + FT_Vector pp[4]; /* Each time we call load_truetype_glyph in this loop, the */ @@ -1364,316 +1547,83 @@ /* pointer on each iteration. */ subglyph = gloader->base.subglyphs + num_base_subgs + n; - pp1 = loader->pp1; - pp2 = loader->pp2; - pp3 = loader->pp3; - pp4 = loader->pp4; + pp[0] = loader->pp1; + pp[1] = loader->pp2; + pp[2] = loader->pp3; + pp[3] = loader->pp4; num_base_points = gloader->base.outline.n_points; error = load_truetype_glyph( loader, subglyph->index, recurse_count + 1 ); if ( error ) - goto Fail; + goto Exit; /* restore subglyph pointer */ subglyph = gloader->base.subglyphs + num_base_subgs + n; - if ( subglyph->flags & USE_MY_METRICS ) + if ( !( subglyph->flags & USE_MY_METRICS ) ) { - pp1 = loader->pp1; - pp2 = loader->pp2; - pp3 = loader->pp3; - pp4 = loader->pp4; - } - else - { - loader->pp1 = pp1; - loader->pp2 = pp2; - loader->pp3 = pp3; - loader->pp4 = pp4; + loader->pp1 = pp[0]; + loader->pp2 = pp[1]; + loader->pp3 = pp[2]; + loader->pp4 = pp[3]; } num_points = gloader->base.outline.n_points; - num_new_points = num_points - num_base_points; + if ( num_points == num_base_points ) + continue; - /* 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 = gloader->base.outline.points + - num_base_points; - FT_Vector* org = gloader->base.extra_points + - num_base_points; - FT_Vector* limit = cur + num_new_points; - - - for ( ; cur < limit; cur++, org++ ) - { - FT_Vector_Transform( cur, &subglyph->transform ); - FT_Vector_Transform( org, &subglyph->transform ); - } - } - - /* apply offset */ - - if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) - { - FT_UInt k = subglyph->arg1; - FT_UInt l = subglyph->arg2; - FT_Vector* p1; - FT_Vector* p2; - - - if ( start_point + k >= (FT_UInt)num_base_points || - l >= (FT_UInt)num_new_points ) - { - error = TT_Err_Invalid_Composite; - goto Fail; - } - - l += num_base_points; - - p1 = gloader->base.outline.points + start_point + k; - p2 = gloader->base.outline.points + start_point + l; - - x = p1->x - p2->x; - y = p1->y - p2->y; - } - else - { - x = subglyph->arg1; - y = subglyph->arg2; - - /* Use a default value dependent on */ - /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */ - /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */ - -#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED - if ( !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) && -#else - if ( ( subglyph->flags & SCALED_COMPONENT_OFFSET ) && -#endif - ( subglyph->flags & ( WE_HAVE_A_SCALE | - WE_HAVE_AN_XY_SCALE | - WE_HAVE_A_2X2 )) ) - { -#if 0 - - /*************************************************************************/ - /* */ - /* This algorithm is what Apple documents. But it doesn't work. */ - /* */ - int a = subglyph->transform.xx > 0 ? subglyph->transform.xx - : -subglyph->transform.xx; - int b = subglyph->transform.yx > 0 ? subglyph->transform.yx - : -subglyph->transform.yx; - int c = subglyph->transform.xy > 0 ? subglyph->transform.xy - : -subglyph->transform.xy; - int d = subglyph->transform.yy > 0 ? subglyph->transform.yy - : -subglyph->transform.yy; - int m = a > b ? a : b; - int n = c > d ? c : d; - - - if ( a - b <= 33 && a - b >= -33 ) - m *= 2; - if ( c - d <= 33 && c - d >= -33 ) - n *= 2; - x = FT_MulFix( x, m ); - y = FT_MulFix( y, n ); - -#else /* 0 */ - - /*************************************************************************/ - /* */ - /* This algorithm is a guess and works much better than the above. */ - /* */ - FT_Fixed mac_xscale = FT_SqrtFixed( - FT_MulFix( subglyph->transform.xx, - subglyph->transform.xx ) + - FT_MulFix( subglyph->transform.xy, - subglyph->transform.xy) ); - FT_Fixed mac_yscale = FT_SqrtFixed( - FT_MulFix( subglyph->transform.yy, - subglyph->transform.yy ) + - FT_MulFix( subglyph->transform.yx, - subglyph->transform.yx ) ); - - - x = FT_MulFix( x, mac_xscale ); - y = FT_MulFix( y, mac_yscale ); -#endif /* 0 */ - - } - - if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) - { - x = FT_MulFix( x, x_scale ); - y = FT_MulFix( y, y_scale ); - - if ( subglyph->flags & ROUND_XY_TO_GRID ) - { - x = FT_PIX_ROUND( x ); - y = FT_PIX_ROUND( y ); - } - } - } - - if ( x || y ) - { - translate_array( num_new_points, - gloader->base.outline.points + num_base_points, - x, y ); - - translate_array( num_new_points, - gloader->base.extra_points + num_base_points, - x, y ); - } + /* gloader->base.outline consists of three part: */ + /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */ + /* */ + /* (1): exist from the beginning */ + /* (2): components that have been loaded so far */ + /* (3): the newly loaded component */ + TT_Process_Composite_Component( loader, subglyph, start_point, + num_base_points ); } - /*******************************************************************/ - /*******************************************************************/ - /*******************************************************************/ - /* we have finished loading all sub-glyphs; now, look for */ - /* instructions for this composite! */ + /* process the glyph */ + loader->ins_pos = ins_pos; + if ( IS_HINTED( loader->load_flags ) && #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - if ( num_subglyphs > 0 && - loader->exec && - ins_pos > 0 && - subglyph->flags & WE_HAVE_INSTR ) - { - FT_UShort n_ins; - TT_ExecContext exec = loader->exec; - TT_GlyphZone pts; - FT_Vector* pp1; + subglyph->flags & WE_HAVE_INSTR && +#endif - /* read size of instructions */ - if ( FT_STREAM_SEEK( ins_pos ) || - FT_READ_USHORT( n_ins ) ) - goto Fail; - FT_TRACE5(( " Instructions size = %d\n", n_ins )); - - /* in some fonts? */ - if ( n_ins == 0xFFFFU ) - n_ins = 0; - - /* check it */ - if ( n_ins > face->max_profile.maxSizeOfInstructions ) - { - FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n", - n_ins, subglyph->index )); - error = TT_Err_Too_Many_Hints; - goto Fail; - } - - /* read the instructions */ - if ( FT_STREAM_READ( exec->glyphIns, n_ins ) ) - goto Fail; - - glyph->control_data = exec->glyphIns; - glyph->control_len = n_ins; - - error = TT_Set_CodeRange( exec, - tt_coderange_glyph, - exec->glyphIns, - n_ins ); - if ( error ) - goto Fail; - - error = FT_GlyphLoader_CheckPoints( gloader, num_points + 4, 0 ); - if ( error ) - goto Fail; - - /* prepare the execution context */ - tt_prepare_zone( &exec->pts, &gloader->base, - start_point, start_contour ); - pts = &exec->pts; - - pts->n_points = (short)( num_points + 4 ); - pts->n_contours = gloader->base.outline.n_contours; - - /* add phantom points */ - pp1 = pts->cur + num_points; - pp1[0] = loader->pp1; - pp1[1] = loader->pp2; - pp1[2] = loader->pp3; - pp1[3] = loader->pp4; - - pts->tags[num_points ] = 0; - pts->tags[num_points + 1] = 0; - pts->tags[num_points + 2] = 0; - pts->tags[num_points + 3] = 0; - - /* if hinting, round the phantom points */ - if ( IS_HINTED( loader->load_flags ) ) - { - pp1[0].x = FT_PIX_ROUND( loader->pp1.x ); - pp1[1].x = FT_PIX_ROUND( loader->pp2.x ); - pp1[2].y = FT_PIX_ROUND( loader->pp3.y ); - pp1[3].y = FT_PIX_ROUND( loader->pp4.y ); - } - - { - FT_UInt k; - - - for ( k = 0; k < num_points; k++ ) - pts->tags[k] &= FT_CURVE_TAG_ON; - } - - cur_to_org( num_points + 4, pts ); - - /* now consider hinting */ - if ( IS_HINTED( loader->load_flags ) && n_ins > 0 ) - { - exec->is_composite = TRUE; - error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug ); - if ( error && exec->pedantic_hinting ) - goto Fail; - } - - /* save glyph origin and advance points */ - loader->pp1 = pp1[0]; - loader->pp2 = pp1[1]; - loader->pp3 = pp1[2]; - loader->pp4 = pp1[3]; - } - -#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + num_points > start_point ) + TT_Process_Composite_Glyph( loader, start_point, start_contour ); } - /* end of composite loading */ } else { /* invalid composite count ( negative but not -1 ) */ error = TT_Err_Invalid_Outline; - goto Fail; + goto Exit; } /***********************************************************************/ /***********************************************************************/ /***********************************************************************/ - Fail: + Exit: + if ( opened_frame ) face->forget_glyph_frame( loader ); - Exit: - #ifdef FT_CONFIG_OPTION_INCREMENTAL + if ( glyph_data_loaded ) face->root.internal->incremental_interface->funcs->free_glyph_data( face->root.internal->incremental_interface->object, &glyph_data ); + #endif return error; @@ -1696,18 +1646,7 @@ y_scale = size->root.metrics.y_scale; if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE ) - { - glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS; - - /* copy outline to our glyph slot */ - FT_GlyphLoader_CopyPoints( glyph->internal->loader, loader->gloader ); - glyph->outline = glyph->internal->loader->base.outline; - - /* translate array so that (0,0) is the glyph's origin */ - FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 ); - FT_Outline_Get_CBox( &glyph->outline, &bbox ); - } else bbox = loader->bbox; @@ -1852,7 +1791,7 @@ } /* adjust advance width to the value contained in the hdmx table */ - if ( !face->postscript.isFixedPitch && size && + if ( !face->postscript.isFixedPitch && IS_HINTED( loader->load_flags ) ) { FT_Byte* widthp = Get_Advance_WidthPtr( face, @@ -1875,6 +1814,153 @@ } +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + static FT_Error + load_sbit_image( TT_Size size, + TT_GlyphSlot glyph, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + TT_Face face; + SFNT_Service sfnt; + FT_Stream stream; + FT_Error error; + TT_SBit_MetricsRec metrics; + + face = (TT_Face)glyph->face; + sfnt = (SFNT_Service)face->sfnt; + stream = face->root.stream; + + error = sfnt->load_sbit_image( face, + (FT_ULong)size->strike_index, + glyph_index, + (FT_Int)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; + if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + { + glyph->bitmap_left = metrics.vertBearingX; + glyph->bitmap_top = metrics.vertBearingY; + } + else + { + glyph->bitmap_left = metrics.horiBearingX; + glyph->bitmap_top = metrics.horiBearingY; + } + } + + return error; + } +#endif + + + static FT_Error + tt_loader_init( TT_Loader loader, + TT_Size size, + TT_GlyphSlot glyph, + FT_Int32 load_flags ) + { + TT_Face face; + FT_Stream stream; + + + face = (TT_Face)glyph->face; + stream = face->root.stream; + + FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) ); + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + /* load execution context */ + { + TT_ExecContext exec; + + + /* query new execution context */ + exec = size->debug ? size->context + : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; + if ( !exec ) + return TT_Err_Could_Not_Find_Context; + + TT_Load_Context( exec, face, size ); + + /* see if the cvt program has disabled hinting */ + if ( exec->GS.instruct_control & 1 ) + load_flags |= FT_LOAD_NO_HINTING; + + /* load default graphics state - if needed */ + if ( exec->GS.instruct_control & 2 ) + exec->GS = tt_default_graphics_state; + + exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); + exec->grayscale = + FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_LOAD_TARGET_MONO ); + + loader->exec = exec; + loader->instructions = exec->glyphIns; + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + /* seek to the beginning of the glyph table. For Type 42 fonts */ + /* the table might be accessed from a Postscript stream or something */ + /* else... */ + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + if ( face->root.internal->incremental_interface ) + loader->glyf_offset = 0; + else + +#endif + + { + FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 ); + if ( error ) + { + FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" )); + return error; + } + loader->glyf_offset = FT_STREAM_POS(); + } + + /* get face's glyph loader */ + { + FT_GlyphLoader gloader = glyph->internal->loader; + + FT_GlyphLoader_Rewind( gloader ); + loader->gloader = gloader; + } + + loader->load_flags = load_flags; + + loader->face = (FT_Face)face; + loader->size = (FT_Size)size; + loader->glyph = (FT_GlyphSlot)glyph; + loader->stream = stream; + + return TT_Err_Ok; + } + + /*************************************************************************/ /* */ /* */ @@ -1908,7 +1994,6 @@ FT_UInt glyph_index, FT_Int32 load_flags ) { - SFNT_Service sfnt; TT_Face face; FT_Stream stream; FT_Error error; @@ -1916,194 +2001,65 @@ face = (TT_Face)glyph->face; - sfnt = (SFNT_Service)face->sfnt; stream = face->root.stream; error = TT_Err_Ok; - 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 */ /* */ /* XXX: The convention should be emphasized in */ /* the documents because it can be confusing. */ - if ( size && - size->strike_index != 0xFFFFU && - sfnt->load_sbits && + if ( size->strike_index != 0xFFFFU && ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) - { - TT_SBit_MetricsRec metrics; - - - error = sfnt->load_sbit_image( face, - (FT_ULong)size->strike_index, - glyph_index, - (FT_Int)load_flags, - stream, - &glyph->bitmap, - &metrics ); + error = load_sbit_image( size, glyph, glyph_index, load_flags ); 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; - if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) - { - glyph->bitmap_left = metrics.vertBearingX; - glyph->bitmap_top = metrics.vertBearingY; - } - else - { - glyph->bitmap_left = metrics.horiBearingX; - glyph->bitmap_top = metrics.horiBearingY; - } - return error; - } + return TT_Err_Ok; } #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - /* return immediately if we only want the embedded bitmaps */ if ( load_flags & FT_LOAD_SBITS_ONLY ) return TT_Err_Invalid_Argument; - /* seek to the beginning of the glyph table. For Type 42 fonts */ - /* the table might be accessed from a Postscript stream or something */ - /* else... */ + error = tt_loader_init( &loader, size, glyph, load_flags ); + if ( error ) + return error; -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - /* Don't look for the glyph table if this is an incremental font. */ - if ( !face->root.internal->incremental_interface ) - -#endif - - { - error = face->goto_table( face, TTAG_glyf, stream, 0 ); - if ( error ) - { - FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" )); - goto Exit; - } - } - - FT_MEM_ZERO( &loader, sizeof ( loader ) ); - - /* update the glyph zone bounds */ - { - FT_GlyphLoader gloader = FT_FACE_DRIVER( face )->glyph_loader; - - - loader.gloader = gloader; - - FT_GlyphLoader_Rewind( gloader ); - - tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 ); - tt_prepare_zone( &loader.base, &gloader->base, 0, 0 ); - } - -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - - if ( size ) - { - /* query new execution context */ - loader.exec = size->debug ? size->context : TT_New_Context( face ); - if ( !loader.exec ) - return TT_Err_Could_Not_Find_Context; - - TT_Load_Context( loader.exec, face, size ); - loader.instructions = loader.exec->glyphIns; - - /* load default graphics state - if needed */ - if ( size->GS.instruct_control & 2 ) - loader.exec->GS = tt_default_graphics_state; - - loader.exec->pedantic_hinting = - FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); - - loader.exec->grayscale = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_LOAD_TARGET_MONO ); - } - -#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ - - /* clear all outline flags, except the `owner' one */ - glyph->outline.flags = 0; - - /* let's initialize the rest of our loader now */ - - loader.load_flags = load_flags; - - loader.face = (FT_Face)face; - loader.size = (FT_Size)size; - loader.glyph = (FT_GlyphSlot)glyph; - loader.stream = stream; - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - if ( face->root.internal->incremental_interface ) - loader.glyf_offset = 0; - else - -#endif - - loader.glyf_offset = FT_STREAM_POS(); - -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - - /* if the cvt program has disabled hinting, the argument */ - /* is ignored. */ - if ( size && ( size->GS.instruct_control & 1 ) ) - loader.load_flags |= FT_LOAD_NO_HINTING; - -#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ - - /* Main loading loop */ glyph->format = FT_GLYPH_FORMAT_OUTLINE; glyph->num_subglyphs = 0; + glyph->outline.flags = 0; + /* Main loading loop */ error = load_truetype_glyph( &loader, glyph_index, 0 ); if ( !error ) + { + if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE ) + { + glyph->num_subglyphs = loader.gloader->base.num_subglyphs; + glyph->subglyphs = loader.gloader->base.subglyphs; + } + else + { + glyph->outline = loader.gloader->base.outline; + glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS; + + /* translate array so that (0,0) is the glyph's origin */ + if ( loader.pp1.x ) + FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 ); + } + compute_glyph_metrics( &loader, glyph_index ); - -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER - - if ( !size || !size->debug ) - TT_Done_Context( loader.exec ); - -#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + } /* Set the `high precision' bit flag. */ /* This is _critical_ to get correct output for monochrome */ /* TrueType glyphs at all sizes using the bytecode interpreter. */ /* */ - if ( size && size->root.metrics.y_ppem < 24 ) + if ( size->root.metrics.y_ppem < 24 ) glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; - Exit: return error; } diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index ec8daae51..483bccc14 100644 --- a/src/truetype/ttinterp.c +++ b/src/truetype/ttinterp.c @@ -371,7 +371,7 @@ /*************************************************************************/ /* */ /* */ - /* TT_Destroy_Context */ + /* TT_Done_Context */ /* */ /* */ /* Destroys a given context. */ @@ -388,9 +388,11 @@ /* Only the glyph loader and debugger should call this function. */ /* */ FT_LOCAL_DEF( FT_Error ) - TT_Destroy_Context( TT_ExecContext exec, - FT_Memory memory ) + TT_Done_Context( TT_ExecContext exec ) { + FT_Memory memory = exec->memory; + + /* free composite load stack */ FT_FREE( exec->loadStack ); exec->loadSize = 0; @@ -416,6 +418,7 @@ exec->face = NULL; FT_FREE( exec ); + return TT_Err_Ok; } @@ -431,8 +434,6 @@ /* */ /* memory :: A handle to the parent memory object. */ /* */ - /* face :: A handle to the source TrueType face object. */ - /* */ /* */ /* exec :: A handle to the target execution context. */ /* */ @@ -441,14 +442,12 @@ /* */ static FT_Error Init_Context( TT_ExecContext exec, - TT_Face face, FT_Memory memory ) { FT_Error error; - FT_TRACE1(( "Init_Context: new object at 0x%08p, parent = 0x%08p\n", - exec, face )); + FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec )); exec->memory = memory; exec->callSize = 32; @@ -469,7 +468,7 @@ exec->loadStack = NULL; exec->glyphIns = NULL; - exec->face = face; + exec->face = NULL; exec->size = NULL; return TT_Err_Ok; @@ -477,7 +476,7 @@ Fail_Memory: FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n", (FT_Long)exec )); - TT_Destroy_Context( exec, memory ); + TT_Done_Context( exec ); return error; } @@ -770,18 +769,12 @@ /* documentation is in ttinterp.h */ FT_EXPORT_DEF( TT_ExecContext ) - TT_New_Context( TT_Face face ) + TT_New_Context( TT_Driver driver ) { - TT_Driver driver; TT_ExecContext exec; FT_Memory memory; - if ( !face ) - return 0; - - driver = (TT_Driver)face->root.driver; - memory = driver->root.root.memory; exec = driver->context; @@ -795,7 +788,7 @@ goto Exit; /* initialize it */ - error = Init_Context( exec, face, memory ); + error = Init_Context( exec, memory ); if ( error ) goto Fail; @@ -813,34 +806,6 @@ } - /*************************************************************************/ - /* */ - /* */ - /* TT_Done_Context */ - /* */ - /* */ - /* Discards an execution context. */ - /* */ - /* */ - /* exec :: A handle to the target execution context. */ - /* */ - /* */ - /* FreeType error code. 0 means success. */ - /* */ - /* */ - /* Only the glyph loader and debugger should call this function. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - TT_Done_Context( TT_ExecContext exec ) - { - /* Nothing at all for now */ - FT_UNUSED( exec ); - - return TT_Err_Ok; - } - - - /*************************************************************************/ /* */ /* Before an opcode is executed, the interpreter verifies that there are */ diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h index 43f662c04..257a7c19e 100644 --- a/src/truetype/ttinterp.h +++ b/src/truetype/ttinterp.h @@ -263,16 +263,11 @@ FT_BEGIN_HEADER /* Only the glyph loader and debugger should call this function. */ /* */ FT_EXPORT( TT_ExecContext ) - TT_New_Context( TT_Face face ); - + TT_New_Context( TT_Driver driver ); FT_LOCAL( FT_Error ) TT_Done_Context( TT_ExecContext exec ); - FT_LOCAL( FT_Error ) - TT_Destroy_Context( TT_ExecContext exec, - FT_Memory memory ); - FT_LOCAL( FT_Error ) TT_Load_Context( TT_ExecContext exec, TT_Face face, diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c index 4ad407244..b61d50cb8 100644 --- a/src/truetype/ttobjs.c +++ b/src/truetype/ttobjs.c @@ -348,7 +348,7 @@ if ( size->debug ) exec = size->context; else - exec = TT_New_Context( face ); + exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; if ( !exec ) return TT_Err_Could_Not_Find_Context; @@ -403,9 +403,6 @@ if ( !error ) TT_Save_Context( exec, size ); - if ( !size->debug ) - TT_Done_Context( exec ); - return error; } @@ -436,7 +433,7 @@ if ( size->debug ) exec = size->context; else - exec = TT_New_Context( face ); + exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; if ( !exec ) return TT_Err_Could_Not_Find_Context; @@ -470,9 +467,6 @@ TT_Save_Context( exec, size ); - if ( !size->debug ) - TT_Done_Context( exec ); - return error; } @@ -917,15 +911,24 @@ /* FreeType error code. 0 means success. */ /* */ FT_LOCAL_DEF( FT_Error ) - tt_driver_init( FT_Module driver ) /* TT_Driver */ + tt_driver_init( FT_Module ttdriver ) /* TT_Driver */ { - FT_Error error; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + TT_Driver driver = (TT_Driver)ttdriver; - /* set `extra' in glyph loader */ - error = FT_GlyphLoader_CreateExtra( FT_DRIVER( driver )->glyph_loader ); + if ( !TT_New_Context( driver ) ) + return TT_Err_Could_Not_Find_Context; - return error; +#else + + FT_UNUSED( ttdriver ); + +#endif + + return TT_Err_Ok; } @@ -950,7 +953,7 @@ /* destroy the execution context */ if ( driver->context ) { - TT_Destroy_Context( driver->context, driver->root.root.memory ); + TT_Done_Context( driver->context ); driver->context = NULL; } #else @@ -960,4 +963,25 @@ } + /*************************************************************************/ + /* */ + /* */ + /* tt_slot_init */ + /* */ + /* */ + /* Initializes a new slot object. */ + /* */ + /* */ + /* slot :: A handle to the slot object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_slot_init( FT_GlyphSlot slot ) + { + return FT_GlyphLoader_CreateExtra( slot->internal->loader ); + } + + /* END */ diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h index c33c1475f..17491a0a2 100644 --- a/src/truetype/ttobjs.h +++ b/src/truetype/ttobjs.h @@ -442,6 +442,14 @@ FT_BEGIN_HEADER tt_driver_done( FT_Module ttdriver ); /* TT_Driver */ + /*************************************************************************/ + /* */ + /* Slot functions */ + /* */ + FT_LOCAL( FT_Error ) + tt_slot_init( FT_GlyphSlot slot ); + + FT_END_HEADER #endif /* __TTOBJS_H__ */