📄 t2gload.c
字号:
}#define USE_ARGS( n ) do \ { \ top -= n; \ if ( top < decoder->stack ) \ goto Stack_Underflow; \ } while ( 0 ) /*************************************************************************/ /* */ /* <Function> */ /* T2_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 T2_Parse_CharStrings( T2_Decoder* decoder, FT_Byte* charstring_base, FT_Int charstring_len ) { FT_Error error; T2_Decoder_Zone* zone; FT_Byte* ip; FT_Byte* limit; T2_Builder* builder = &decoder->builder; FT_Outline* outline; FT_Pos x, y; FT_Fixed seed; FT_Fixed* stack; /* 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; builder->path_begun = 0; zone->base = charstring_base; limit = zone->limit = charstring_base + charstring_len; ip = zone->cursor = zone->base; error = T2_Err_Ok; outline = builder->current; x = builder->pos_x; y = builder->pos_y; /* now, execute loop */ while ( ip < limit ) { T2_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 >= T2_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 = t2_op_unknown; switch ( v ) { case 1: op = t2_op_hstem; break; case 3: op = t2_op_vstem; break; case 4: op = t2_op_vmoveto; break; case 5: op = t2_op_rlineto; break; case 6: op = t2_op_hlineto; break; case 7: op = t2_op_vlineto; break; case 8: op = t2_op_rrcurveto; break; case 10: op = t2_op_callsubr; break; case 11: op = t2_op_return; break; case 12: { if ( ip >= limit ) goto Syntax_Error; v = *ip++; switch ( v ) { case 3: op = t2_op_and; break; case 4: op = t2_op_or; break; case 5: op = t2_op_not; break; case 8: op = t2_op_store; break; case 9: op = t2_op_abs; break; case 10: op = t2_op_add; break; case 11: op = t2_op_sub; break; case 12: op = t2_op_div; break; case 13: op = t2_op_load; break; case 14: op = t2_op_neg; break; case 15: op = t2_op_eq; break; case 18: op = t2_op_drop; break; case 20: op = t2_op_put; break; case 21: op = t2_op_get; break; case 22: op = t2_op_ifelse; break; case 23: op = t2_op_random; break; case 24: op = t2_op_mul; break; case 26: op = t2_op_sqrt; break; case 27: op = t2_op_dup; break; case 28: op = t2_op_exch; break; case 29: op = t2_op_index; break; case 30: op = t2_op_roll; break; case 34: op = t2_op_hflex; break; case 35: op = t2_op_flex; break; case 36: op = t2_op_hflex1; break; case 37: op = t2_op_flex1; break; default: /* decrement ip for syntax error message */ ip--; } } break; case 14: op = t2_op_endchar; break; case 16: op = t2_op_blend; break; case 18: op = t2_op_hstemhm; break; case 19: op = t2_op_hintmask; break; case 20: op = t2_op_cntrmask; break; case 21: op = t2_op_rmoveto; break; case 22: op = t2_op_hmoveto; break; case 23: op = t2_op_vstemhm; break; case 24: op = t2_op_rcurveline; break; case 25: op = t2_op_rlinecurve; break; case 26: op = t2_op_vvcurveto; break; case 27: op = t2_op_hhcurveto; break; case 29: op = t2_op_callgsubr; break; case 30: op = t2_op_vhcurveto; break; case 31: op = t2_op_hvcurveto; break; default: ; } if ( op == t2_op_unknown ) goto Syntax_Error; /* check arguments */ req_args = t2_argument_counts[op]; if ( req_args & T2_COUNT_CHECK_WIDTH ) { args = stack; if ( num_args > 0 && decoder->read_width ) { /* If `nominal_width' is non-zero, the number is really a */ /* difference against `nominal_width'. Else, the number here */ /* is truly a width, not a difference against `nominal_width'. */ /* If the font does not set `nominal_width', then */ /* `nominal_width' defaults to zero, and so we can set */ /* `glyph_width' to `nominal_width' plus number on the stack */ /* -- for either case. */ FT_Int set_width_ok; switch ( op ) { case t2_op_hmoveto: case t2_op_vmoveto: set_width_ok = num_args & 2; break; case t2_op_hstem: case t2_op_vstem: case t2_op_hstemhm: case t2_op_vstemhm: case t2_op_endchar: case t2_op_rmoveto: set_width_ok = num_args & 1; break; default: set_width_ok = 0; break; } if ( set_width_ok ) { decoder->glyph_width = decoder->nominal_width + ( stack[0] >> 16 ); num_args--; args++; } } decoder->read_width = 0; req_args = 0; } req_args &= 15; if ( num_args < req_args ) goto Stack_Underflow; args -= req_args; num_args -= req_args; switch ( op ) { case t2_op_hstem: case t2_op_vstem: case t2_op_hstemhm: case t2_op_vstemhm: /* if the number of arguments is not even, the first one */ /* is simply the glyph width, encoded as the difference */ /* to nominalWidthX */ FT_TRACE4(( op == t2_op_hstem ? " hstem" : op == t2_op_vstem ? " vstem" : op == t2_op_hstemhm ? " hstemhm" : " vstemhm" )); decoder->num_hints += num_args / 2; args = stack; break; case t2_op_hintmask: case t2_op_cntrmask: FT_TRACE4(( op == t2_op_hintmask ? " hintmask" : " cntrmask" )); decoder->num_hints += num_args / 2; ip += ( decoder->num_hints + 7 ) >> 3; if ( ip >= limit ) goto Syntax_Error; args = stack; break; case t2_op_rmoveto: FT_TRACE4(( " rmoveto" )); close_contour( builder ); builder->path_begun = 0; x += args[0]; y += args[1]; args = stack; break; case t2_op_vmoveto: FT_TRACE4(( " vmoveto" )); close_contour( builder ); builder->path_begun = 0; y += args[0]; args = stack; break; case t2_op_hmoveto: FT_TRACE4(( " hmoveto" )); close_contour( builder ); builder->path_begun = 0; x += args[0]; args = stack; break; case t2_op_rlineto: FT_TRACE4(( " rlineto" )); if ( start_point ( builder, x, y ) || check_points( builder, num_args / 2 ) ) goto Memory_Error; if ( num_args < 2 || num_args & 1 ) goto Stack_Underflow; args = stack; while ( args < decoder->top ) { x += args[0]; y += args[1]; add_point( builder, x, y, 1 ); args += 2; } args = stack; break; case t2_op_hlineto: case t2_op_vlineto: { FT_Int phase = ( op == t2_op_hlineto ); FT_TRACE4(( op == t2_op_hlineto ? " hlineto" : " vlineto" )); if ( start_point ( builder, x, y ) || check_points( builder, num_args ) ) goto Memory_Error; args = stack; while (args < decoder->top ) { if ( phase ) x += args[0]; else y += args[0]; if ( add_point1( builder, x, y ) ) goto Memory_Error; args++; phase ^= 1; } args = stack; } break; case t2_op_rrcurveto: FT_TRACE4(( " rrcurveto" )); /* check number of arguments; must be a multiple of 6 */ if ( num_args % 6 != 0 ) goto Stack_Underflow; if ( start_point ( builder, x, y ) || check_points( builder, num_args / 2 ) ) goto Memory_Error; args = stack; while ( args < decoder->top ) { x += args[0]; y += args[1]; add_point( builder, x, y, 0 ); x += args[2]; y += args[3]; add_point( builder, x, y, 0 ); x += args[4]; y += args[5]; add_point( builder, x, y, 1 ); args += 6; } args = stack; break; case t2_op_vvcurveto: FT_TRACE4(( " vvcurveto" )); if ( start_point ( builder, x, y ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -