📄 cffgload.c
字号:
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; } else { if ( ip + 3 >= limit ) goto Syntax_Error; val = ( (FT_Int32)ip[0] << 24 ) | ( (FT_Int32)ip[1] << 16 ) | ( (FT_Int32)ip[2] << 8 ) | ip[3]; ip += 4; shift = 0; } if ( decoder->top - stack >= CFF_MAX_OPERANDS ) goto Stack_Overflow; val <<= shift; *decoder->top++ = val;#ifdef FT_DEBUG_LEVEL_TRACE if ( !( val & 0xFFFFL ) ) FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) )); else FT_TRACE4(( " %.2f", val / 65536.0 ));#endif } else { FT_Fixed* args = decoder->top; FT_Int num_args = (FT_Int)( args - decoder->stack );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -