📄 cffgload.c
字号:
error = check_points( builder, 1 );
if ( !error )
cff_builder_add_point( builder, x, y, 1 );
return error;
}
/* check space for a new contour, then add it */
static FT_Error
cff_builder_add_contour( CFF_Builder* builder )
{
FT_Outline* outline = builder->current;
FT_Error error;
if ( !builder->load_points )
{
outline->n_contours++;
return CFF_Err_Ok;
}
error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
if ( !error )
{
if ( outline->n_contours > 0 )
outline->contours[outline->n_contours - 1] =
(short)( outline->n_points - 1 );
outline->n_contours++;
}
return error;
}
/* if a path was begun, add its first on-curve point */
static FT_Error
cff_builder_start_point( CFF_Builder* builder,
FT_Pos x,
FT_Pos y )
{
FT_Error error = CFF_Err_Ok;
/* test whether we are building a new contour */
if ( !builder->path_begun )
{
builder->path_begun = 1;
error = cff_builder_add_contour( builder );
if ( !error )
error = cff_builder_add_point1( builder, x, y );
}
return error;
}
/* close the current contour */
static void
cff_builder_close_contour( CFF_Builder* builder )
{
FT_Outline* outline = builder->current;
if ( !outline )
return;
/* XXXX: We must not include the last point in the path if it */
/* is located on the first point. */
if ( outline->n_points > 1 )
{
FT_Int first = 0;
FT_Vector* p1 = outline->points + first;
FT_Vector* p2 = outline->points + outline->n_points - 1;
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
if ( outline->n_contours > 1 )
{
first = outline->contours[outline->n_contours - 2] + 1;
p1 = outline->points + first;
}
/* `delete' last point only if it coincides with the first */
/* point and if it is not a control point (which can happen). */
if ( p1->x == p2->x && p1->y == p2->y )
if ( *control == FT_CURVE_TAG_ON )
outline->n_points--;
}
if ( outline->n_contours > 0 )
outline->contours[outline->n_contours - 1] =
(short)( outline->n_points - 1 );
}
static FT_Int
cff_lookup_glyph_by_stdcharcode( CFF_Font cff,
FT_Int charcode )
{
FT_UInt n;
FT_UShort glyph_sid;
/* CID-keyed fonts don't have glyph names */
if ( !cff->charset.sids )
return -1;
/* check range of standard char code */
if ( charcode < 0 || charcode > 255 )
return -1;
/* Get code to SID mapping from `cff_standard_encoding'. */
glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );
for ( n = 0; n < cff->num_glyphs; n++ )
{
if ( cff->charset.sids[n] == glyph_sid )
return n;
}
return -1;
}
static FT_Error
cff_get_glyph_data( TT_Face face,
FT_UInt glyph_index,
FT_Byte** pointer,
FT_ULong* length )
{
#ifdef FT_CONFIG_OPTION_INCREMENTAL
/* For incremental fonts get the character data using the */
/* callback function. */
if ( face->root.internal->incremental_interface )
{
FT_Data data;
FT_Error error =
face->root.internal->incremental_interface->funcs->get_glyph_data(
face->root.internal->incremental_interface->object,
glyph_index, &data );
*pointer = (FT_Byte*)data.pointer;
*length = data.length;
return error;
}
else
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
{
CFF_Font cff = (CFF_Font)(face->extra.data);
return cff_index_access_element( &cff->charstrings_index, glyph_index,
pointer, length );
}
}
static void
cff_free_glyph_data( TT_Face face,
FT_Byte** pointer,
FT_ULong length )
{
#ifndef FT_CONFIG_OPTION_INCREMENTAL
FT_UNUSED( length );
#endif
#ifdef FT_CONFIG_OPTION_INCREMENTAL
/* For incremental fonts get the character data using the */
/* callback function. */
if ( face->root.internal->incremental_interface )
{
FT_Data data;
data.pointer = *pointer;
data.length = length;
face->root.internal->incremental_interface->funcs->free_glyph_data(
face->root.internal->incremental_interface->object,&data );
}
else
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
{
CFF_Font cff = (CFF_Font)(face->extra.data);
cff_index_forget_element( &cff->charstrings_index, pointer );
}
}
static FT_Error
cff_operator_seac( CFF_Decoder* decoder,
FT_Pos adx,
FT_Pos ady,
FT_Int bchar,
FT_Int achar )
{
FT_Error error;
CFF_Builder* builder = &decoder->builder;
FT_Int bchar_index, achar_index;
TT_Face face = decoder->builder.face;
FT_Vector left_bearing, advance;
FT_Byte* charstring;
FT_ULong charstring_len;
#ifdef FT_CONFIG_OPTION_INCREMENTAL
/* Incremental fonts don't necessarily have valid charsets. */
/* They use the character code, not the glyph index, in this case. */
if ( face->root.internal->incremental_interface )
{
bchar_index = bchar;
achar_index = achar;
}
else
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
{
CFF_Font cff = (CFF_Font)(face->extra.data);
bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
}
if ( bchar_index < 0 || achar_index < 0 )
{
FT_ERROR(( "cff_operator_seac:" ));
FT_ERROR(( " invalid seac character code arguments\n" ));
return CFF_Err_Syntax_Error;
}
/* If we are trying to load a composite glyph, do not load the */
/* accent character and return the array of subglyphs. */
if ( builder->no_recurse )
{
FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph;
FT_GlyphLoader loader = glyph->internal->loader;
FT_SubGlyph subg;
/* reallocate subglyph array if necessary */
error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
if ( error )
goto Exit;
subg = loader->current.subglyphs;
/* subglyph 0 = base character */
subg->index = bchar_index;
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
FT_SUBGLYPH_FLAG_USE_MY_METRICS;
subg->arg1 = 0;
subg->arg2 = 0;
subg++;
/* subglyph 1 = accent character */
subg->index = achar_index;
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
subg->arg1 = (FT_Int)( adx >> 16 );
subg->arg2 = (FT_Int)( ady >> 16 );
/* set up remaining glyph fields */
glyph->num_subglyphs = 2;
glyph->subglyphs = loader->base.subglyphs;
glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
loader->current.num_subglyphs = 2;
}
FT_GlyphLoader_Prepare( builder->loader );
/* First load `bchar' in builder */
error = cff_get_glyph_data( face, bchar_index,
&charstring, &charstring_len );
if ( !error )
{
error = cff_decoder_parse_charstrings( decoder, charstring,
charstring_len );
if ( error )
goto Exit;
cff_free_glyph_data( face, &charstring, charstring_len );
}
/* Save the left bearing and width of the base character */
/* as they will be erased by the next load. */
left_bearing = builder->left_bearing;
advance = builder->advance;
builder->left_bearing.x = 0;
builder->left_bearing.y = 0;
builder->pos_x = adx;
builder->pos_y = ady;
/* Now load `achar' on top of the base outline. */
error = cff_get_glyph_data( face, achar_index,
&charstring, &charstring_len );
if ( !error )
{
error = cff_decoder_parse_charstrings( decoder, charstring,
charstring_len );
if ( error )
goto Exit;
cff_free_glyph_data( face, &charstring, charstring_len );
}
/* Restore the left side bearing and advance width */
/* of the base character. */
builder->left_bearing = left_bearing;
builder->advance = advance;
builder->pos_x = 0;
builder->pos_y = 0;
Exit:
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* cff_decoder_parse_charstrings */
/* */
/* <Description> */
/* Parses a given Type 2 charstrings program. */
/* */
/* <InOut> */
/* decoder :: The current Type 1 decoder. */
/* */
/* <Input> */
/* charstring_base :: The base of the charstring stream. */
/* */
/* charstring_len :: The length in bytes of the charstring stream. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
cff_decoder_parse_charstrings( CFF_Decoder* decoder,
FT_Byte* charstring_base,
FT_ULong charstring_len )
{
FT_Error error;
CFF_Decoder_Zone* zone;
FT_Byte* ip;
FT_Byte* limit;
CFF_Builder* builder = &decoder->builder;
FT_Pos x, y;
FT_Fixed seed;
FT_Fixed* stack;
T2_Hints_Funcs hinter;
/* 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 ) ) & 0xFFFFL;
if ( seed == 0 )
seed = 0x7384;
/* initialize the decoder */
decoder->top = decoder->stack;
decoder->zone = decoder->zones;
zone = decoder->zones;
stack = decoder->top;
hinter = (T2_Hints_Funcs)builder->hints_funcs;
builder->path_begun = 0;
zone->base = charstring_base;
limit = zone->limit = charstring_base + charstring_len;
ip = zone->cursor = zone->base;
error = CFF_Err_Ok;
x = builder->pos_x;
y = builder->pos_y;
/* begin hints recording session, if any */
if ( hinter )
hinter->open( hinter->hints );
/* now execute loop */
while ( ip < limit )
{
CFF_Operator op;
FT_Byte v;
/********************************************************************/
/* */
/* Decode operator or operand */
/* */
v = *ip++;
if ( v >= 32 || v == 28 )
{
FT_Int shift = 16;
FT_Int32 val;
/* this is an operand, push it on the stack */
if ( v == 28 )
{
if ( ip + 1 >= limit )
goto Syntax_Error;
val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
ip += 2;
}
else if ( v < 247 )
val = (FT_Long)v - 139;
else if ( v < 251 )
{
if ( ip >= limit )
goto Syntax_Error;
val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
}
else if ( v < 255 )
{
if ( ip >= limit )
goto Syntax_Error;
val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -