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.c248
1 files changed, 160 insertions, 88 deletions
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index d22e94f..d568926 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -4,8 +4,7 @@
/* */
/* TrueType bytecode interpreter (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 */
+/* Copyright 1996-2011 */
/* by David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -478,8 +477,7 @@
return TT_Err_Ok;
Fail_Memory:
- FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
- (FT_Long)exec ));
+ FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
TT_Done_Context( exec );
return error;
@@ -596,6 +594,12 @@
exec->storage = size->storage;
exec->twilight = size->twilight;
+
+ /* In case of multi-threading it can happen that the old size object */
+ /* no longer exists, thus we must clear all glyph zone references. */
+ ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) );
+ exec->zp1 = exec->zp0;
+ exec->zp2 = exec->zp0;
}
/* XXX: We reserve a little more elements on the stack to deal safely */
@@ -981,8 +985,8 @@
/* INS_$83 */ PACK( 0, 0 ),
/* INS_$84 */ PACK( 0, 0 ),
/* ScanCTRL */ PACK( 1, 0 ),
- /* SDVPTL[0] */ PACK( 2, 0 ),
- /* SDVPTL[1] */ PACK( 2, 0 ),
+ /* SDPVTL[0] */ PACK( 2, 0 ),
+ /* SDPVTL[1] */ PACK( 2, 0 ),
/* GetINFO */ PACK( 1, 1 ),
/* IDEF */ PACK( 1, 0 ),
/* ROLL */ PACK( 3, 3 ),
@@ -3162,44 +3166,54 @@
args[0] = CUR.top;
-#define DO_CINDEX \
- { \
- FT_Long L; \
- \
- \
- L = args[0]; \
- \
- if ( L <= 0 || L > CUR.args ) \
- CUR.error = TT_Err_Invalid_Reference; \
- else \
- args[0] = CUR.stack[CUR.args - L]; \
- }
-
-
-#define DO_JROT \
- if ( args[1] != 0 ) \
- { \
- CUR.IP += args[0]; \
- if ( CUR.IP < 0 ) \
- CUR.error = TT_Err_Bad_Argument; \
- CUR.step_ins = FALSE; \
- }
-
-
-#define DO_JMPR \
- CUR.IP += args[0]; \
- if ( CUR.IP < 0 ) \
- CUR.error = TT_Err_Bad_Argument; \
+#define DO_CINDEX \
+ { \
+ FT_Long L; \
+ \
+ \
+ L = args[0]; \
+ \
+ if ( L <= 0 || L > CUR.args ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ CUR.error = TT_Err_Invalid_Reference; \
+ args[0] = 0; \
+ } \
+ else \
+ args[0] = CUR.stack[CUR.args - L]; \
+ }
+
+
+#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_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; \
CUR.step_ins = FALSE;
-#define DO_JROF \
- if ( args[1] == 0 ) \
- { \
- 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.error = TT_Err_Bad_Argument; \
+ CUR.step_ins = FALSE; \
}
@@ -4381,17 +4395,19 @@
if ( L <= 0 || L > CUR.args )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
}
+ else
+ {
+ K = CUR.stack[CUR.args - L];
- K = CUR.stack[CUR.args - L];
-
- FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
- &CUR.stack[CUR.args - L + 1],
- ( L - 1 ) );
+ FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
+ &CUR.stack[CUR.args - L + 1],
+ ( L - 1 ) );
- CUR.stack[CUR.args - 1] = K;
+ CUR.stack[CUR.args - 1] = K;
+ }
}
@@ -5034,12 +5050,8 @@
if ( BOUNDSL( L, CUR.zp2.n_points ) )
{
if ( CUR.pedantic_hinting )
- {
CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- else
- R = 0;
+ R = 0;
}
else
{
@@ -5119,10 +5131,7 @@
BOUNDS( K, CUR.zp1.n_points ) )
{
if ( CUR.pedantic_hinting )
- {
CUR.error = TT_Err_Invalid_Reference;
- return;
- }
D = 0;
}
else
@@ -5460,8 +5469,9 @@
if ( CUR.top < CUR.GS.loop )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ goto Fail;
}
while ( CUR.GS.loop > 0 )
@@ -5484,6 +5494,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5671,8 +5682,9 @@
if ( CUR.top < CUR.GS.loop )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ goto Fail;
}
if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
@@ -5698,6 +5710,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5795,7 +5808,16 @@
if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
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;
+ }
+ }
else
last_point = 0;
@@ -5823,8 +5845,9 @@
if ( CUR.top < CUR.GS.loop + 1 )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ goto Fail;
}
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
@@ -5868,6 +5891,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5982,7 +6006,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
/* XXX: UNDOCUMENTED! */
@@ -6028,6 +6052,7 @@
CUR_Func_move( &CUR.zp0, point, distance - org_dist );
+ Fail:
CUR.GS.rp0 = point;
CUR.GS.rp1 = point;
}
@@ -6053,7 +6078,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
/* XXX: Is there some undocumented feature while in the */
@@ -6138,6 +6163,7 @@
CUR_Func_move( &CUR.zp1, point, distance - org_dist );
+ Fail:
CUR.GS.rp1 = CUR.GS.rp0;
CUR.GS.rp2 = point;
@@ -6175,7 +6201,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
if ( !cvtEntry )
@@ -6230,8 +6256,22 @@
/* refer to the same zone. */
if ( CUR.GS.gep0 == CUR.GS.gep1 )
- if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
+ {
+ /* XXX: According to Greg Hitchcock, the following wording is */
+ /* the right one: */
+ /* */
+ /* When the absolute difference between the value in */
+ /* the table [CVT] and the measurement directly from */
+ /* the outline is _greater_ than the cut_in value, the */
+ /* outline measurement is used. */
+ /* */
+ /* This is from `instgly.doc'. The description in */
+ /* `ttinst2.doc', version 1.66, is thus incorrect since */
+ /* it implies `>=' instead of `>'. */
+
+ if ( FT_ABS( cvt_dist - org_dist ) > CUR.GS.control_value_cutin )
cvt_dist = org_dist;
+ }
distance = CUR_Func_round(
cvt_dist,
@@ -6260,6 +6300,7 @@
CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
+ Fail:
CUR.GS.rp1 = CUR.GS.rp0;
if ( ( CUR.opcode & 16 ) != 0 )
@@ -6290,7 +6331,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
while ( CUR.GS.loop > 0 )
@@ -6318,6 +6359,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -6459,8 +6501,9 @@
if ( CUR.top < CUR.GS.loop )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ goto Fail;
}
/*
@@ -6474,7 +6517,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
if ( twilight )
@@ -6539,6 +6582,8 @@
CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
}
+
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -6773,12 +6818,11 @@
{
if ( ( CUR.pts.tags[point] & mask ) != 0 )
{
- if ( point > 0 )
- _iup_worker_interpolate( &V,
- cur_touched + 1,
- point - 1,
- cur_touched,
- point );
+ _iup_worker_interpolate( &V,
+ cur_touched + 1,
+ point - 1,
+ cur_touched,
+ point );
cur_touched = point;
}
@@ -6832,8 +6876,9 @@
if ( CUR.args < n )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ n = CUR.args;
}
CUR.args -= n;
@@ -6849,8 +6894,10 @@
{
if ( CUR.args < 2 )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ CUR.args = 0;
+ goto Fail;
}
CUR.args -= 2;
@@ -6899,6 +6946,7 @@
CUR.error = TT_Err_Invalid_Reference;
}
+ Fail:
CUR.new_top = CUR.args;
}
@@ -6926,8 +6974,9 @@
if ( CUR.args < n )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ n = CUR.args;
}
CUR.args -= n;
@@ -6942,8 +6991,10 @@
{
if ( CUR.args < 2 )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ CUR.args = 0;
+ goto Fail;
}
CUR.args -= 2;
@@ -6991,6 +7042,7 @@
}
}
+ Fail:
CUR.new_top = CUR.args;
}
@@ -7452,8 +7504,19 @@
/* One can also interpret it as the index of the last argument. */
if ( CUR.args < 0 )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- goto LErrorLabel_;
+ FT_UShort i;
+
+
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ goto LErrorLabel_;
+ }
+
+ /* push zeroes onto the stack */
+ for ( i = 0; i < Pop_Push_Count[CUR.opcode] >> 4; i++ )
+ CUR.stack[i] = 0;
+ CUR.args = 0;
}
CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
@@ -7490,7 +7553,7 @@
case 0x04: /* SFvTCA y */
case 0x05: /* SFvTCA x */
{
- FT_Short AA, BB;
+ FT_Short AA, BB;
AA = (FT_Short)( ( opcode & 1 ) << 14 );
@@ -8128,6 +8191,15 @@
*exc = cur;
#endif
+ /* If any errors have occurred, function tables may be broken. */
+ /* Force a re-execution of `prep' and `fpgm' tables if no */
+ /* bytecode debugger is run. */
+ if ( CUR.error && !CUR.instruction_trap )
+ {
+ FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error ));
+ exc->size->cvt_ready = FALSE;
+ }
+
return CUR.error;
}