diff options
Diffstat (limited to 'third_party/freetype/src/cff/cf2intrp.c')
-rw-r--r-- | third_party/freetype/src/cff/cf2intrp.c | 686 |
1 files changed, 514 insertions, 172 deletions
diff --git a/third_party/freetype/src/cff/cf2intrp.c b/third_party/freetype/src/cff/cf2intrp.c index ff3fa9aaaa..6bf298a4d6 100644 --- a/third_party/freetype/src/cff/cf2intrp.c +++ b/third_party/freetype/src/cff/cf2intrp.c @@ -47,6 +47,8 @@ #include "cf2error.h" +#include "cffload.h" + /*************************************************************************/ /* */ @@ -184,7 +186,7 @@ return; FT_ASSERT( hintmask->byteCount > 0 ); - FT_ASSERT( hintmask->byteCount < + FT_ASSERT( hintmask->byteCount <= sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) ); /* set mask to all ones */ @@ -215,8 +217,8 @@ cf2_cmdESC, /* 12 */ cf2_cmdRESERVED_13, /* 13 */ cf2_cmdENDCHAR, /* 14 */ - cf2_cmdRESERVED_15, /* 15 */ - cf2_cmdRESERVED_16, /* 16 */ + cf2_cmdVSINDEX, /* 15 */ + cf2_cmdBLEND, /* 16 */ cf2_cmdRESERVED_17, /* 17 */ cf2_cmdHSTEMHM, /* 18 */ cf2_cmdHINTMASK, /* 19 */ @@ -273,7 +275,8 @@ cf2_escHFLEX, /* 34 */ cf2_escFLEX, /* 35 */ cf2_escHFLEX1, /* 36 */ - cf2_escFLEX1 /* 37 */ + cf2_escFLEX1, /* 37 */ + cf2_escRESERVED_38 /* 38 & all higher */ }; @@ -293,7 +296,8 @@ /* variable accumulates delta values from operand stack */ CF2_Fixed position = hintOffset; - if ( hasWidthArg && ! *haveWidth ) + + if ( hasWidthArg && !*haveWidth ) *width = cf2_stack_getReal( opStack, 0 ) + cf2_getNominalWidthX( font->decoder ); @@ -343,7 +347,7 @@ vals[0] = *curX; vals[1] = *curY; index = 0; - isHFlex = readFromStack[9] == FALSE; + isHFlex = FT_BOOL( readFromStack[9] == FALSE ); top = isHFlex ? 9 : 10; for ( i = 0; i < top; i++ ) @@ -402,6 +406,43 @@ } + /* Blend numOperands on the stack, */ + /* store results into the first numBlends values, */ + /* then pop remaining arguments. */ + static void + cf2_doBlend( const CFF_Blend blend, + CF2_Stack opStack, + CF2_UInt numBlends ) + { + CF2_UInt delta; + CF2_UInt base; + CF2_UInt i, j; + CF2_UInt numOperands = (CF2_UInt)( numBlends * blend->lenBV ); + + + base = cf2_stack_count( opStack ) - numOperands; + delta = base + numBlends; + + for ( i = 0; i < numBlends; i++ ) + { + const CF2_Fixed* weight = &blend->BV[1]; + + /* start with first term */ + CF2_Fixed sum = cf2_stack_getReal( opStack, i + base ); + + + for ( j = 1; j < blend->lenBV; j++ ) + sum += FT_MulFix( *weight++, cf2_stack_getReal( opStack, delta++ ) ); + + /* store blended result */ + cf2_stack_setReal( opStack, i + base, sum ); + } + + /* leave only `numBlends' results on stack */ + cf2_stack_pop( opStack, numOperands - numBlends ); + } + + /* * `error' is a shared error code used by many objects in this * routine. Before the code continues from an error, it must check and @@ -444,8 +485,11 @@ CF2_Fixed hintOriginY = curY; CF2_Stack opStack = NULL; + FT_UInt stackSize; FT_Byte op1; /* first opcode byte */ + CF2_F16Dot16 storage[CF2_STORAGE_SIZE]; /* for `put' and `get' */ + /* instruction limit; 20,000,000 matches Avalon */ FT_UInt32 instructionLimit = 20000000UL; @@ -466,6 +510,8 @@ CF2_GlyphPathRec glyphPath; + FT_ZERO( &storage ); + /* initialize the remaining objects */ cf2_arrstack_init( &subrStack, memory, @@ -515,19 +561,24 @@ * If one of the above operators occurs without explicitly specifying * a width, we assume the default width. * + * CFF2 charstrings always return the default width (0). + * */ - haveWidth = FALSE; + haveWidth = font->isCFF2 ? TRUE : FALSE; *width = cf2_getDefaultWidthX( decoder ); /* - * Note: at this point, all pointers to resources must be NULL - * and all local objects must be initialized. - * There must be no branches to exit: above this point. + * Note: At this point, all pointers to resources must be NULL + * and all local objects must be initialized. + * There must be no branches to `exit:' above this point. * */ /* allocate an operand stack */ - opStack = cf2_stack_init( memory, error ); + stackSize = font->isCFF2 ? cf2_getMaxstack( decoder ) + : CF2_OPERAND_STACK_SIZE; + opStack = cf2_stack_init( memory, error, stackSize ); + if ( !opStack ) { lastError = FT_THROW( Out_Of_Memory ); @@ -556,14 +607,23 @@ { /* If we've reached the end of the charstring, simulate a */ /* cf2_cmdRETURN or cf2_cmdENDCHAR. */ + /* We do this for both CFF and CFF2. */ if ( charstringIndex ) op1 = cf2_cmdRETURN; /* end of buffer for subroutine */ else op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */ } else + { op1 = (FT_Byte)cf2_buf_readByte( charstring ); + /* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */ + /* Note: Trace message will report 0 instead of 11 or 14. */ + if ( ( op1 == cf2_cmdRETURN || op1 == cf2_cmdENDCHAR ) && + font->isCFF2 ) + op1 = cf2_cmdRESERVED_0; + } + /* check for errors once per loop */ if ( *error ) goto exit; @@ -581,13 +641,78 @@ case cf2_cmdRESERVED_2: case cf2_cmdRESERVED_9: case cf2_cmdRESERVED_13: - case cf2_cmdRESERVED_15: - case cf2_cmdRESERVED_16: case cf2_cmdRESERVED_17: /* we may get here if we have a prior error */ FT_TRACE4(( " unknown op (%d)\n", op1 )); break; + case cf2_cmdVSINDEX: + FT_TRACE4(( " vsindex\n" )); + + if ( !font->isCFF2 ) + break; /* clear stack & ignore */ + + if ( font->blend.usedBV ) + { + /* vsindex not allowed after blend */ + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + { + FT_Int temp = cf2_stack_popInt( opStack ); + + + if ( temp >= 0 ) + font->vsindex = (FT_UInt)temp; + } + break; + + case cf2_cmdBLEND: + { + FT_UInt numBlends; + + + FT_TRACE4(( " blend\n" )); + + if ( !font->isCFF2 ) + break; /* clear stack & ignore */ + + /* do we have a `blend' op in a non-variant font? */ + if ( !font->blend.font ) + { + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + /* check cached blend vector */ + if ( cff_blend_check_vector( &font->blend, + font->vsindex, + font->lenNDV, + font->NDV ) ) + { + lastError = cff_blend_build_vector( &font->blend, + font->vsindex, + font->lenNDV, + font->NDV ); + if ( lastError ) + goto exit; + } + + /* do the blend */ + numBlends = (FT_UInt)cf2_stack_popInt( opStack ); + if ( numBlends > stackSize ) + { + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + cf2_doBlend( &font->blend, opStack, numBlends ); + + font->blend.usedBV = TRUE; + } + continue; /* do not clear the stack */ + case cf2_cmdHSTEMHM: case cf2_cmdHSTEM: FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" )); @@ -608,7 +733,7 @@ 0 ); if ( font->decoder->width_only ) - goto exit; + goto exit; break; @@ -632,7 +757,7 @@ 0 ); if ( font->decoder->width_only ) - goto exit; + goto exit; break; @@ -646,7 +771,7 @@ haveWidth = TRUE; if ( font->decoder->width_only ) - goto exit; + goto exit; curY += cf2_stack_popFixed( opStack ); @@ -680,7 +805,7 @@ CF2_UInt index; CF2_UInt count = cf2_stack_count( opStack ); - FT_Bool isX = op1 == cf2_cmdHLINETO; + FT_Bool isX = FT_BOOL( op1 == cf2_cmdHLINETO ); FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" )); @@ -746,7 +871,7 @@ case cf2_cmdCALLGSUBR: case cf2_cmdCALLSUBR: { - CF2_UInt subrIndex; + CF2_Int subrNum; FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr" @@ -766,17 +891,17 @@ (size_t)charstringIndex + 1 ); /* set up the new CFF region and pointer */ - subrIndex = (CF2_UInt)cf2_stack_popInt( opStack ); + subrNum = cf2_stack_popInt( opStack ); switch ( op1 ) { case cf2_cmdCALLGSUBR: FT_TRACE4(( " (idx %d, entering level %d)\n", - subrIndex + (CF2_UInt)decoder->globals_bias, + subrNum + decoder->globals_bias, charstringIndex + 1 )); if ( cf2_initGlobalRegionBuffer( decoder, - subrIndex, + subrNum, charstring ) ) { lastError = FT_THROW( Invalid_Glyph_Format ); @@ -787,11 +912,11 @@ default: /* cf2_cmdCALLSUBR */ FT_TRACE4(( " (idx %d, entering level %d)\n", - subrIndex + (CF2_UInt)decoder->locals_bias, + subrNum + decoder->locals_bias, charstringIndex + 1 )); if ( cf2_initLocalRegionBuffer( decoder, - subrIndex, + subrNum, charstring ) ) { lastError = FT_THROW( Invalid_Glyph_Format ); @@ -825,135 +950,10 @@ FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring ); + /* first switch for 2-byte operators handles CFF2 */ + /* and opcodes that are reserved for both CFF and CFF2 */ switch ( op2 ) { - case cf2_escDOTSECTION: - /* something about `flip type of locking' -- ignore it */ - FT_TRACE4(( " dotsection\n" )); - - break; - - /* TODO: should these operators be supported? */ - case cf2_escAND: /* in spec */ - FT_TRACE4(( " and\n" )); - - CF2_FIXME; - break; - - case cf2_escOR: /* in spec */ - FT_TRACE4(( " or\n" )); - - CF2_FIXME; - break; - - case cf2_escNOT: /* in spec */ - FT_TRACE4(( " not\n" )); - - CF2_FIXME; - break; - - case cf2_escABS: /* in spec */ - FT_TRACE4(( " abs\n" )); - - CF2_FIXME; - break; - - case cf2_escADD: /* in spec */ - FT_TRACE4(( " add\n" )); - - CF2_FIXME; - break; - - case cf2_escSUB: /* in spec */ - FT_TRACE4(( " sub\n" )); - - CF2_FIXME; - break; - - case cf2_escDIV: /* in spec */ - FT_TRACE4(( " div\n" )); - - CF2_FIXME; - break; - - case cf2_escNEG: /* in spec */ - FT_TRACE4(( " neg\n" )); - - CF2_FIXME; - break; - - case cf2_escEQ: /* in spec */ - FT_TRACE4(( " eq\n" )); - - CF2_FIXME; - break; - - case cf2_escDROP: /* in spec */ - FT_TRACE4(( " drop\n" )); - - CF2_FIXME; - break; - - case cf2_escPUT: /* in spec */ - FT_TRACE4(( " put\n" )); - - CF2_FIXME; - break; - - case cf2_escGET: /* in spec */ - FT_TRACE4(( " get\n" )); - - CF2_FIXME; - break; - - case cf2_escIFELSE: /* in spec */ - FT_TRACE4(( " ifelse\n" )); - - CF2_FIXME; - break; - - case cf2_escRANDOM: /* in spec */ - FT_TRACE4(( " random\n" )); - - CF2_FIXME; - break; - - case cf2_escMUL: /* in spec */ - FT_TRACE4(( " mul\n" )); - - CF2_FIXME; - break; - - case cf2_escSQRT: /* in spec */ - FT_TRACE4(( " sqrt\n" )); - - CF2_FIXME; - break; - - case cf2_escDUP: /* in spec */ - FT_TRACE4(( " dup\n" )); - - CF2_FIXME; - break; - - case cf2_escEXCH: /* in spec */ - FT_TRACE4(( " exch\n" )); - - CF2_FIXME; - break; - - case cf2_escINDEX: /* in spec */ - FT_TRACE4(( " index\n" )); - - CF2_FIXME; - break; - - case cf2_escROLL: /* in spec */ - FT_TRACE4(( " roll\n" )); - - CF2_FIXME; - break; - case cf2_escHFLEX: { static const FT_Bool readFromStack[12] = @@ -1050,6 +1050,7 @@ } continue; + /* these opcodes are reserved in both CFF & CFF2 */ case cf2_escRESERVED_1: case cf2_escRESERVED_2: case cf2_escRESERVED_6: @@ -1063,12 +1064,342 @@ case cf2_escRESERVED_31: case cf2_escRESERVED_32: case cf2_escRESERVED_33: - default: FT_TRACE4(( " unknown op (12, %d)\n", op2 )); + break; + + default: + { + if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 ) + FT_TRACE4(( " unknown op (12, %d)\n", op2 )); + else + { + /* second switch for 2-byte operators handles just CFF */ + switch ( op2 ) + { + + case cf2_escDOTSECTION: + /* something about `flip type of locking' -- ignore it */ + FT_TRACE4(( " dotsection\n" )); + + break; + + case cf2_escAND: + { + CF2_F16Dot16 arg1; + CF2_F16Dot16 arg2; + + + FT_TRACE4(( " and\n" )); + + arg2 = cf2_stack_popFixed( opStack ); + arg1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushInt( opStack, arg1 && arg2 ); + } + continue; /* do not clear the stack */ + + case cf2_escOR: + { + CF2_F16Dot16 arg1; + CF2_F16Dot16 arg2; + + + FT_TRACE4(( " or\n" )); + + arg2 = cf2_stack_popFixed( opStack ); + arg1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushInt( opStack, arg1 || arg2 ); + } + continue; /* do not clear the stack */ + + case cf2_escNOT: + { + CF2_F16Dot16 arg; + + + FT_TRACE4(( " not\n" )); + + arg = cf2_stack_popFixed( opStack ); + + cf2_stack_pushInt( opStack, !arg ); + } + continue; /* do not clear the stack */ + + case cf2_escABS: + { + CF2_F16Dot16 arg; + + + FT_TRACE4(( " abs\n" )); + + arg = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, FT_ABS( arg ) ); + } + continue; /* do not clear the stack */ + + case cf2_escADD: + { + CF2_F16Dot16 summand1; + CF2_F16Dot16 summand2; + + + FT_TRACE4(( " add\n" )); + + summand2 = cf2_stack_popFixed( opStack ); + summand1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, summand1 + summand2 ); + } + continue; /* do not clear the stack */ + + case cf2_escSUB: + { + CF2_F16Dot16 minuend; + CF2_F16Dot16 subtrahend; + + + FT_TRACE4(( " sub\n" )); + + subtrahend = cf2_stack_popFixed( opStack ); + minuend = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, minuend - subtrahend ); + } + continue; /* do not clear the stack */ + + case cf2_escDIV: + { + CF2_F16Dot16 dividend; + CF2_F16Dot16 divisor; + + + FT_TRACE4(( " div\n" )); + + divisor = cf2_stack_popFixed( opStack ); + dividend = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, FT_DivFix( dividend, divisor ) ); + } + continue; /* do not clear the stack */ + + case cf2_escNEG: + { + CF2_F16Dot16 arg; + + + FT_TRACE4(( " neg\n" )); + + arg = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, -arg ); + } + continue; /* do not clear the stack */ + + case cf2_escEQ: + { + CF2_F16Dot16 arg1; + CF2_F16Dot16 arg2; + + + FT_TRACE4(( " eq\n" )); + + arg2 = cf2_stack_popFixed( opStack ); + arg1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushInt( opStack, arg1 == arg2 ); + } + continue; /* do not clear the stack */ + + case cf2_escDROP: + FT_TRACE4(( " drop\n" )); + + (void)cf2_stack_popFixed( opStack ); + continue; /* do not clear the stack */ + + case cf2_escPUT: + { + CF2_F16Dot16 val; + CF2_Int idx; + + + FT_TRACE4(( " put\n" )); - }; /* end of switch statement checking `op2' */ + idx = cf2_stack_popInt( opStack ); + val = cf2_stack_popFixed( opStack ); + if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) + storage[idx] = val; + } + continue; /* do not clear the stack */ + + case cf2_escGET: + { + CF2_Int idx; + + + FT_TRACE4(( " get\n" )); + + idx = cf2_stack_popInt( opStack ); + + if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) + cf2_stack_pushFixed( opStack, storage[idx] ); + } + continue; /* do not clear the stack */ + + case cf2_escIFELSE: + { + CF2_F16Dot16 arg1; + CF2_F16Dot16 arg2; + CF2_F16Dot16 cond1; + CF2_F16Dot16 cond2; + + + FT_TRACE4(( " ifelse\n" )); + + cond2 = cf2_stack_popFixed( opStack ); + cond1 = cf2_stack_popFixed( opStack ); + arg2 = cf2_stack_popFixed( opStack ); + arg1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, cond1 <= cond2 ? arg1 : arg2 ); + } + continue; /* do not clear the stack */ + + case cf2_escRANDOM: /* in spec */ + FT_TRACE4(( " random\n" )); + + CF2_FIXME; + break; + + case cf2_escMUL: + { + CF2_F16Dot16 factor1; + CF2_F16Dot16 factor2; + + + FT_TRACE4(( " mul\n" )); + + factor2 = cf2_stack_popFixed( opStack ); + factor1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, FT_MulFix( factor1, factor2 ) ); + } + continue; /* do not clear the stack */ + + case cf2_escSQRT: + { + CF2_F16Dot16 arg; + + + FT_TRACE4(( " sqrt\n" )); + + arg = cf2_stack_popFixed( opStack ); + if ( arg > 0 ) + { + FT_Fixed root = arg; + FT_Fixed new_root; + + + /* Babylonian method */ + for (;;) + { + new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1; + if ( new_root == root ) + break; + root = new_root; + } + arg = new_root; + } + else + arg = 0; + + cf2_stack_pushFixed( opStack, arg ); + } + continue; /* do not clear the stack */ + + case cf2_escDUP: + { + CF2_F16Dot16 arg; + + + FT_TRACE4(( " dup\n" )); + + arg = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, arg ); + cf2_stack_pushFixed( opStack, arg ); + } + continue; /* do not clear the stack */ + + case cf2_escEXCH: + { + CF2_F16Dot16 arg1; + CF2_F16Dot16 arg2; + + + FT_TRACE4(( " exch\n" )); + + arg2 = cf2_stack_popFixed( opStack ); + arg1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, arg2 ); + cf2_stack_pushFixed( opStack, arg1 ); + } + continue; /* do not clear the stack */ + + case cf2_escINDEX: + { + CF2_Int idx; + CF2_UInt size; + + + FT_TRACE4(( " index\n" )); + + idx = cf2_stack_popInt( opStack ); + size = cf2_stack_count( opStack ); + + if ( size > 0 ) + { + /* for `cf2_stack_getReal', index 0 is bottom of stack */ + CF2_UInt gr_idx; + + + if ( idx < 0 ) + gr_idx = size - 1; + else if ( (CF2_UInt)idx >= size ) + gr_idx = 0; + else + gr_idx = size - 1 - (CF2_UInt)idx; + + cf2_stack_pushFixed( opStack, + cf2_stack_getReal( opStack, gr_idx ) ); + } + } + continue; /* do not clear the stack */ + + case cf2_escROLL: + { + CF2_Int idx; + CF2_Int count; + + + FT_TRACE4(( " roll\n" )); + + idx = cf2_stack_popInt( opStack ); + count = cf2_stack_popInt( opStack ); + + cf2_stack_roll( opStack, count, idx ); + } + continue; /* do not clear the stack */ + + } /* end of 2nd switch checking op2 */ + } + } + } /* end of 1st switch checking op2 */ } /* case cf2_cmdESC */ + break; case cf2_cmdENDCHAR: @@ -1085,12 +1416,13 @@ haveWidth = TRUE; if ( font->decoder->width_only ) - goto exit; + goto exit; /* close path if still open */ cf2_glyphpath_closeOpenPath( &glyphPath ); - if ( cf2_stack_count( opStack ) > 1 ) + /* disable seac for CFF2 (charstring ending with args on stack) */ + if ( !font->isCFF2 && cf2_stack_count( opStack ) > 1 ) { /* must be either 4 or 5 -- */ /* this is a (deprecated) implied `seac' operator */ @@ -1117,8 +1449,8 @@ error2 = cf2_getSeacComponent( decoder, achar, &component ); if ( error2 ) { - lastError = error2; /* pass FreeType error through */ - goto exit; + lastError = error2; /* pass FreeType error through */ + goto exit; } cf2_interpT2CharString( font, &component, @@ -1172,7 +1504,7 @@ 0 ); if ( font->decoder->width_only ) - goto exit; + goto exit; if ( op1 == cf2_cmdHINTMASK ) { @@ -1231,7 +1563,7 @@ haveWidth = TRUE; if ( font->decoder->width_only ) - goto exit; + goto exit; curY += cf2_stack_popFixed( opStack ); curX += cf2_stack_popFixed( opStack ); @@ -1250,7 +1582,7 @@ haveWidth = TRUE; if ( font->decoder->width_only ) - goto exit; + goto exit; curX += cf2_stack_popFixed( opStack ); @@ -1319,7 +1651,7 @@ { x1 = cf2_stack_getReal( opStack, index ) + curX; - ++index; + index++; } else x1 = curX; @@ -1364,7 +1696,7 @@ { y1 = cf2_stack_getReal( opStack, index ) + curY; - ++index; + index++; } else y1 = curY; @@ -1392,7 +1724,7 @@ CF2_UInt count, count1 = cf2_stack_count( opStack ); CF2_UInt index = 0; - FT_Bool alternate = op1 == cf2_cmdHVCURVETO; + FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO ); /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */ @@ -1421,7 +1753,7 @@ { x3 = cf2_stack_getReal( opStack, index + 4 ) + x2; - ++index; + index++; } else x3 = x2; @@ -1440,7 +1772,7 @@ { y3 = cf2_stack_getReal( opStack, index + 4 ) + y2; - ++index; + index++; } else y3 = y2; @@ -1463,9 +1795,12 @@ { CF2_Int v; + CF2_Int byte1 = cf2_buf_readByte( charstring ); + CF2_Int byte2 = cf2_buf_readByte( charstring ); + - v = (FT_Short)( ( cf2_buf_readByte( charstring ) << 8 ) | - cf2_buf_readByte( charstring ) ); + v = (FT_Short)( ( byte1 << 8 ) | + byte2 ); FT_TRACE4(( " %d", v )); @@ -1527,14 +1862,18 @@ { CF2_Fixed v; + FT_UInt32 byte1 = (FT_UInt32)cf2_buf_readByte( charstring ); + FT_UInt32 byte2 = (FT_UInt32)cf2_buf_readByte( charstring ); + FT_UInt32 byte3 = (FT_UInt32)cf2_buf_readByte( charstring ); + FT_UInt32 byte4 = (FT_UInt32)cf2_buf_readByte( charstring ); - v = (CF2_Fixed) - ( ( (FT_UInt32)cf2_buf_readByte( charstring ) << 24 ) | - ( (FT_UInt32)cf2_buf_readByte( charstring ) << 16 ) | - ( (FT_UInt32)cf2_buf_readByte( charstring ) << 8 ) | - (FT_UInt32)cf2_buf_readByte( charstring ) ); - FT_TRACE4(( " %.2f", v / 65536.0 )); + v = (CF2_Fixed)( ( byte1 << 24 ) | + ( byte2 << 16 ) | + ( byte3 << 8 ) | + byte4 ); + + FT_TRACE4(( " %.5f", v / 65536.0 )); cf2_stack_pushFixed( opStack, v ); } @@ -1555,6 +1894,9 @@ /* check whether last error seen is also the first one */ cf2_setError( error, lastError ); + if ( *error ) + FT_TRACE4(( "charstring error %d\n", *error )); + /* free resources from objects we've used */ cf2_glyphpath_finalize( &glyphPath ); cf2_arrstack_finalize( &vStemHintArray ); |