summaryrefslogtreecommitdiff
path: root/freetype/src/truetype/ttinterp.c
diff options
context:
space:
mode:
Diffstat (limited to 'freetype/src/truetype/ttinterp.c')
-rw-r--r--freetype/src/truetype/ttinterp.c631
1 files changed, 413 insertions, 218 deletions
diff --git a/freetype/src/truetype/ttinterp.c b/freetype/src/truetype/ttinterp.c
index 2d15ea712..da9b595ab 100644
--- a/freetype/src/truetype/ttinterp.c
+++ b/freetype/src/truetype/ttinterp.c
@@ -4,7 +4,7 @@
/* */
/* TrueType bytecode interpreter (body). */
/* */
-/* Copyright 1996-2016 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,7 +25,7 @@
#include FT_INTERNAL_CALC_H
#include FT_TRIGONOMETRY_H
#include FT_SYSTEM_H
-#include FT_TRUETYPE_DRIVER_H
+#include FT_DRIVER_H
#include FT_MULTIPLE_MASTERS_H
#include "ttinterp.h"
@@ -65,11 +65,15 @@
TT_INTERPRETER_VERSION_40 )
#endif
-#define PROJECT( v1, v2 ) \
- exc->func_project( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
+#define PROJECT( v1, v2 ) \
+ exc->func_project( exc, \
+ SUB_LONG( (v1)->x, (v2)->x ), \
+ SUB_LONG( (v1)->y, (v2)->y ) )
-#define DUALPROJ( v1, v2 ) \
- exc->func_dualproj( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
+#define DUALPROJ( v1, v2 ) \
+ exc->func_dualproj( exc, \
+ SUB_LONG( (v1)->x, (v2)->x ), \
+ SUB_LONG( (v1)->y, (v2)->y ) )
#define FAST_PROJECT( v ) \
exc->func_project( exc, (v)->x, (v)->y )
@@ -129,7 +133,7 @@
coderange = &exec->codeRangeTable[range - 1];
- FT_ASSERT( coderange->base != NULL );
+ FT_ASSERT( coderange->base );
/* NOTE: Because the last instruction of a program may be a CALL */
/* which will return to the first byte *after* the code */
@@ -402,7 +406,7 @@
exec->IDefs = size->instruction_defs;
exec->pointSize = size->point_size;
exec->tt_metrics = size->ttmetrics;
- exec->metrics = size->metrics;
+ exec->metrics = *size->metrics;
exec->maxFunc = size->max_func;
exec->maxIns = size->max_ins;
@@ -423,7 +427,7 @@
/* 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 ) );
+ FT_ZERO( &exec->zp0 );
exec->zp1 = exec->zp0;
exec->zp2 = exec->zp0;
}
@@ -1613,7 +1617,7 @@
range = &exc->codeRangeTable[aRange - 1];
- if ( range->base == NULL ) /* invalid coderange */
+ if ( !range->base ) /* invalid coderange */
{
exc->error = FT_THROW( Invalid_CodeRange );
return FAILURE;
@@ -1656,7 +1660,7 @@
/* zone :: The affected glyph zone. */
/* */
/* <Note> */
- /* See `ttinterp.h' for details on backwards compatibility mode. */
+ /* See `ttinterp.h' for details on backward compatibility mode. */
/* `Touches' the point. */
/* */
static void
@@ -1676,7 +1680,10 @@
if ( SUBPIXEL_HINTING_INFINALITY &&
( !exc->ignore_x_mode ||
( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
- zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
else
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
@@ -1684,13 +1691,19 @@
/* Exception to the post-IUP curfew: Allow the x component of */
/* diagonal moves, but only post-IUP. DejaVu tries to adjust */
/* diagonal stems like on `Z' and `z' post-IUP. */
- if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility )
- zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+ if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility )
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
else
#endif
if ( NO_SUBPIXEL_HINTING )
- zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -1700,12 +1713,15 @@
if ( v != 0 )
{
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( !( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
- exc->iupx_called &&
- exc->iupy_called ) )
+ if ( !( SUBPIXEL_HINTING_MINIMAL &&
+ exc->backward_compatibility &&
+ exc->iupx_called &&
+ exc->iupy_called ) )
#endif
- zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->cur[point].y = ADD_LONG( zone->cur[point].y,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
@@ -1741,12 +1757,18 @@
v = exc->GS.freeVector.x;
if ( v != 0 )
- zone->org[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->org[point].x = ADD_LONG( zone->org[point].x,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
v = exc->GS.freeVector.y;
if ( v != 0 )
- zone->org[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->org[point].y = ADD_LONG( zone->org[point].y,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
}
@@ -1756,7 +1778,7 @@
/* */
/* The following versions are used whenever both vectors are both */
/* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
- /* See `ttinterp.h' for details on backwards compatibility mode. */
+ /* See `ttinterp.h' for details on backward compatibility mode. */
/* */
/*************************************************************************/
@@ -1769,18 +1791,18 @@
{
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode )
- zone->cur[point].x += distance;
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance );
else
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility )
- zone->cur[point].x += distance;
+ if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility )
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance );
else
#endif
if ( NO_SUBPIXEL_HINTING )
- zone->cur[point].x += distance;
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -1796,10 +1818,10 @@
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
if ( !( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
+ exc->backward_compatibility &&
exc->iupx_called && exc->iupy_called ) )
#endif
- zone->cur[point].y += distance;
+ zone->cur[point].y = ADD_LONG( zone->cur[point].y, distance );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
@@ -1823,7 +1845,7 @@
{
FT_UNUSED( exc );
- zone->org[point].x += distance;
+ zone->org[point].x = ADD_LONG( zone->org[point].x, distance );
}
@@ -1835,7 +1857,7 @@
{
FT_UNUSED( exc );
- zone->org[point].y += distance;
+ zone->org[point].y = ADD_LONG( zone->org[point].y, distance );
}
@@ -1873,13 +1895,13 @@
if ( distance >= 0 )
{
- val = distance + compensation;
+ val = ADD_LONG( distance, compensation );
if ( val < 0 )
val = 0;
}
else
{
- val = distance - compensation;
+ val = SUB_LONG( distance, compensation );
if ( val > 0 )
val = 0;
}
@@ -1915,13 +1937,14 @@
if ( distance >= 0 )
{
- val = FT_PIX_ROUND( distance + compensation );
+ val = FT_PIX_ROUND_LONG( ADD_LONG( distance, compensation ) );
if ( val < 0 )
val = 0;
}
else
{
- val = -FT_PIX_ROUND( compensation - distance );
+ val = NEG_LONG( FT_PIX_ROUND_LONG( SUB_LONG( compensation,
+ distance ) ) );
if ( val > 0 )
val = 0;
}
@@ -1958,13 +1981,16 @@
if ( distance >= 0 )
{
- val = FT_PIX_FLOOR( distance + compensation ) + 32;
+ val = ADD_LONG( FT_PIX_FLOOR( ADD_LONG( distance, compensation ) ),
+ 32 );
if ( val < 0 )
val = 32;
}
else
{
- val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
+ val = NEG_LONG( ADD_LONG( FT_PIX_FLOOR( SUB_LONG( compensation,
+ distance ) ),
+ 32 ) );
if ( val > 0 )
val = -32;
}
@@ -2001,13 +2027,13 @@
if ( distance >= 0 )
{
- val = FT_PIX_FLOOR( distance + compensation );
+ val = FT_PIX_FLOOR( ADD_LONG( distance, compensation ) );
if ( val < 0 )
val = 0;
}
else
{
- val = -FT_PIX_FLOOR( compensation - distance );
+ val = NEG_LONG( FT_PIX_FLOOR( SUB_LONG( compensation, distance ) ) );
if ( val > 0 )
val = 0;
}
@@ -2044,13 +2070,14 @@
if ( distance >= 0 )
{
- val = FT_PIX_CEIL( distance + compensation );
+ val = FT_PIX_CEIL_LONG( ADD_LONG( distance, compensation ) );
if ( val < 0 )
val = 0;
}
else
{
- val = -FT_PIX_CEIL( compensation - distance );
+ val = NEG_LONG( FT_PIX_CEIL_LONG( SUB_LONG( compensation,
+ distance ) ) );
if ( val > 0 )
val = 0;
}
@@ -2087,13 +2114,14 @@
if ( distance >= 0 )
{
- val = FT_PAD_ROUND( distance + compensation, 32 );
+ val = FT_PAD_ROUND_LONG( ADD_LONG( distance, compensation ), 32 );
if ( val < 0 )
val = 0;
}
else
{
- val = -FT_PAD_ROUND( compensation - distance, 32 );
+ val = NEG_LONG( FT_PAD_ROUND_LONG( SUB_LONG( compensation, distance ),
+ 32 ) );
if ( val > 0 )
val = 0;
}
@@ -2134,17 +2162,19 @@
if ( distance >= 0 )
{
- val = ( distance - exc->phase + exc->threshold + compensation ) &
+ val = ADD_LONG( distance,
+ exc->threshold - exc->phase + compensation ) &
-exc->period;
- val += exc->phase;
+ val = ADD_LONG( val, exc->phase );
if ( val < 0 )
val = exc->phase;
}
else
{
- val = -( ( exc->threshold - exc->phase - distance + compensation ) &
- -exc->period );
- val -= exc->phase;
+ val = NEG_LONG( SUB_LONG( exc->threshold - exc->phase + compensation,
+ distance ) &
+ -exc->period );
+ val = SUB_LONG( val, exc->phase );
if ( val > 0 )
val = -exc->phase;
}
@@ -2183,17 +2213,19 @@
if ( distance >= 0 )
{
- val = ( ( distance - exc->phase + exc->threshold + compensation ) /
+ val = ( ADD_LONG( distance,
+ exc->threshold - exc->phase + compensation ) /
exc->period ) * exc->period;
- val += exc->phase;
+ val = ADD_LONG( val, exc->phase );
if ( val < 0 )
val = exc->phase;
}
else
{
- val = -( ( ( exc->threshold - exc->phase - distance + compensation ) /
- exc->period ) * exc->period );
- val -= exc->phase;
+ val = NEG_LONG( ( SUB_LONG( exc->threshold - exc->phase + compensation,
+ distance ) /
+ exc->period ) * exc->period );
+ val = SUB_LONG( val, exc->phase );
if ( val > 0 )
val = -exc->phase;
}
@@ -2826,7 +2858,7 @@
static void
Ins_ADD( FT_Long* args )
{
- args[0] += args[1];
+ args[0] = ADD_LONG( args[0], args[1] );
}
@@ -2839,7 +2871,7 @@
static void
Ins_SUB( FT_Long* args )
{
- args[0] -= args[1];
+ args[0] = SUB_LONG( args[0], args[1] );
}
@@ -2882,7 +2914,8 @@
static void
Ins_ABS( FT_Long* args )
{
- args[0] = FT_ABS( args[0] );
+ if ( args[0] < 0 )
+ args[0] = NEG_LONG( args[0] );
}
@@ -2895,7 +2928,7 @@
static void
Ins_NEG( FT_Long* args )
{
- args[0] = -args[0];
+ args[0] = NEG_LONG( args[0] );
}
@@ -2921,7 +2954,7 @@
static void
Ins_CEILING( FT_Long* args )
{
- args[0] = FT_PIX_CEIL( args[0] );
+ args[0] = FT_PIX_CEIL_LONG( args[0] );
}
@@ -3256,7 +3289,10 @@
if ( args[0] < 0 )
exc->error = FT_THROW( Bad_Argument );
else
- exc->GS.loop = args[0];
+ {
+ /* we heuristically limit the number of loops to 16 bits */
+ exc->GS.loop = args[0] > 0xFFFFL ? 0xFFFFL : args[0];
+ }
}
@@ -3388,13 +3424,27 @@
FT_Long* args )
{
if ( args[0] == 0 && exc->args == 0 )
+ {
exc->error = FT_THROW( Bad_Argument );
+ return;
+ }
+
exc->IP += args[0];
if ( exc->IP < 0 ||
( exc->callTop > 0 &&
exc->IP > exc->callStack[exc->callTop - 1].Def->end ) )
+ {
exc->error = FT_THROW( Bad_Argument );
+ return;
+ }
+
exc->step_ins = FALSE;
+
+ if ( args[0] < 0 )
+ {
+ if ( ++exc->neg_jump_counter > exc->neg_jump_counter_max )
+ exc->error = FT_THROW( Execution_Too_Long );
+ }
}
@@ -3550,6 +3600,13 @@
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+ /* FDEF is only allowed in `prep' or `fpgm' */
+ if ( exc->curRange == tt_coderange_glyph )
+ {
+ exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
+ return;
+ }
+
/* some font programs are broken enough to redefine functions! */
/* We will then parse the current table. */
@@ -3949,6 +4006,10 @@
Ins_Goto_CodeRange( exc, def->range, def->start );
exc->step_ins = FALSE;
+
+ exc->loopcall_counter += (FT_ULong)args[0];
+ if ( exc->loopcall_counter > exc->loopcall_counter_max )
+ exc->error = FT_THROW( Execution_Too_Long );
}
return;
@@ -3972,6 +4033,13 @@
TT_DefRecord* limit;
+ /* we enable IDEF only in `prep' or `fpgm' */
+ if ( exc->curRange == tt_coderange_glyph )
+ {
+ exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
+ return;
+ }
+
/* First of all, look for the same function in our table */
def = exc->IDefs;
@@ -4179,8 +4247,8 @@
p1 = exc->zp1.cur + aIdx2;
p2 = exc->zp2.cur + aIdx1;
- A = p1->x - p2->x;
- B = p1->y - p2->y;
+ A = SUB_LONG( p1->x, p2->x );
+ B = SUB_LONG( p1->y, p2->y );
/* If p1 == p2, SPvTL and SFvTL behave the same as */
/* SPvTCA[X] and SFvTCA[X], respectively. */
@@ -4195,9 +4263,9 @@
if ( ( opcode & 1 ) != 0 )
{
- C = B; /* counter clockwise rotation */
- B = A;
- A = -C;
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = NEG_LONG( C );
}
Normalize( A, B, Vec );
@@ -4738,7 +4806,7 @@
K = FAST_PROJECT( &exc->zp2.cur[L] );
- exc->func_move( exc, &exc->zp2, L, args[1] - K );
+ exc->func_move( exc, &exc->zp2, L, SUB_LONG( args[1], K ) );
/* UNDOCUMENTED! The MS rasterizer does that with */
/* twilight points (confirmed by Greg Hitchcock) */
@@ -4862,12 +4930,12 @@
}
{
- FT_Vector* v1 = exc->zp1.org + p2;
- FT_Vector* v2 = exc->zp2.org + p1;
+ FT_Vector* v1 = exc->zp1.org + p2;
+ FT_Vector* v2 = exc->zp2.org + p1;
- A = v1->x - v2->x;
- B = v1->y - v2->y;
+ A = SUB_LONG( v1->x, v2->x );
+ B = SUB_LONG( v1->y, v2->y );
/* If v1 == v2, SDPvTL behaves the same as */
/* SVTCA[X], respectively. */
@@ -4883,9 +4951,9 @@
if ( ( opcode & 1 ) != 0 )
{
- C = B; /* counter clockwise rotation */
- B = A;
- A = -C;
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = NEG_LONG( C );
}
Normalize( A, B, &exc->GS.dualVector );
@@ -4895,8 +4963,8 @@
FT_Vector* v2 = exc->zp2.cur + p1;
- A = v1->x - v2->x;
- B = v1->y - v2->y;
+ A = SUB_LONG( v1->x, v2->x );
+ B = SUB_LONG( v1->y, v2->y );
if ( A == 0 && B == 0 )
{
@@ -4907,9 +4975,9 @@
if ( ( opcode & 1 ) != 0 )
{
- C = B; /* counter clockwise rotation */
- B = A;
- A = -C;
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = NEG_LONG( C );
}
Normalize( A, B, &exc->GS.projVector );
@@ -5094,11 +5162,11 @@
#endif
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* Native ClearType fonts sign a waiver that turns off all backwards */
+ /* Native ClearType fonts sign a waiver that turns off all backward */
/* compatibility hacks and lets them program points to the grid like */
/* it's 1996. They might sign a waiver for just one glyph, though. */
if ( SUBPIXEL_HINTING_MINIMAL )
- exc->backwards_compatibility = !FT_BOOL( L == 4 );
+ exc->backward_compatibility = !FT_BOOL( L == 4 );
#endif
}
}
@@ -5155,14 +5223,14 @@
/* */
/* SCANTYPE[]: SCAN TYPE */
/* Opcode range: 0x8D */
- /* Stack: uint32? --> */
+ /* Stack: uint16 --> */
/* */
static void
Ins_SCANTYPE( TT_ExecContext exc,
FT_Long* args )
{
if ( args[0] >= 0 )
- exc->GS.scan_type = (FT_Int)args[0];
+ exc->GS.scan_type = (FT_Int)args[0] & 0xFFFF;
}
@@ -5186,11 +5254,11 @@
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* See `ttinterp.h' for details on backwards compatibility mode. */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
- exc->iupx_called &&
- exc->iupy_called )
+ /* See `ttinterp.h' for details on backward compatibility mode. */
+ if ( SUBPIXEL_HINTING_MINIMAL &&
+ exc->backward_compatibility &&
+ exc->iupx_called &&
+ exc->iupy_called )
goto Fail;
#endif
@@ -5241,11 +5309,11 @@
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* See `ttinterp.h' for details on backwards compatibility mode. */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
- exc->iupx_called &&
- exc->iupy_called )
+ /* See `ttinterp.h' for details on backward compatibility mode. */
+ if ( SUBPIXEL_HINTING_MINIMAL &&
+ exc->backward_compatibility &&
+ exc->iupx_called &&
+ exc->iupy_called )
return;
#endif
@@ -5279,11 +5347,11 @@
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* See `ttinterp.h' for details on backwards compatibility mode. */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
- exc->iupx_called &&
- exc->iupy_called )
+ /* See `ttinterp.h' for details on backward compatibility mode. */
+ if ( SUBPIXEL_HINTING_MINIMAL &&
+ exc->backward_compatibility &&
+ exc->iupx_called &&
+ exc->iupy_called )
return;
#endif
@@ -5346,7 +5414,7 @@
}
- /* See `ttinterp.h' for details on backwards compatibility mode. */
+ /* See `ttinterp.h' for details on backward compatibility mode. */
static void
Move_Zp2_Point( TT_ExecContext exc,
FT_UShort point,
@@ -5357,10 +5425,10 @@
if ( exc->GS.freeVector.x != 0 )
{
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( !( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility ) )
+ if ( !( SUBPIXEL_HINTING_MINIMAL &&
+ exc->backward_compatibility ) )
#endif
- exc->zp2.cur[point].x += dx;
+ exc->zp2.cur[point].x = ADD_LONG( exc->zp2.cur[point].x, dx );
if ( touch )
exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
@@ -5369,12 +5437,12 @@
if ( exc->GS.freeVector.y != 0 )
{
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( !( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
- exc->iupx_called &&
- exc->iupy_called ) )
+ if ( !( SUBPIXEL_HINTING_MINIMAL &&
+ exc->backward_compatibility &&
+ exc->iupx_called &&
+ exc->iupy_called ) )
#endif
- exc->zp2.cur[point].y += dy;
+ exc->zp2.cur[point].y = ADD_LONG( exc->zp2.cur[point].y, dy );
if ( touch )
exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
@@ -5559,9 +5627,9 @@
FT_Int B1, B2;
#endif
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- FT_Bool in_twilight = exc->GS.gep0 == 0 || \
- exc->GS.gep1 == 0 || \
- exc->GS.gep2 == 0;
+ FT_Bool in_twilight = FT_BOOL( exc->GS.gep0 == 0 ||
+ exc->GS.gep1 == 0 ||
+ exc->GS.gep2 == 0 );
#endif
@@ -5625,7 +5693,11 @@
( B1 & 63 ) != 0 &&
( B2 & 63 ) != 0 &&
B1 != B2 )
- Move_Zp2_Point( exc, point, -dx, -dy, TRUE );
+ Move_Zp2_Point( exc,
+ point,
+ NEG_LONG( dx ),
+ NEG_LONG( dy ),
+ TRUE );
}
}
else if ( exc->face->sph_compatibility_mode )
@@ -5657,7 +5729,7 @@
if ( ( B1 & 63 ) == 0 &&
( B2 & 63 ) != 0 &&
B1 != B2 )
- Move_Zp2_Point( exc, point, 0, -dy, TRUE );
+ Move_Zp2_Point( exc, point, 0, NEG_LONG( dy ), TRUE );
}
}
else if ( exc->sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
@@ -5669,14 +5741,14 @@
else
#endif
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility )
+ if ( SUBPIXEL_HINTING_MINIMAL &&
+ exc->backward_compatibility )
{
/* Special case: allow SHPIX to move points in the twilight zone. */
/* Otherwise, treat SHPIX the same as DELTAP. Unbreaks various */
/* fonts such as older versions of Rokkitt and DTL Argo T Light */
- /* that would glitch severly after calling ALIGNRP after a blocked */
- /* SHPIX. */
+ /* that would glitch severely after calling ALIGNRP after a */
+ /* blocked SHPIX. */
if ( in_twilight ||
( !( exc->iupx_called && exc->iupy_called ) &&
( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
@@ -5713,6 +5785,7 @@
FT_F26Dot6 distance;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
FT_F26Dot6 control_value_cutin = 0;
+ FT_F26Dot6 delta;
if ( SUBPIXEL_HINTING_INFINALITY )
@@ -5748,15 +5821,22 @@
distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+ delta = SUB_LONG( distance, args[1] );
+ if ( delta < 0 )
+ delta = NEG_LONG( delta );
+
/* subpixel hinting - make MSIRP respect CVT cut-in; */
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.freeVector.x != 0 &&
- FT_ABS( distance - args[1] ) >= control_value_cutin )
+ if ( SUBPIXEL_HINTING_INFINALITY &&
+ exc->ignore_x_mode &&
+ exc->GS.freeVector.x != 0 &&
+ delta >= control_value_cutin )
distance = args[1];
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
- exc->func_move( exc, &exc->zp1, point, args[1] - distance );
+ exc->func_move( exc,
+ &exc->zp1,
+ point,
+ SUB_LONG( args[1], distance ) );
exc->GS.rp1 = exc->GS.rp0;
exc->GS.rp2 = point;
@@ -5797,16 +5877,18 @@
if ( SUBPIXEL_HINTING_INFINALITY &&
exc->ignore_x_mode &&
exc->GS.freeVector.x != 0 )
- distance = Round_None(
- exc,
- cur_dist,
- exc->tt_metrics.compensations[0] ) - cur_dist;
+ distance = SUB_LONG(
+ Round_None( exc,
+ cur_dist,
+ exc->tt_metrics.compensations[0] ),
+ cur_dist );
else
#endif
- distance = exc->func_round(
- exc,
- cur_dist,
- exc->tt_metrics.compensations[0] ) - cur_dist;
+ distance = SUB_LONG(
+ exc->func_round( exc,
+ cur_dist,
+ exc->tt_metrics.compensations[0] ),
+ cur_dist );
}
else
distance = 0;
@@ -5906,7 +5988,14 @@
if ( ( exc->opcode & 1 ) != 0 ) /* rounding and control cut-in flag */
{
- if ( FT_ABS( distance - org_dist ) > control_value_cutin )
+ FT_F26Dot6 delta;
+
+
+ delta = SUB_LONG( distance, org_dist );
+ if ( delta < 0 )
+ delta = NEG_LONG( delta );
+
+ if ( delta > control_value_cutin )
distance = org_dist;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
@@ -5923,7 +6012,7 @@
exc->tt_metrics.compensations[0] );
}
- exc->func_move( exc, &exc->zp0, point, distance - org_dist );
+ exc->func_move( exc, &exc->zp0, point, SUB_LONG( distance, org_dist ) );
Fail:
exc->GS.rp0 = point;
@@ -5995,8 +6084,10 @@
FT_Vector vec;
- vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale );
- vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale );
+ vec.x = FT_MulFix( SUB_LONG( vec1->x, vec2->x ),
+ exc->metrics.x_scale );
+ vec.y = FT_MulFix( SUB_LONG( vec1->y, vec2->y ),
+ exc->metrics.y_scale );
org_dist = FAST_DUALPROJ( &vec );
}
@@ -6004,8 +6095,12 @@
/* single width cut-in test */
- if ( FT_ABS( org_dist - exc->GS.single_width_value ) <
- exc->GS.single_width_cutin )
+ /* |org_dist - single_width_value| < single_width_cutin */
+ if ( exc->GS.single_width_cutin > 0 &&
+ org_dist < exc->GS.single_width_value +
+ exc->GS.single_width_cutin &&
+ org_dist > exc->GS.single_width_value -
+ exc->GS.single_width_cutin )
{
if ( org_dist >= 0 )
org_dist = exc->GS.single_width_value;
@@ -6049,8 +6144,8 @@
}
else
{
- if ( distance > -minimum_distance )
- distance = -minimum_distance;
+ if ( distance > NEG_LONG( minimum_distance ) )
+ distance = NEG_LONG( minimum_distance );
}
}
@@ -6058,7 +6153,7 @@
org_dist = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
- exc->func_move( exc, &exc->zp1, point, distance - org_dist );
+ exc->func_move( exc, &exc->zp1, point, SUB_LONG( distance, org_dist ) );
Fail:
exc->GS.rp1 = exc->GS.rp0;
@@ -6098,7 +6193,7 @@
minimum_distance = exc->GS.minimum_distance;
control_value_cutin = exc->GS.control_value_cutin;
point = (FT_UShort)args[0];
- cvtEntry = (FT_ULong)( args[1] + 1 );
+ cvtEntry = (FT_ULong)( ADD_LONG( args[1], 1 ) );
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( SUBPIXEL_HINTING_INFINALITY &&
@@ -6181,6 +6276,9 @@
if ( exc->GS.gep0 == exc->GS.gep1 )
{
+ FT_F26Dot6 delta;
+
+
/* XXX: According to Greg Hitchcock, the following wording is */
/* the right one: */
/* */
@@ -6193,7 +6291,11 @@
/* `ttinst2.doc', version 1.66, is thus incorrect since */
/* it implies `>=' instead of `>'. */
- if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
+ delta = SUB_LONG( cvt_dist, org_dist );
+ if ( delta < 0 )
+ delta = NEG_LONG( delta );
+
+ if ( delta > control_value_cutin )
cvt_dist = org_dist;
}
@@ -6211,7 +6313,14 @@
exc->ignore_x_mode &&
exc->GS.gep0 == exc->GS.gep1 )
{
- if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
+ FT_F26Dot6 delta;
+
+
+ delta = SUB_LONG( cvt_dist, org_dist );
+ if ( delta < 0 )
+ delta = NEG_LONG( delta );
+
+ if ( delta > control_value_cutin )
cvt_dist = org_dist;
}
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
@@ -6233,8 +6342,8 @@
}
else
{
- if ( distance > -minimum_distance )
- distance = -minimum_distance;
+ if ( distance > NEG_LONG( minimum_distance ) )
+ distance = NEG_LONG( minimum_distance );
}
}
@@ -6258,7 +6367,10 @@
}
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
- exc->func_move( exc, &exc->zp1, point, distance - cur_dist );
+ exc->func_move( exc,
+ &exc->zp1,
+ point,
+ SUB_LONG( distance, cur_dist ) );
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( SUBPIXEL_HINTING_INFINALITY )
@@ -6282,7 +6394,10 @@
}
if ( reverse_move )
- exc->func_move( exc, &exc->zp1, point, -( distance - cur_dist ) );
+ exc->func_move( exc,
+ &exc->zp1,
+ point,
+ SUB_LONG( cur_dist, distance ) );
}
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
@@ -6348,7 +6463,7 @@
distance = PROJECT( exc->zp1.cur + point,
exc->zp0.cur + exc->GS.rp0 );
- exc->func_move( exc, &exc->zp1, point, -distance );
+ exc->func_move( exc, &exc->zp1, point, NEG_LONG( distance ) );
}
exc->GS.loop--;
@@ -6405,19 +6520,19 @@
/* Cramer's rule */
- dbx = exc->zp0.cur[b1].x - exc->zp0.cur[b0].x;
- dby = exc->zp0.cur[b1].y - exc->zp0.cur[b0].y;
+ dbx = SUB_LONG( exc->zp0.cur[b1].x, exc->zp0.cur[b0].x );
+ dby = SUB_LONG( exc->zp0.cur[b1].y, exc->zp0.cur[b0].y );
- dax = exc->zp1.cur[a1].x - exc->zp1.cur[a0].x;
- day = exc->zp1.cur[a1].y - exc->zp1.cur[a0].y;
+ dax = SUB_LONG( exc->zp1.cur[a1].x, exc->zp1.cur[a0].x );
+ day = SUB_LONG( exc->zp1.cur[a1].y, exc->zp1.cur[a0].y );
- dx = exc->zp0.cur[b0].x - exc->zp1.cur[a0].x;
- dy = exc->zp0.cur[b0].y - exc->zp1.cur[a0].y;
+ dx = SUB_LONG( exc->zp0.cur[b0].x, exc->zp1.cur[a0].x );
+ dy = SUB_LONG( exc->zp0.cur[b0].y, exc->zp1.cur[a0].y );
- discriminant = FT_MulDiv( dax, -dby, 0x40 ) +
- FT_MulDiv( day, dbx, 0x40 );
- dotproduct = FT_MulDiv( dax, dbx, 0x40 ) +
- FT_MulDiv( day, dby, 0x40 );
+ discriminant = ADD_LONG( FT_MulDiv( dax, NEG_LONG( dby ), 0x40 ),
+ FT_MulDiv( day, dbx, 0x40 ) );
+ dotproduct = ADD_LONG( FT_MulDiv( dax, dbx, 0x40 ),
+ FT_MulDiv( day, dby, 0x40 ) );
/* The discriminant above is actually a cross product of vectors */
/* da and db. Together with the dot product, they can be used as */
@@ -6427,30 +6542,29 @@
/* discriminant = |da||db|sin(angle) . */
/* We use these equations to reject grazing intersections by */
/* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */
- if ( 19 * FT_ABS( discriminant ) > FT_ABS( dotproduct ) )
+ if ( MUL_LONG( 19, FT_ABS( discriminant ) ) > FT_ABS( dotproduct ) )
{
- val = FT_MulDiv( dx, -dby, 0x40 ) + FT_MulDiv( dy, dbx, 0x40 );
+ val = ADD_LONG( FT_MulDiv( dx, NEG_LONG( dby ), 0x40 ),
+ FT_MulDiv( dy, dbx, 0x40 ) );
R.x = FT_MulDiv( val, dax, discriminant );
R.y = FT_MulDiv( val, day, discriminant );
- /* XXX: Block in backwards_compatibility and/or post-IUP? */
- exc->zp2.cur[point].x = exc->zp1.cur[a0].x + R.x;
- exc->zp2.cur[point].y = exc->zp1.cur[a0].y + R.y;
+ /* XXX: Block in backward_compatibility and/or post-IUP? */
+ exc->zp2.cur[point].x = ADD_LONG( exc->zp1.cur[a0].x, R.x );
+ exc->zp2.cur[point].y = ADD_LONG( exc->zp1.cur[a0].y, R.y );
}
else
{
/* else, take the middle of the middles of A and B */
- /* XXX: Block in backwards_compatibility and/or post-IUP? */
- exc->zp2.cur[point].x = ( exc->zp1.cur[a0].x +
- exc->zp1.cur[a1].x +
- exc->zp0.cur[b0].x +
- exc->zp0.cur[b1].x ) / 4;
- exc->zp2.cur[point].y = ( exc->zp1.cur[a0].y +
- exc->zp1.cur[a1].y +
- exc->zp0.cur[b0].y +
- exc->zp0.cur[b1].y ) / 4;
+ /* XXX: Block in backward_compatibility and/or post-IUP? */
+ exc->zp2.cur[point].x =
+ ADD_LONG( ADD_LONG( exc->zp1.cur[a0].x, exc->zp1.cur[a1].x ),
+ ADD_LONG( exc->zp0.cur[b0].x, exc->zp0.cur[b1].x ) ) / 4;
+ exc->zp2.cur[point].y =
+ ADD_LONG( ADD_LONG( exc->zp1.cur[a0].y, exc->zp1.cur[a1].y ),
+ ADD_LONG( exc->zp0.cur[b0].y, exc->zp0.cur[b1].y ) ) / 4;
}
exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
@@ -6485,7 +6599,7 @@
distance = PROJECT( exc->zp0.cur + p2, exc->zp1.cur + p1 ) / 2;
exc->func_move( exc, &exc->zp1, p1, distance );
- exc->func_move( exc, &exc->zp0, p2, -distance );
+ exc->func_move( exc, &exc->zp0, p2, NEG_LONG( distance ) );
}
@@ -6519,7 +6633,9 @@
* Otherwise, by definition, the value of exc->twilight.orus[n] is (0,0),
* for every n.
*/
- twilight = exc->GS.gep0 == 0 || exc->GS.gep1 == 0 || exc->GS.gep2 == 0;
+ twilight = ( exc->GS.gep0 == 0 ||
+ exc->GS.gep1 == 0 ||
+ exc->GS.gep2 == 0 );
if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) )
{
@@ -6556,9 +6672,11 @@
FT_Vector vec;
- vec.x = FT_MulFix( exc->zp1.orus[exc->GS.rp2].x - orus_base->x,
+ vec.x = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].x,
+ orus_base->x ),
exc->metrics.x_scale );
- vec.y = FT_MulFix( exc->zp1.orus[exc->GS.rp2].y - orus_base->y,
+ vec.y = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].y,
+ orus_base->y ),
exc->metrics.y_scale );
old_range = FAST_DUALPROJ( &vec );
@@ -6567,7 +6685,7 @@
cur_range = PROJECT( &exc->zp1.cur[exc->GS.rp2], cur_base );
}
- for ( ; exc->GS.loop > 0; --exc->GS.loop )
+ for ( ; exc->GS.loop > 0; exc->GS.loop-- )
{
FT_UInt point = (FT_UInt)exc->stack[--exc->args];
FT_F26Dot6 org_dist, cur_dist, new_dist;
@@ -6593,9 +6711,11 @@
FT_Vector vec;
- vec.x = FT_MulFix( exc->zp2.orus[point].x - orus_base->x,
+ vec.x = FT_MulFix( SUB_LONG( exc->zp2.orus[point].x,
+ orus_base->x ),
exc->metrics.x_scale );
- vec.y = FT_MulFix( exc->zp2.orus[point].y - orus_base->y,
+ vec.y = FT_MulFix( SUB_LONG( exc->zp2.orus[point].y,
+ orus_base->y ),
exc->metrics.y_scale );
org_dist = FAST_DUALPROJ( &vec );
@@ -6634,7 +6754,7 @@
exc->func_move( exc,
&exc->zp2,
(FT_UShort)point,
- new_dist - cur_dist );
+ SUB_LONG( new_dist, cur_dist ) );
}
Fail:
@@ -6699,14 +6819,14 @@
FT_F26Dot6 dx;
- dx = worker->curs[p].x - worker->orgs[p].x;
+ dx = SUB_LONG( worker->curs[p].x, worker->orgs[p].x );
if ( dx != 0 )
{
for ( i = p1; i < p; i++ )
- worker->curs[i].x += dx;
+ worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx );
for ( i = p + 1; i <= p2; i++ )
- worker->curs[i].x += dx;
+ worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx );
}
}
@@ -6751,8 +6871,8 @@
org2 = worker->orgs[ref2].x;
cur1 = worker->curs[ref1].x;
cur2 = worker->curs[ref2].x;
- delta1 = cur1 - org1;
- delta2 = cur2 - org2;
+ delta1 = SUB_LONG( cur1, org1 );
+ delta2 = SUB_LONG( cur2, org2 );
if ( cur1 == cur2 || orus1 == orus2 )
{
@@ -6764,10 +6884,10 @@
if ( x <= org1 )
- x += delta1;
+ x = ADD_LONG( x, delta1 );
else if ( x >= org2 )
- x += delta2;
+ x = ADD_LONG( x, delta2 );
else
x = cur1;
@@ -6788,20 +6908,23 @@
if ( x <= org1 )
- x += delta1;
+ x = ADD_LONG( x, delta1 );
else if ( x >= org2 )
- x += delta2;
+ x = ADD_LONG( x, delta2 );
else
{
if ( !scale_valid )
{
scale_valid = 1;
- scale = FT_DivFix( cur2 - cur1, orus2 - orus1 );
+ scale = FT_DivFix( SUB_LONG( cur2, cur1 ),
+ SUB_LONG( orus2, orus1 ) );
}
- x = cur1 + FT_MulFix( worker->orus[i].x - orus1, scale );
+ x = ADD_LONG( cur1,
+ FT_MulFix( SUB_LONG( worker->orus[i].x, orus1 ),
+ scale ) );
}
worker->curs[i].x = x;
}
@@ -6832,11 +6955,11 @@
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* See `ttinterp.h' for details on backwards compatibility mode. */
+ /* See `ttinterp.h' for details on backward compatibility mode. */
/* Allow IUP until it has been called on both axes. Immediately */
/* return on subsequent ones. */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility )
+ if ( SUBPIXEL_HINTING_MINIMAL &&
+ exc->backward_compatibility )
{
if ( exc->iupx_called && exc->iupy_called )
return;
@@ -7069,7 +7192,7 @@
SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) &&
( B1 & 63 ) != 0 &&
( B2 & 63 ) != 0 ) ) )
- exc->func_move( exc, &exc->zp0, A, -B );
+ exc->func_move( exc, &exc->zp0, A, NEG_LONG( B ) );
}
}
else
@@ -7078,10 +7201,10 @@
{
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* See `ttinterp.h' for details on backwards compatibility */
- /* mode. */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility )
+ /* See `ttinterp.h' for details on backward compatibility */
+ /* mode. */
+ if ( SUBPIXEL_HINTING_MINIMAL &&
+ exc->backward_compatibility )
{
if ( !( exc->iupx_called && exc->iupy_called ) &&
( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
@@ -7225,7 +7348,7 @@
{
if ( exc->ignore_x_mode )
{
- /* if in ClearType backwards compatibility mode, */
+ /* if in ClearType backward compatibility mode, */
/* we sometimes change the TrueType version dynamically */
K = exc->rasterizer_version;
FT_TRACE6(( "Setting rasterizer version %d\n",
@@ -7276,7 +7399,11 @@
K |= 1 << 12;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( SUBPIXEL_HINTING_MINIMAL )
+ /* Toggle the following flags only outside of monochrome mode. */
+ /* Otherwise, instructions may behave weirdly and rendering results */
+ /* may differ between v35 and v40 mode, e.g., in `Times New Roman */
+ /* Bold Italic'. */
+ if ( SUBPIXEL_HINTING_MINIMAL && exc->subpixel_hinting_lean )
{
/********************************/
/* HINTING FOR SUBPIXEL */
@@ -7311,7 +7438,7 @@
/* */
/* The only smoothing method FreeType supports unless someone sets */
/* FT_LOAD_TARGET_MONO. */
- if ( ( args[0] & 2048 ) != 0 )
+ if ( ( args[0] & 2048 ) != 0 && exc->subpixel_hinting_lean )
K |= 1 << 18;
/********************************/
@@ -7436,8 +7563,16 @@
return;
}
- for ( i = 0; i < num_axes; i++ )
- args[i] = coords[i] >> 2; /* convert 16.16 to 2.14 format */
+ if ( coords )
+ {
+ for ( i = 0; i < num_axes; i++ )
+ args[i] = coords[i] >> 2; /* convert 16.16 to 2.14 format */
+ }
+ else
+ {
+ for ( i = 0; i < num_axes; i++ )
+ args[i] = 0;
+ }
}
@@ -7532,7 +7667,8 @@
FT_EXPORT_DEF( FT_Error )
TT_RunIns( TT_ExecContext exc )
{
- FT_Long ins_counter = 0; /* executed instructions counter */
+ FT_ULong ins_counter = 0; /* executed instructions counter */
+ FT_ULong num_twilight_points;
FT_UShort i;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
@@ -7554,20 +7690,81 @@
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* Toggle backwards compatibility according to what font says, except */
- /* when it's a `tricky' font that heavily relies on the interpreter to */
- /* render glyphs correctly, e.g. DFKai-SB. Backwards compatibility */
- /* hacks may break it. */
+ /*
+ * Toggle backward compatibility according to what font wants, except
+ * when
+ *
+ * 1) we have a `tricky' font that heavily relies on the interpreter to
+ * render glyphs correctly, for example DFKai-SB, or
+ * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
+ *
+ * In those cases, backward compatibility needs to be turned off to get
+ * correct rendering. The rendering is then completely up to the
+ * font's programming.
+ *
+ */
if ( SUBPIXEL_HINTING_MINIMAL &&
+ exc->subpixel_hinting_lean &&
!FT_IS_TRICKY( &exc->face->root ) )
- exc->backwards_compatibility = !( exc->GS.instruct_control & 4 );
+ exc->backward_compatibility = !( exc->GS.instruct_control & 4 );
else
- exc->backwards_compatibility = FALSE;
+ exc->backward_compatibility = FALSE;
exc->iupx_called = FALSE;
exc->iupy_called = FALSE;
#endif
+ /* We restrict the number of twilight points to a reasonable, */
+ /* heuristic value to avoid slow execution of malformed bytecode. */
+ num_twilight_points = FT_MAX( 30,
+ 2 * ( exc->pts.n_points + exc->cvtSize ) );
+ if ( exc->twilight.n_points > num_twilight_points )
+ {
+ if ( num_twilight_points > 0xFFFFU )
+ num_twilight_points = 0xFFFFU;
+
+ FT_TRACE5(( "TT_RunIns: Resetting number of twilight points\n"
+ " from %d to the more reasonable value %d\n",
+ exc->twilight.n_points,
+ num_twilight_points ));
+ exc->twilight.n_points = (FT_UShort)num_twilight_points;
+ }
+
+ /* Set up loop detectors. We restrict the number of LOOPCALL loops */
+ /* and the number of JMPR, JROT, and JROF calls with a negative */
+ /* argument to values that depend on various parameters like the */
+ /* size of the CVT table or the number of points in the current */
+ /* glyph (if applicable). */
+ /* */
+ /* The idea is that in real-world bytecode you either iterate over */
+ /* all CVT entries (in the `prep' table), or over all points (or */
+ /* contours, in the `glyf' table) of a glyph, and such iterations */
+ /* don't happen very often. */
+ exc->loopcall_counter = 0;
+ exc->neg_jump_counter = 0;
+
+ /* The maximum values are heuristic. */
+ if ( exc->pts.n_points )
+ exc->loopcall_counter_max = FT_MAX( 50,
+ 10 * exc->pts.n_points ) +
+ FT_MAX( 50,
+ exc->cvtSize / 10 );
+ else
+ exc->loopcall_counter_max = 300 + 8 * exc->cvtSize;
+
+ /* as a protection against an unreasonable number of CVT entries */
+ /* we assume at most 100 control values per glyph for the counter */
+ if ( exc->loopcall_counter_max >
+ 100 * (FT_ULong)exc->face->root.num_glyphs )
+ exc->loopcall_counter_max = 100 * (FT_ULong)exc->face->root.num_glyphs;
+
+ FT_TRACE5(( "TT_RunIns: Limiting total number of loops in LOOPCALL"
+ " to %d\n", exc->loopcall_counter_max ));
+
+ exc->neg_jump_counter_max = exc->loopcall_counter_max;
+ FT_TRACE5(( "TT_RunIns: Limiting total number of backward jumps"
+ " to %d\n", exc->neg_jump_counter_max ));
+
/* set PPEM and CVT functions */
exc->tt_metrics.ratio = 0;
if ( exc->metrics.x_ppem != exc->metrics.y_ppem )
@@ -8328,29 +8525,27 @@
} while ( !exc->instruction_trap );
LNo_Error_:
+ FT_TRACE4(( " %d instruction%s executed\n",
+ ins_counter,
+ ins_counter == 1 ? "" : "s" ));
return FT_Err_Ok;
LErrorCodeOverflow_:
exc->error = FT_THROW( Code_Overflow );
LErrorLabel_:
- /* 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 ( exc->error &&
- !exc->instruction_trap &&
- exc->curRange == tt_coderange_glyph )
- {
+ if ( exc->error && !exc->instruction_trap )
FT_TRACE1(( " The interpreter returned error 0x%x\n", exc->error ));
- exc->size->bytecode_ready = -1;
- exc->size->cvt_ready = -1;
- }
return exc->error;
}
+#else /* !TT_USE_BYTECODE_INTERPRETER */
+
+ /* ANSI C doesn't like empty source files */
+ typedef int _tt_interp_dummy;
-#endif /* TT_USE_BYTECODE_INTERPRETER */
+#endif /* !TT_USE_BYTECODE_INTERPRETER */
/* END */