📄 ttgload.c
字号:
/*************************************************************************/ /* */ /* <Function> */ /* TT_Process_Composite_Component */ /* */ /* <Description> */ /* 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 = FT_BOOL( 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 >= num_base_points || l >= 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; } /*************************************************************************/ /* */ /* <Function> */ /* TT_Process_Composite_Glyph */ /* */ /* <Description> */ /* This is slightly different from TT_Process_Simple_Glyph, in that */ /* its 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; FT_UInt i; outline = &loader->gloader->base.outline; /* make room for phantom points */ error = FT_GLYPHLOADER_CHECK_POINTS( 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_USE_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 ); /* Some points are likely touched during execution of */ /* instructions on components. So let's untouch them. */ for ( i = start_point; i < loader->zone.n_points; i++ ) loader->zone.tags[i] &= ~( FT_CURVE_TAG_TOUCH_X | FT_CURVE_TAG_TOUCH_Y ); 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 ) /*************************************************************************/ /* */ /* <Function> */ /* load_truetype_glyph */ /* */ /* <Description> */ /* Loads a given truetype glyph. Handles composites and uses a */ /* TT_Loader object. */ /* */ static FT_Error load_truetype_glyph( TT_Loader loader, FT_UInt glyph_index, FT_UInt recurse_count ) { FT_Error error; FT_Fixed x_scale, y_scale; 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 if ( recurse_count > face->max_profile.maxComponentDepth ) { error = TT_Err_Invalid_Composite; goto Exit; } /* check glyph index */ if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) { error = TT_Err_Invalid_Glyph_Index; goto Exit; } loader->glyph_index = glyph_index; 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 */ { FT_Short left_bearing = 0, top_bearing = 0; FT_UShort advance_width = 0, advance_height = 0; Get_HMetrics( face, glyph_index, (FT_Bool)!( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ), &left_bearing, &advance_width ); Get_VMetrics( face, glyph_index, (FT_Bool)!( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ), &top_bearing, &advance_height );#ifdef FT_CONFIG_OPTION_INCREMENTAL /* If this is an incrementally loaded font see if there are */ /* overriding metrics for this glyph. */ if ( face->root.internal->incremental_interface && face->root.internal->incremental_interface->funcs->get_glyph_metrics ) { FT_Incremental_MetricsRec metrics; metrics.bearing_x = left_bearing; metrics.bearing_y = 0; metrics.advance = advance_width; error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( face->root.internal->incremental_interface->object, glyph_index, FALSE, &metrics ); if ( error ) 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? */ metrics.bearing_x = 0; metrics.bearing_y = top_bearing; metrics.advance = advance_height; error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( face->root.internal->incremental_interface->object, glyph_index, TRUE, &metrics ); if ( error ) goto Exit; top_bearing = (FT_Short)metrics.bearing_y; advance_height = (FT_UShort)metrics.advance;#endif /* 0 */ }#endif /* FT_CONFIG_OPTION_INCREMENTAL */ loader->left_bearing = left_bearing; loader->advance = advance_width; loader->top_bearing = top_bearing; loader->vadvance = advance_height; if ( !loader->linear_def ) { loader->linear_def = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -