summaryrefslogtreecommitdiffstats
path: root/src/truetype/ttinterp.c
diff options
context:
space:
mode:
authorEric Vannier <evannier@google.com>2012-03-22 16:08:33 -0700
committerGeremy Condra <gcondra@google.com>2012-04-20 14:53:55 -0700
commit41371e1e39c8528eb0c4bc40683c736e6683e60c (patch)
treeba563af45d79cd0832305fe3833919bb2475f186 /src/truetype/ttinterp.c
parent27811904d8de0ce5591417812ca31163bf5aad60 (diff)
downloadandroid_external_freetype-41371e1e39c8528eb0c4bc40683c736e6683e60c.tar.gz
android_external_freetype-41371e1e39c8528eb0c4bc40683c736e6683e60c.tar.bz2
android_external_freetype-41371e1e39c8528eb0c4bc40683c736e6683e60c.zip
Update to freetype 2.4.9
This was done by applying the entire 2.4.9 except for the following exceptions: - files that were new, or were not present originally in the version of freetype we were using (meaning that they are present in 2.4.8, and in 2.4.9, but were never integrated into the Android tree because they are not used in the Android tree). - ftmodule.h: given that we support fewer modules than in upstream 2.4.9 (same as Android), the file was left unchanged (and there were no changes from the official 2.4.8 to 2.4.9 - ftoption.h: same reasons as ftmodule.h Change-Id: Id251f2cc5ca1c864f9a4cc0c67b94025ee3ccc4a
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;