📄 cffgload.c
字号:
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 start_point( CFF_Builder* builder, FT_Pos x, FT_Pos y ) { FT_Error error = 0; /* test whether we are building a new contour */ if ( !builder->path_begun ) { builder->path_begun = 1; error = add_contour( builder ); if ( !error ) error = add_point1( builder, x, y ); } return error; } /* close the current contour */ static void close_contour( CFF_Builder* builder ) { FT_Outline* outline = builder->current; /* 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 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; /* 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_operator_seac( CFF_Decoder* decoder, FT_Pos adx, FT_Pos ady, FT_Int bchar, FT_Int achar ) { FT_Error error; FT_Int bchar_index, achar_index, n_base_points; FT_Outline* base = decoder->builder.base; TT_Face face = decoder->builder.face; CFF_Font* cff = (CFF_Font*)(face->extra.data); FT_Vector left_bearing, advance; FT_Byte* charstring; FT_ULong charstring_len; 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 ( decoder->builder.no_recurse ) { FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; FT_GlyphLoader* loader = glyph->internal->loader; FT_SubGlyph* subg; /* reallocate subglyph array if necessary */ error = FT_GlyphLoader_Check_Subglyphs( 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 = adx; subg->arg2 = ady; /* 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; } /* First load `bchar' in builder */ error = CFF_Access_Element( &cff->charstrings_index, bchar_index, &charstring, &charstring_len ); if ( !error ) { error = CFF_Parse_CharStrings( decoder, charstring, charstring_len ); if ( error ) goto Exit; CFF_Forget_Element( &cff->charstrings_index, &charstring ); } n_base_points = base->n_points; /* Save the left bearing and width of the base character */ /* as they will be erased by the next load. */ left_bearing = decoder->builder.left_bearing; advance = decoder->builder.advance; decoder->builder.left_bearing.x = 0; decoder->builder.left_bearing.y = 0; /* Now load `achar' on top of the base outline. */ error = CFF_Access_Element( &cff->charstrings_index, achar_index, &charstring, &charstring_len ); if ( !error ) { error = CFF_Parse_CharStrings( decoder, charstring, charstring_len ); if ( error ) goto Exit; CFF_Forget_Element( &cff->charstrings_index, &charstring ); } /* Restore the left side bearing and advance width */ /* of the base character. */ decoder->builder.left_bearing = left_bearing; decoder->builder.advance = advance; /* Finally, move the accent. */ if ( decoder->builder.load_points ) { FT_Outline dummy; dummy.n_points = (short)( base->n_points - n_base_points ); dummy.points = base->points + n_base_points; FT_Outline_Translate( &dummy, adx, ady ); } Exit: return error; } /*************************************************************************/ /* */ /* <Function> */ /* CFF_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_Parse_CharStrings( CFF_Decoder* decoder, FT_Byte* charstring_base, FT_Int 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 ) ) & 0xFFFF; 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 & 0xFFFF ) ) FT_TRACE4(( " %d", (FT_Int32)( val >> 16 ) )); else FT_TRACE4(( " %.2f", val / 65536.0 ));#endif } else { FT_Fixed* args = decoder->top; FT_Int num_args = args - decoder->stack; FT_Int req_args; /* find operator */ op = cff_op_unknown; switch ( v ) { case 1: op = cff_op_hstem; break; case 3: op = cff_op_vstem; break; case 4: op = cff_op_vmoveto; break; case 5: op = cff_op_rlineto; break; case 6: op = cff_op_hlineto; break; case 7: op = cff_op_vlineto; break; case 8: op = cff_op_rrcurveto; break; case 10: op = cff_op_callsubr; break; case 11: op = cff_op_return; break; case 12: { if ( ip >= limit ) goto Syntax_Error; v = *ip++; switch ( v ) { case 0: op = cff_op_dotsection; break; case 3: op = cff_op_and; break; case 4: op = cff_op_or; break; case 5: op = cff_op_not; break; case 8: op = cff_op_store; break; case 9: op = cff_op_abs; break; case 10: op = cff_op_add; break; case 11: op = cff_op_sub; break; case 12: op = cff_op_div; break; case 13: op = cff_op_load; break; case 14: op = cff_op_neg; break; case 15: op = cff_op_eq; break; case 18: op = cff_op_drop; break; case 20: op = cff_op_put; break; case 21: op = cff_op_get; break; case 22: op = cff_op_ifelse;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -