diff options
Diffstat (limited to 'src/freetype2/truetype/ttinterp.c')
-rw-r--r-- | src/freetype2/truetype/ttinterp.c | 129 |
1 files changed, 82 insertions, 47 deletions
diff --git a/src/freetype2/truetype/ttinterp.c b/src/freetype2/truetype/ttinterp.c index 85c8529..13aa9a2 100644 --- a/src/freetype2/truetype/ttinterp.c +++ b/src/freetype2/truetype/ttinterp.c @@ -4,7 +4,7 @@ /* */ /* TrueType bytecode interpreter (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -693,7 +693,7 @@ /* exec :: A handle to the target execution context. */ /* */ /* <Return> */ - /* TrueTyoe error code. 0 means success. */ + /* TrueType error code. 0 means success. */ /* */ /* <Note> */ /* Only the glyph loader and debugger should call this function. */ @@ -748,6 +748,13 @@ } + /* The default value for `scan_control' is documented as FALSE in the */ + /* TrueType specification. This is confusing since it implies a */ + /* Boolean value. However, this is not the case, thus both the */ + /* default values of our `scan_type' and `scan_control' fields (which */ + /* the documentation's `scan_control' variable is split into) are */ + /* zero. */ + const TT_GraphicsState tt_default_graphics_state = { 0, 0, 0, @@ -761,7 +768,7 @@ 1, 64, 1, TRUE, 68, 0, 0, 9, 3, - 0, FALSE, 2, 1, 1, 1 + 0, FALSE, 0, 1, 1, 1 }; @@ -784,9 +791,9 @@ /* allocate object */ if ( FT_NEW( exec ) ) - goto Exit; + goto Fail; - /* initialize it */ + /* initialize it; in case of error this deallocates `exec' too */ error = Init_Context( exec, memory ); if ( error ) goto Fail; @@ -795,13 +802,10 @@ driver->context = exec; } - Exit: return driver->context; Fail: - FT_FREE( exec ); - - return 0; + return NULL; } @@ -2190,7 +2194,7 @@ FT_ASSERT( !CUR.face->unpatented_hinting ); #endif - return TT_DotFix14( dx, dy, + return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy, CUR.GS.projVector.x, CUR.GS.projVector.y ); } @@ -2216,7 +2220,7 @@ Dual_Project( EXEC_OP_ FT_Pos dx, FT_Pos dy ) { - return TT_DotFix14( dx, dy, + return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy, CUR.GS.dualVector.x, CUR.GS.dualVector.y ); } @@ -4286,13 +4290,21 @@ CUR.numFDefs++; } + /* Although FDEF takes unsigned 32-bit integer, */ + /* func # must be within unsigned 16-bit integer */ + if ( n > 0xFFFFU ) + { + CUR.error = TT_Err_Too_Many_Function_Defs; + return; + } + rec->range = CUR.curRange; - rec->opc = n; + rec->opc = (FT_UInt16)n; rec->start = CUR.IP + 1; rec->active = TRUE; if ( n > CUR.maxFunc ) - CUR.maxFunc = n; + CUR.maxFunc = (FT_UInt16)n; /* Now skip the whole function definition. */ /* We don't allow nested IDEFS & FDEFs. */ @@ -4549,13 +4561,20 @@ CUR.numIDefs++; } - def->opc = args[0]; + /* opcode must be unsigned 8-bit integer */ + if ( 0 > args[0] || args[0] > 0x00FF ) + { + CUR.error = TT_Err_Too_Many_Instruction_Defs; + return; + } + + def->opc = (FT_Byte)args[0]; def->start = CUR.IP+1; def->range = CUR.curRange; def->active = TRUE; if ( (FT_ULong)args[0] > CUR.maxIns ) - CUR.maxIns = args[0]; + CUR.maxIns = (FT_Byte)args[0]; /* Now skip the whole function definition. */ /* We don't allow nested IDEFs & FDEFs. */ @@ -4821,7 +4840,28 @@ if ( CUR.opcode & 1 ) D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K ); else - D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K ); + { + FT_Vector* vec1 = CUR.zp0.orus + L; + FT_Vector* vec2 = CUR.zp1.orus + K; + + + if ( CUR.metrics.x_scale == CUR.metrics.y_scale ) + { + /* this should be faster */ + D = CUR_Func_dualproj( vec1, vec2 ); + D = TT_MULFIX( D, CUR.metrics.x_scale ); + } + else + { + FT_Vector vec; + + + vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale ); + vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale ); + + D = CUR_fast_dualproj( &vec ); + } + } } args[0] = D; @@ -5071,12 +5111,8 @@ return; } - A *= 64; - -#if 0 - if ( ( args[0] & 0x100 ) != 0 && CUR.metrics.pointSize <= A ) + if ( ( args[0] & 0x100 ) != 0 && CUR.tt_metrics.ppem <= A ) CUR.GS.scan_control = TRUE; -#endif if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated ) CUR.GS.scan_control = TRUE; @@ -5084,10 +5120,8 @@ if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched ) CUR.GS.scan_control = TRUE; -#if 0 - if ( ( args[0] & 0x800 ) != 0 && CUR.metrics.pointSize > A ) + if ( ( args[0] & 0x800 ) != 0 && CUR.tt_metrics.ppem > A ) CUR.GS.scan_control = FALSE; -#endif if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated ) CUR.GS.scan_control = FALSE; @@ -5106,16 +5140,8 @@ static void Ins_SCANTYPE( INS_ARG ) { - /* for compatibility with future enhancements, */ - /* we must ignore new modes */ - - if ( args[0] >= 0 && args[0] <= 5 ) - { - if ( args[0] == 3 ) - args[0] = 2; - + if ( args[0] >= 0 ) CUR.GS.scan_type = (FT_Int)args[0]; - } } @@ -5428,7 +5454,7 @@ /* XXX: this is probably wrong... at least it prevents memory */ /* corruption when zp2 is the twilight zone */ - if ( last_point > CUR.zp2.n_points ) + if ( BOUNDS( last_point, CUR.zp2.n_points ) ) { if ( CUR.zp2.n_points > 0 ) last_point = (FT_UShort)(CUR.zp2.n_points - 1); @@ -5516,20 +5542,20 @@ { if ( CUR.GS.both_x_axis ) { - dx = TT_MulFix14( args[0], 0x4000 ); + dx = TT_MulFix14( (FT_UInt32)args[0], 0x4000 ); dy = 0; } else { dx = 0; - dy = TT_MulFix14( args[0], 0x4000 ); + dy = TT_MulFix14( (FT_UInt32)args[0], 0x4000 ); } } else #endif { - dx = TT_MulFix14( args[0], CUR.GS.freeVector.x ); - dy = TT_MulFix14( args[0], CUR.GS.freeVector.y ); + dx = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.x ); + dy = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.y ); } while ( CUR.GS.loop > 0 ) @@ -5695,8 +5721,8 @@ if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */ { - CUR.zp0.org[point].x = TT_MulFix14( distance, CUR.GS.freeVector.x ); - CUR.zp0.org[point].y = TT_MulFix14( distance, CUR.GS.freeVector.y ), + CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.x ); + CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.y ), CUR.zp0.cur[point] = CUR.zp0.org[point]; } @@ -5883,10 +5909,12 @@ if ( CUR.GS.gep1 == 0 ) { CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x + - TT_MulFix14( cvt_dist, CUR.GS.freeVector.x ); + TT_MulFix14( (FT_UInt32)cvt_dist, + CUR.GS.freeVector.x ); CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y + - TT_MulFix14( cvt_dist, CUR.GS.freeVector.y ); + TT_MulFix14( (FT_UInt32)cvt_dist, + CUR.GS.freeVector.y ); CUR.zp1.cur[point] = CUR.zp0.cur[point]; } @@ -6211,9 +6239,13 @@ org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base ); cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base ); - new_dist = ( old_range != 0 ) - ? TT_MULDIV( org_dist, cur_range, old_range ) - : cur_dist; + + if ( org_dist ) + new_dist = ( old_range != 0 ) + ? TT_MULDIV( org_dist, cur_range, old_range ) + : cur_dist; + else + new_dist = 0; CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist ); } @@ -6257,7 +6289,7 @@ /* Local variables for Ins_IUP: */ - typedef struct + typedef struct IUP_WorkerRec_ { FT_Vector* orgs; /* original and current coordinate */ FT_Vector* curs; /* arrays */ @@ -6370,7 +6402,7 @@ { scale_valid = 1; scale = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ), - 0x10000, orus2 - orus1 ); + 0x10000L, orus2 - orus1 ); } x = ( org1 + delta1 ) + @@ -6434,6 +6466,9 @@ end_point = CUR.pts.contours[contour] - CUR.pts.first_point; first_point = point; + if ( CUR.pts.n_points <= end_point ) + end_point = CUR.pts.n_points; + while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 ) point++; |