summaryrefslogtreecommitdiffstats
path: root/src/truetype/ttinterp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/truetype/ttinterp.c')
-rw-r--r--src/truetype/ttinterp.c192
1 files changed, 108 insertions, 84 deletions
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index c62c589..3acb24a 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 )
@@ -5761,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;
@@ -5786,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 );
+ start = (FT_UShort)( CUR.zp2.contours[contour - 1] + 1 -
+ CUR.zp2.first_point );
- last_point = (FT_UShort)( CUR.pts.contours[contour] -
- CUR.pts.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 );
@@ -5826,7 +5833,7 @@
FT_F26Dot6 dx,
dy;
- FT_UShort last_point, i;
+ FT_UShort limit, i;
if ( BOUNDS( args[0], 2 ) )
@@ -5839,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 );
@@ -6266,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],
@@ -6575,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 );
}
@@ -6601,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 );
@@ -7149,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 );
@@ -7521,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];
@@ -8157,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_;
@@ -8230,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;