| Index: src/truetype/ttinterp.c
|
| diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
|
| index 6c4eed684688d1cf9821ba435b36bf991fd740a5..3acb24a2f6f6dc513a2eb4963f77ca36ec5fc79f 100644
|
| --- a/src/truetype/ttinterp.c
|
| +++ b/src/truetype/ttinterp.c
|
| @@ -4,7 +4,7 @@
|
| /* */
|
| /* TrueType bytecode interpreter (body). */
|
| /* */
|
| -/* Copyright 1996-2011 */
|
| +/* Copyright 1996-2012 */
|
| /* by David Turner, Robert Wilhelm, and Werner Lemberg. */
|
| /* */
|
| /* This file is part of the FreeType project, and may only be used, */
|
| @@ -715,7 +715,7 @@
|
| FT_Error error;
|
|
|
|
|
| - if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
|
| + if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
|
| != TT_Err_Ok )
|
| return error;
|
|
|
| @@ -1800,7 +1800,7 @@
|
|
|
| /* NOTE: Because the last instruction of a program may be a CALL */
|
| /* which will return to the first byte *after* the code */
|
| - /* range, we test for AIP <= Size, instead of AIP < Size. */
|
| + /* range, we test for aIP <= Size, instead of aIP < Size. */
|
|
|
| if ( aIP > range->size )
|
| {
|
| @@ -2757,7 +2757,7 @@
|
| W = Vx * Vx + Vy * Vy;
|
|
|
| /* Now, we want that Sqrt( W ) = 0x4000 */
|
| - /* Or 0x10000000 <= W < 0x10004000 */
|
| + /* Or 0x10000000 <= W < 0x10004000 */
|
|
|
| if ( Vx < 0 )
|
| {
|
| @@ -3199,36 +3199,42 @@
|
| }
|
|
|
|
|
| -#define DO_JROT \
|
| - if ( args[1] != 0 ) \
|
| - { \
|
| - if ( args[0] == 0 && CUR.args == 0 ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| - CUR.IP += args[0]; \
|
| - if ( CUR.IP < 0 ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| - CUR.step_ins = FALSE; \
|
| +#define DO_JROT \
|
| + if ( args[1] != 0 ) \
|
| + { \
|
| + if ( args[0] == 0 && CUR.args == 0 ) \
|
| + CUR.error = TT_Err_Bad_Argument; \
|
| + CUR.IP += args[0]; \
|
| + if ( CUR.IP < 0 || \
|
| + ( CUR.callTop > 0 && \
|
| + CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
|
| + CUR.error = TT_Err_Bad_Argument; \
|
| + CUR.step_ins = FALSE; \
|
| }
|
|
|
|
|
| -#define DO_JMPR \
|
| - if ( args[0] == 0 && CUR.args == 0 ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| - CUR.IP += args[0]; \
|
| - if ( CUR.IP < 0 ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| +#define DO_JMPR \
|
| + if ( args[0] == 0 && CUR.args == 0 ) \
|
| + CUR.error = TT_Err_Bad_Argument; \
|
| + CUR.IP += args[0]; \
|
| + if ( CUR.IP < 0 || \
|
| + ( CUR.callTop > 0 && \
|
| + CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
|
| + CUR.error = TT_Err_Bad_Argument; \
|
| CUR.step_ins = FALSE;
|
|
|
|
|
| -#define DO_JROF \
|
| - if ( args[1] == 0 ) \
|
| - { \
|
| - if ( args[0] == 0 && CUR.args == 0 ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| - CUR.IP += args[0]; \
|
| - if ( CUR.IP < 0 ) \
|
| - CUR.error = TT_Err_Bad_Argument; \
|
| - CUR.step_ins = FALSE; \
|
| +#define DO_JROF \
|
| + if ( args[1] == 0 ) \
|
| + { \
|
| + if ( args[0] == 0 && CUR.args == 0 ) \
|
| + CUR.error = TT_Err_Bad_Argument; \
|
| + CUR.IP += args[0]; \
|
| + if ( CUR.IP < 0 || \
|
| + ( CUR.callTop > 0 && \
|
| + CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
|
| + CUR.error = TT_Err_Bad_Argument; \
|
| + CUR.step_ins = FALSE; \
|
| }
|
|
|
|
|
| @@ -4471,7 +4477,7 @@
|
| CUR.length = opcode_length[CUR.opcode];
|
| if ( CUR.length < 0 )
|
| {
|
| - if ( CUR.IP + 1 > CUR.codeSize )
|
| + if ( CUR.IP + 1 >= CUR.codeSize )
|
| goto Fail_Overflow;
|
| CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
|
| }
|
| @@ -4640,6 +4646,7 @@
|
| return;
|
|
|
| case 0x2D: /* ENDF */
|
| + rec->end = CUR.IP;
|
| return;
|
| }
|
| }
|
| @@ -4757,6 +4764,7 @@
|
| pCrec->Caller_IP = CUR.IP + 1;
|
| pCrec->Cur_Count = 1;
|
| pCrec->Cur_Restart = def->start;
|
| + pCrec->Cur_End = def->end;
|
|
|
| CUR.callTop++;
|
|
|
| @@ -4835,6 +4843,7 @@
|
| pCrec->Caller_IP = CUR.IP + 1;
|
| pCrec->Cur_Count = (FT_Int)args[0];
|
| pCrec->Cur_Restart = def->start;
|
| + pCrec->Cur_End = def->end;
|
|
|
| CUR.callTop++;
|
|
|
| @@ -5050,8 +5059,8 @@
|
| /* Opcode range: 0x46-0x47 */
|
| /* Stack: uint32 --> f26.6 */
|
| /* */
|
| - /* BULLSHIT: Measures from the original glyph must be taken along the */
|
| - /* dual projection vector! */
|
| + /* XXX: UNDOCUMENTED: Measures from the original glyph must be taken */
|
| + /* along the dual projection vector! */
|
| /* */
|
| static void
|
| Ins_GC( INS_ARG )
|
| @@ -5123,14 +5132,14 @@
|
| /* Opcode range: 0x49-0x4A */
|
| /* Stack: uint32 uint32 --> f26.6 */
|
| /* */
|
| - /* BULLSHIT: Measure taken in the original glyph must be along the dual */
|
| - /* projection vector. */
|
| + /* XXX: UNDOCUMENTED: Measure taken in the original glyph must be along */
|
| + /* the dual projection vector. */
|
| /* */
|
| - /* Second BULLSHIT: Flag attributes are inverted! */
|
| - /* 0 => measure distance in original outline */
|
| - /* 1 => measure distance in grid-fitted outline */
|
| + /* XXX: UNDOCUMENTED: Flag attributes are inverted! */
|
| + /* 0 => measure distance in original outline */
|
| + /* 1 => measure distance in grid-fitted outline */
|
| /* */
|
| - /* Third one: `zp0 - zp1', and not `zp2 - zp1! */
|
| + /* XXX: UNDOCUMENTED: `zp0 - zp1', and not `zp2 - zp1! */
|
| /* */
|
| static void
|
| Ins_MD( INS_ARG )
|
| @@ -5155,25 +5164,38 @@
|
| D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
|
| else
|
| {
|
| - FT_Vector* vec1 = CUR.zp0.orus + L;
|
| - FT_Vector* vec2 = CUR.zp1.orus + K;
|
| + /* XXX: UNDOCUMENTED: twilight zone special case */
|
|
|
| -
|
| - if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
|
| + if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
|
| {
|
| - /* this should be faster */
|
| + FT_Vector* vec1 = CUR.zp0.org + L;
|
| + FT_Vector* vec2 = CUR.zp1.org + K;
|
| +
|
| +
|
| D = CUR_Func_dualproj( vec1, vec2 );
|
| - D = TT_MULFIX( D, CUR.metrics.x_scale );
|
| }
|
| else
|
| {
|
| - FT_Vector vec;
|
| + 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 );
|
| + 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 );
|
| + D = CUR_fast_dualproj( &vec );
|
| + }
|
| }
|
| }
|
| }
|
| @@ -5748,21 +5770,25 @@
|
| /* Opcode range: 0x34-35 */
|
| /* Stack: uint32 --> */
|
| /* */
|
| + /* UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual) */
|
| + /* contour in the twilight zone, namely contour number */
|
| + /* zero. */
|
| + /* */
|
| static void
|
| Ins_SHC( INS_ARG )
|
| {
|
| - TT_GlyphZoneRec zp;
|
| - FT_UShort refp;
|
| - FT_F26Dot6 dx,
|
| - dy;
|
| + TT_GlyphZoneRec zp;
|
| + FT_UShort refp;
|
| + FT_F26Dot6 dx, dy;
|
|
|
| - FT_Short contour;
|
| - FT_UShort first_point, last_point, i;
|
| + FT_Short contour, bounds;
|
| + FT_UShort start, limit, i;
|
|
|
|
|
| contour = (FT_UShort)args[0];
|
| + bounds = ( CUR.GS.gep2 == 0 ) ? 1 : CUR.zp2.n_contours;
|
|
|
| - if ( BOUNDS( contour, CUR.pts.n_contours ) )
|
| + if ( BOUNDS( contour, bounds ) )
|
| {
|
| if ( CUR.pedantic_hinting )
|
| CUR.error = TT_Err_Invalid_Reference;
|
| @@ -5773,25 +5799,19 @@
|
| return;
|
|
|
| if ( contour == 0 )
|
| - first_point = 0;
|
| + start = 0;
|
| else
|
| - first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -
|
| - CUR.pts.first_point );
|
| -
|
| - last_point = (FT_UShort)( CUR.pts.contours[contour] -
|
| - CUR.pts.first_point );
|
| + start = (FT_UShort)( CUR.zp2.contours[contour - 1] + 1 -
|
| + CUR.zp2.first_point );
|
|
|
| - /* XXX: this is probably wrong... at least it prevents memory */
|
| - /* corruption when zp2 is the twilight zone */
|
| - if ( BOUNDS( last_point, CUR.zp2.n_points ) )
|
| - {
|
| - if ( CUR.zp2.n_points > 0 )
|
| - last_point = (FT_UShort)(CUR.zp2.n_points - 1);
|
| - else
|
| - last_point = 0;
|
| - }
|
| + /* we use the number of points if in the twilight zone */
|
| + if ( CUR.GS.gep2 == 0 )
|
| + limit = CUR.zp2.n_points;
|
| + else
|
| + limit = (FT_UShort)( CUR.zp2.contours[contour] -
|
| + CUR.zp2.first_point + 1 );
|
|
|
| - for ( i = first_point; i <= last_point; i++ )
|
| + for ( i = start; i < limit; i++ )
|
| {
|
| if ( zp.cur != CUR.zp2.cur || refp != i )
|
| MOVE_Zp2_Point( i, dx, dy, TRUE );
|
| @@ -5813,7 +5833,7 @@
|
| FT_F26Dot6 dx,
|
| dy;
|
|
|
| - FT_UShort last_point, i;
|
| + FT_UShort limit, i;
|
|
|
|
|
| if ( BOUNDS( args[0], 2 ) )
|
| @@ -5826,28 +5846,19 @@
|
| if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
|
| return;
|
|
|
| - /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */
|
| - /* Twilight zone has no contours, so use `n_points'. */
|
| - /* Normal zone's `n_points' includes phantoms, so must */
|
| - /* use end of last contour. */
|
| - if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
|
| - last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
|
| + /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */
|
| + /* Twilight zone has no real contours, so use `n_points'. */
|
| + /* Normal zone's `n_points' includes phantoms, so must */
|
| + /* use end of last contour. */
|
| + if ( CUR.GS.gep2 == 0 )
|
| + limit = (FT_UShort)CUR.zp2.n_points;
|
| else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
|
| - {
|
| - last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
|
| -
|
| - if ( BOUNDS( last_point, CUR.zp2.n_points ) )
|
| - {
|
| - if ( CUR.pedantic_hinting )
|
| - CUR.error = TT_Err_Invalid_Reference;
|
| - return;
|
| - }
|
| - }
|
| + limit = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] + 1 );
|
| else
|
| - last_point = 0;
|
| + limit = 0;
|
|
|
| /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
|
| - for ( i = 0; i <= last_point; i++ )
|
| + for ( i = 0; i < limit; i++ )
|
| {
|
| if ( zp.cur != CUR.zp2.cur || refp != i )
|
| MOVE_Zp2_Point( i, dx, dy, FALSE );
|
| @@ -6253,7 +6264,7 @@
|
| CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
|
| TT_MulFix14( (FT_UInt32)cvt_dist,
|
| CUR.GS.freeVector.y );
|
| - CUR.zp1.cur[point] = CUR.zp0.cur[point];
|
| + CUR.zp1.cur[point] = CUR.zp1.org[point];
|
| }
|
|
|
| org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
|
| @@ -6562,9 +6573,21 @@
|
| if ( twilight )
|
| old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
|
| orus_base );
|
| - else
|
| + else if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
|
| old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
|
| orus_base );
|
| + else
|
| + {
|
| + FT_Vector vec;
|
| +
|
| +
|
| + vec.x = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x,
|
| + CUR.metrics.x_scale );
|
| + vec.y = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y,
|
| + CUR.metrics.y_scale );
|
| +
|
| + old_range = CUR_fast_dualproj( &vec );
|
| + }
|
|
|
| cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
|
| }
|
| @@ -6588,8 +6611,20 @@
|
|
|
| if ( twilight )
|
| org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
|
| - else
|
| + else if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
|
| org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
|
| + else
|
| + {
|
| + FT_Vector vec;
|
| +
|
| +
|
| + vec.x = TT_MULFIX( CUR.zp2.orus[point].x - orus_base->x,
|
| + CUR.metrics.x_scale );
|
| + vec.y = TT_MULFIX( CUR.zp2.orus[point].y - orus_base->y,
|
| + CUR.metrics.y_scale );
|
| +
|
| + org_dist = CUR_fast_dualproj( &vec );
|
| + }
|
|
|
| cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
|
|
|
| @@ -7136,6 +7171,7 @@
|
| call->Caller_IP = CUR.IP + 1;
|
| call->Cur_Count = 1;
|
| call->Cur_Restart = def->start;
|
| + call->Cur_End = def->end;
|
|
|
| INS_Goto_CodeRange( def->range, def->start );
|
|
|
| @@ -7508,7 +7544,7 @@
|
|
|
| if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
|
| {
|
| - if ( CUR.IP + 1 > CUR.codeSize )
|
| + if ( CUR.IP + 1 >= CUR.codeSize )
|
| goto LErrorCodeOverflow_;
|
|
|
| CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
|
| @@ -8144,6 +8180,7 @@
|
| callrec->Caller_IP = CUR.IP + 1;
|
| callrec->Cur_Count = 1;
|
| callrec->Cur_Restart = def->start;
|
| + callrec->Cur_End = def->end;
|
|
|
| if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
|
| goto LErrorLabel_;
|
| @@ -8217,7 +8254,7 @@
|
| if ( CUR.error && !CUR.instruction_trap )
|
| {
|
| FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error ));
|
| - exc->size->cvt_ready = FALSE;
|
| + exc->size->cvt_ready = FALSE;
|
| }
|
|
|
| return CUR.error;
|
|
|