summaryrefslogtreecommitdiffstats
path: root/src/truetype
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2011-08-17 18:21:28 +0200
committerDavid 'Digit' Turner <digit@google.com>2011-08-17 18:25:40 +0200
commitaeb407daf3711a10a27f3bc2223c5eb05158076e (patch)
tree570010914e8c91992ea388f2319611655c7d4b0c /src/truetype
parent3053d1b9db55099918843889e4809ce97483ca9f (diff)
downloadandroid_external_freetype-aeb407daf3711a10a27f3bc2223c5eb05158076e.tar.gz
android_external_freetype-aeb407daf3711a10a27f3bc2223c5eb05158076e.tar.bz2
android_external_freetype-aeb407daf3711a10a27f3bc2223c5eb05158076e.zip
Update to FreeType 2.4.6+
This patch updates our copy of the FreeType sources to 2.4.6+. More precisely, it contains source code corresponding to the state of the upstream repository at the following hash submitted on August 16 2001: c3fb981e2ac79acad09d5673352646696472f55e This corresponds to 2.4.6 with 7 more patches applied on top of it to fix bugs in the TrueType interpreter and the CFF parser. Change-Id: I9f3ac736d616020c8d10fd1d4e4be466f35fb6e7
Diffstat (limited to 'src/truetype')
-rw-r--r--src/truetype/ttdriver.c12
-rw-r--r--src/truetype/ttgload.c53
-rw-r--r--src/truetype/ttgload.h4
-rw-r--r--src/truetype/ttgxvar.c6
-rw-r--r--src/truetype/ttinterp.c318
-rw-r--r--src/truetype/ttobjs.c206
-rw-r--r--src/truetype/ttobjs.h11
-rw-r--r--src/truetype/ttpload.c13
8 files changed, 403 insertions, 220 deletions
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index d723b57..e70a611 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -4,8 +4,7 @@
/* */
/* TrueType font driver implementation (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -135,8 +134,6 @@
{
FT_UInt nn;
TT_Face face = (TT_Face) ttface;
- FT_Bool check = FT_BOOL(
- !( flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) );
/* XXX: TODO: check for sbits */
@@ -149,7 +146,7 @@
FT_UShort ah;
- TT_Get_VMetrics( face, start + nn, check, &tsb, &ah );
+ TT_Get_VMetrics( face, start + nn, &tsb, &ah );
advances[nn] = ah;
}
}
@@ -161,7 +158,7 @@
FT_UShort aw;
- TT_Get_HMetrics( face, start + nn, check, &lsb, &aw );
+ TT_Get_HMetrics( face, start + nn, &lsb, &aw );
advances[nn] = aw;
}
}
@@ -249,7 +246,10 @@
FT_Request_Metrics( size->face, req );
if ( FT_IS_SCALABLE( size->face ) )
+ {
error = tt_size_reset( ttsize );
+ ttsize->root.metrics = ttsize->metrics;
+ }
return error;
}
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 3a69b7b..f35521e 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -4,8 +4,7 @@
/* */
/* TrueType Glyph Loader (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -47,7 +46,7 @@
/*************************************************************************/
/* */
- /* Composite font flags. */
+ /* Composite glyph flags. */
/* */
#define ARGS_ARE_WORDS 0x0001
#define ARGS_ARE_XY_VALUES 0x0002
@@ -66,22 +65,16 @@
/*************************************************************************/
/* */
- /* Returns the horizontal metrics in font units for a given glyph. If */
- /* `check' is true, take care of monospaced fonts by returning the */
- /* advance width maximum. */
+ /* Return the horizontal metrics in font units for a given glyph. */
/* */
FT_LOCAL_DEF( void )
TT_Get_HMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* lsb,
FT_UShort* aw )
{
( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
- if ( check && face->postscript.isFixedPitch )
- *aw = face->horizontal.advance_Width_Max;
-
FT_TRACE5(( " advance width (font units): %d\n", *aw ));
FT_TRACE5(( " left side bearing (font units): %d\n", *lsb ));
}
@@ -89,7 +82,7 @@
/*************************************************************************/
/* */
- /* Returns the vertical metrics in font units for a given glyph. */
+ /* Return the vertical metrics in font units for a given glyph. */
/* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
/* table, typoAscender/Descender from the `OS/2' table would be used */
/* instead, and if there were no `OS/2' table, use ascender/descender */
@@ -97,18 +90,12 @@
/* apparently does: It uses the ppem value as the advance height, and */
/* sets the top side bearing to be zero. */
/* */
- /* The monospace `check' is probably not meaningful here, but we leave */
- /* it in for a consistent interface. */
- /* */
FT_LOCAL_DEF( void )
TT_Get_VMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* tsb,
FT_UShort* ah )
{
- FT_UNUSED( check );
-
if ( face->vertical_info )
( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
@@ -151,13 +138,9 @@
TT_Get_HMetrics( face, glyph_index,
- (FT_Bool)!( loader->load_flags &
- FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
&left_bearing,
&advance_width );
TT_Get_VMetrics( face, glyph_index,
- (FT_Bool)!( loader->load_flags &
- FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
&top_bearing,
&advance_height );
@@ -1656,23 +1639,7 @@
/* get the device-independent horizontal advance; it is scaled later */
/* by the base layer. */
- {
- FT_Pos advance = loader->linear;
-
-
- /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
- /* correctly support DynaLab fonts, which have an incorrect */
- /* `advance_Width_Max' field! It is used, to my knowledge, */
- /* exclusively in the X-TrueType font server. */
- /* */
- if ( face->postscript.isFixedPitch &&
- ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
- advance = face->horizontal.advance_Width_Max;
-
- /* we need to return the advance in font units in linearHoriAdvance, */
- /* it will be scaled later by the base layer. */
- glyph->linearHoriAdvance = advance;
- }
+ glyph->linearHoriAdvance = loader->linear;
glyph->metrics.horiBearingX = bbox.xMin;
glyph->metrics.horiBearingY = bbox.yMax;
@@ -1869,6 +1836,7 @@
{
TT_Face face;
FT_Stream stream;
+ FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
face = (TT_Face)glyph->face;
@@ -1887,7 +1855,9 @@
if ( !size->cvt_ready )
{
- FT_Error error = tt_size_ready_bytecode( size );
+ FT_Error error = tt_size_ready_bytecode( size, pedantic );
+
+
if ( error )
return error;
}
@@ -1917,7 +1887,7 @@
for ( i = 0; i < size->cvt_size; i++ )
size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
- tt_size_run_prep( size );
+ tt_size_run_prep( size, pedantic );
}
/* see whether the cvt program has disabled hinting */
@@ -2047,9 +2017,6 @@
glyph->linearHoriAdvance = loader.linear;
glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
loader.vadvance;
- if ( face->postscript.isFixedPitch &&
- ( load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
- glyph->linearHoriAdvance = face->horizontal.advance_Width_Max;
}
return TT_Err_Ok;
diff --git a/src/truetype/ttgload.h b/src/truetype/ttgload.h
index 958d67d..05f7588 100644
--- a/src/truetype/ttgload.h
+++ b/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
/* */
/* TrueType Glyph Loader (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008 by */
+/* Copyright 1996-2006, 2008, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -37,14 +37,12 @@ FT_BEGIN_HEADER
FT_LOCAL( void )
TT_Get_HMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* lsb,
FT_UShort* aw );
FT_LOCAL( void )
TT_Get_VMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* tsb,
FT_UShort* ah );
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 47bb9fc..37bbe6d 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -123,7 +123,7 @@
ft_var_readpackedpoints( FT_Stream stream,
FT_UInt *point_cnt )
{
- FT_UShort *points;
+ FT_UShort *points = NULL;
FT_Int n;
FT_Int runcnt;
FT_Int i;
@@ -622,7 +622,7 @@
FT_Error error = TT_Err_Ok;
FT_ULong fvar_start;
FT_Int i, j;
- FT_MM_Var* mmvar;
+ FT_MM_Var* mmvar = NULL;
FT_Fixed* next_coords;
FT_String* next_name;
FT_Var_Axis* a;
@@ -1325,7 +1325,7 @@
FT_Stream stream = face->root.stream;
FT_Memory memory = stream->memory;
GX_Blend blend = face->blend;
- FT_Vector* delta_xy;
+ FT_Vector* delta_xy = NULL;
FT_Error error;
FT_ULong glyph_start;
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index f55b8ee..6c4eed6 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, */
@@ -17,6 +16,10 @@
/***************************************************************************/
+/* Greg Hitchcock from Microsoft has helped a lot in resolving unclear */
+/* issues; many thanks! */
+
+
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_CALC_H
@@ -665,9 +668,9 @@
FT_Int i;
- /* XXXX: Will probably disappear soon with all the code range */
- /* management, which is now rather obsolete. */
- /* */
+ /* XXX: Will probably disappear soon with all the code range */
+ /* management, which is now rather obsolete. */
+ /* */
size->num_function_defs = exec->numFDefs;
size->num_instruction_defs = exec->numIDefs;
@@ -986,8 +989,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 ),
@@ -2842,6 +2845,17 @@
A = p1->x - p2->x;
B = p1->y - p2->y;
+ /* If p1 == p2, SPVTL and SFVTL behave the same as */
+ /* SPVTCA[X] and SFVTCA[X], respectively. */
+ /* */
+ /* Confirmed by Greg Hitchcock. */
+
+ if ( A == 0 && B == 0 )
+ {
+ A = 0x4000;
+ aOpc = 0;
+ }
+
if ( ( aOpc & 1 ) != 0 )
{
C = B; /* counter clockwise rotation */
@@ -3167,44 +3181,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; \
}
@@ -4386,17 +4410,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;
+ }
}
@@ -5039,12 +5065,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
{
@@ -5088,8 +5110,8 @@
CUR_Func_move( &CUR.zp2, L, args[1] - K );
- /* not part of the specs, but here for safety */
-
+ /* UNDOCUMENTED! The MS rasterizer does that with */
+ /* twilight points (confirmed by Greg Hitchcock) */
if ( CUR.GS.gep2 == 0 )
CUR.zp2.org[L] = CUR.zp2.cur[L];
}
@@ -5124,10 +5146,7 @@
BOUNDS( K, CUR.zp1.n_points ) )
{
if ( CUR.pedantic_hinting )
- {
CUR.error = TT_Err_Invalid_Reference;
- return;
- }
D = 0;
}
else
@@ -5173,7 +5192,8 @@
Ins_SDPVTL( INS_ARG )
{
FT_Long A, B, C;
- FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
+ FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
+ FT_Int aOpc = CUR.opcode;
p1 = (FT_UShort)args[1];
@@ -5194,9 +5214,20 @@
A = v1->x - v2->x;
B = v1->y - v2->y;
+
+ /* If v1 == v2, SDPVTL behaves the same as */
+ /* SVTCA[X], respectively. */
+ /* */
+ /* Confirmed by Greg Hitchcock. */
+
+ if ( A == 0 && B == 0 )
+ {
+ A = 0x4000;
+ aOpc = 0;
+ }
}
- if ( ( CUR.opcode & 1 ) != 0 )
+ if ( ( aOpc & 1 ) != 0 )
{
C = B; /* counter clockwise rotation */
B = A;
@@ -5214,7 +5245,7 @@
B = v1->y - v2->y;
}
- if ( ( CUR.opcode & 1 ) != 0 )
+ if ( ( aOpc & 1 ) != 0 )
{
C = B; /* counter clockwise rotation */
B = A;
@@ -5465,8 +5496,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 )
@@ -5489,6 +5521,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5676,8 +5709,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 ) )
@@ -5697,12 +5731,12 @@
}
}
else
- /* XXX: UNDOCUMENTED! SHP touches the points */
MOVE_Zp2_Point( point, dx, dy, TRUE );
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5757,7 +5791,6 @@
last_point = 0;
}
- /* XXX: UNDOCUMENTED! SHC touches the points */
for ( i = first_point; i <= last_point; i++ )
{
if ( zp.cur != CUR.zp2.cur || refp != i )
@@ -5837,8 +5870,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
@@ -5882,6 +5916,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5910,9 +5945,9 @@
return;
}
- /* XXX: UNDOCUMENTED! behaviour */
- if ( CUR.GS.gep1 == 0 ) /* if the point that is to be moved */
- /* is in twilight zone */
+ /* UNDOCUMENTED! The MS rasterizer does that with */
+ /* twilight points (confirmed by Greg Hitchcock) */
+ if ( CUR.GS.gep1 == 0 )
{
CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
CUR_Func_move_orig( &CUR.zp1, point, args[1] );
@@ -5955,8 +5990,6 @@
return;
}
- /* XXX: Is there some undocumented feature while in the */
- /* twilight zone? ? */
if ( ( CUR.opcode & 1 ) != 0 )
{
cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
@@ -5996,37 +6029,37 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
- /* XXX: UNDOCUMENTED! */
- /* */
- /* The behaviour of an MIAP instruction is quite */
- /* different when used in the twilight zone. */
- /* */
- /* First, no control value cut-in test is performed */
- /* as it would fail anyway. Second, the original */
- /* point, i.e. (org_x,org_y) of zp0.point, is set */
- /* to the absolute, unrounded distance found in */
- /* the CVT. */
- /* */
- /* This is used in the CVT programs of the Microsoft */
- /* fonts Arial, Times, etc., in order to re-adjust */
- /* some key font heights. It allows the use of the */
- /* IP instruction in the twilight zone, which */
- /* otherwise would be `illegal' according to the */
- /* specification. */
- /* */
- /* We implement it with a special sequence for the */
- /* twilight zone. This is a bad hack, but it seems */
- /* to work. */
+ /* UNDOCUMENTED! */
+ /* */
+ /* The behaviour of an MIAP instruction is quite different when used */
+ /* in the twilight zone. */
+ /* */
+ /* First, no control value cut-in test is performed as it would fail */
+ /* anyway. Second, the original point, i.e. (org_x,org_y) of */
+ /* zp0.point, is set to the absolute, unrounded distance found in the */
+ /* CVT. */
+ /* */
+ /* This is used in the CVT programs of the Microsoft fonts Arial, */
+ /* Times, etc., in order to re-adjust some key font heights. It */
+ /* allows the use of the IP instruction in the twilight zone, which */
+ /* otherwise would be invalid according to the specification. */
+ /* */
+ /* We implement it with a special sequence for the twilight zone. */
+ /* This is a bad hack, but it seems to work. */
+ /* */
+ /* Confirmed by Greg Hitchcock. */
distance = CUR_Func_read_cvt( cvtEntry );
if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
{
- CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.x );
- CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.y ),
+ CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance,
+ CUR.GS.freeVector.x );
+ CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance,
+ CUR.GS.freeVector.y ),
CUR.zp0.cur[point] = CUR.zp0.org[point];
}
@@ -6042,6 +6075,7 @@
CUR_Func_move( &CUR.zp0, point, distance - org_dist );
+ Fail:
CUR.GS.rp0 = point;
CUR.GS.rp1 = point;
}
@@ -6067,7 +6101,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
/* XXX: Is there some undocumented feature while in the */
@@ -6152,6 +6186,7 @@
CUR_Func_move( &CUR.zp1, point, distance - org_dist );
+ Fail:
CUR.GS.rp1 = CUR.GS.rp0;
CUR.GS.rp2 = point;
@@ -6189,7 +6224,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
if ( !cvtEntry )
@@ -6208,19 +6243,17 @@
cvt_dist = -CUR.GS.single_width_value;
}
- /* XXX: UNDOCUMENTED! -- twilight zone */
-
+ /* UNDOCUMENTED! The MS rasterizer does that with */
+ /* twilight points (confirmed by Greg Hitchcock) */
if ( CUR.GS.gep1 == 0 )
{
CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
TT_MulFix14( (FT_UInt32)cvt_dist,
CUR.GS.freeVector.x );
-
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.zp0.cur[point];
}
org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
@@ -6244,8 +6277,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,
@@ -6274,12 +6321,12 @@
CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
+ Fail:
CUR.GS.rp1 = CUR.GS.rp0;
if ( ( CUR.opcode & 16 ) != 0 )
CUR.GS.rp0 = point;
- /* XXX: UNDOCUMENTED! */
CUR.GS.rp2 = point;
}
@@ -6304,7 +6351,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
while ( CUR.GS.loop > 0 )
@@ -6332,6 +6379,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -6473,8 +6521,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;
}
/*
@@ -6488,7 +6537,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
if ( twilight )
@@ -6553,6 +6602,8 @@
CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
}
+
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -6845,8 +6896,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;
@@ -6862,8 +6914,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;
@@ -6912,6 +6966,7 @@
CUR.error = TT_Err_Invalid_Reference;
}
+ Fail:
CUR.new_top = CUR.args;
}
@@ -6939,8 +6994,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;
@@ -6955,8 +7011,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;
@@ -7004,6 +7062,7 @@
}
}
+ Fail:
CUR.new_top = CUR.args;
}
@@ -7465,8 +7524,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 );
@@ -7503,7 +7573,7 @@
case 0x04: /* SFvTCA y */
case 0x05: /* SFvTCA x */
{
- FT_Short AA, BB;
+ FT_Short AA, BB;
AA = (FT_Short)( ( opcode & 1 ) << 14 );
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 8fe86ad..d77c3c4 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -4,8 +4,7 @@
/* */
/* Objects manager (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -214,16 +213,18 @@
tt_get_sfnt_checksum( TT_Face face,
FT_UShort i )
{
+#if 0 /* if we believe the written value, use following part. */
if ( face->dir_tables[i].CheckSum )
return face->dir_tables[i].CheckSum;
+#endif
- else if ( !face->goto_table )
+ if ( !face->goto_table )
return 0;
- else if ( !face->goto_table( face,
- face->dir_tables[i].Tag,
- face->root.stream,
- NULL ) )
+ if ( face->goto_table( face,
+ face->dir_tables[i].Tag,
+ face->root.stream,
+ NULL ) )
return 0;
return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,
@@ -243,7 +244,7 @@
tt_check_trickyness_sfnt_ids( TT_Face face )
{
#define TRICK_SFNT_IDS_PER_FACE 3
-#define TRICK_SFNT_IDS_NUM_FACES 5
+#define TRICK_SFNT_IDS_NUM_FACES 13
static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
[TRICK_SFNT_IDS_PER_FACE] = {
@@ -276,16 +277,61 @@
{ 0xfffbfffc, 0x00000008 }, /* cvt */
{ 0x0a5a0483, 0x00017c39 }, /* fpgm */
{ 0x70020112, 0x00000008 } /* prep */
+ },
+ { /* NEC fadpop7.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x40c92555, 0x000000e5 }, /* fpgm */
+ { 0xa39b58e3, 0x0000117c } /* prep */
+ },
+ { /* NEC fadrei5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x33c41652, 0x000000e5 }, /* fpgm */
+ { 0x26d6c52a, 0x00000f6a } /* prep */
+ },
+ { /* NEC fangot7.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x6db1651d, 0x0000019d }, /* fpgm */
+ { 0x6c6e4b03, 0x00002492 } /* prep */
+ },
+ { /* NEC fangyo5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x40c92555, 0x000000e5 }, /* fpgm */
+ { 0xde51fad0, 0x0000117c } /* prep */
+ },
+ { /* NEC fankyo5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x85e47664, 0x000000e5 }, /* fpgm */
+ { 0xa6c62831, 0x00001caa } /* prep */
+ },
+ { /* NEC fanrgo5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x2d891cfd, 0x0000019d }, /* fpgm */
+ { 0xa0604633, 0x00001de8 } /* prep */
+ },
+ { /* NEC fangot5.ttc */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x40aa774c, 0x000001cb }, /* fpgm */
+ { 0x9b5caa96, 0x00001f9a } /* prep */
+ },
+ { /* NEC fanmin3.ttc */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x0d3de9cb, 0x00000141 }, /* fpgm */
+ { 0xd4127766, 0x00002280 } /* prep */
}
};
- FT_ULong checksum;
- int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
- int i, j, k;
+ FT_ULong checksum;
+ int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
+ FT_Bool has_cvt, has_fpgm, has_prep;
+ FT_UShort i;
+ int j, k;
FT_MEM_SET( num_matched_ids, 0,
sizeof( int ) * TRICK_SFNT_IDS_NUM_FACES );
+ has_cvt = FALSE;
+ has_fpgm = FALSE;
+ has_prep = FALSE;
for ( i = 0; i < face->num_tables; i++ )
{
@@ -295,14 +341,17 @@
{
case TTAG_cvt:
k = TRICK_SFNT_ID_cvt;
+ has_cvt = TRUE;
break;
case TTAG_fpgm:
k = TRICK_SFNT_ID_fpgm;
+ has_fpgm = TRUE;
break;
case TTAG_prep:
k = TRICK_SFNT_ID_prep;
+ has_prep = TRUE;
break;
default:
@@ -323,6 +372,18 @@
}
}
+ for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
+ {
+ if ( !has_cvt && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
+ num_matched_ids[j] ++;
+ if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
+ num_matched_ids[j] ++;
+ if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
+ num_matched_ids[j] ++;
+ if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
+ return TRUE;
+ }
+
return FALSE;
}
@@ -333,14 +394,10 @@
if ( !face )
return FALSE;
- /* First, check the face name. */
- if ( face->family_name )
- {
- if ( tt_check_trickyness_family( face->family_name ) )
- return TRUE;
- else
- return FALSE;
- }
+ /* For first, check the face name for quick check. */
+ if ( face->family_name &&
+ tt_check_trickyness_family( face->family_name ) )
+ return TRUE;
/* Type42 fonts may lack `name' tables, we thus try to identify */
/* tricky fonts by checking the checksums of Type42-persistent */
@@ -352,6 +409,54 @@
}
+ /* Check whether `.notdef' is the only glyph in the `loca' table. */
+ static FT_Bool
+ tt_check_single_notdef( FT_Face ttface )
+ {
+ FT_Bool result = FALSE;
+
+ TT_Face face = (TT_Face)ttface;
+ FT_UInt asize;
+ FT_ULong i;
+ FT_ULong glyph_index = 0;
+ FT_UInt count = 0;
+
+
+ for( i = 0; i < face->num_locations; i++ )
+ {
+ tt_face_get_location( face, i, &asize );
+ if ( asize > 0 )
+ {
+ count += 1;
+ if ( count > 1 )
+ break;
+ glyph_index = i;
+ }
+ }
+
+ /* Only have a single outline. */
+ if ( count == 1 )
+ {
+ if ( glyph_index == 0 )
+ result = TRUE;
+ else
+ {
+ /* FIXME: Need to test glyphname == .notdef ? */
+ FT_Error error;
+ char buf[8];
+
+
+ error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 );
+ if ( !error &&
+ buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) )
+ result = TRUE;
+ }
+ }
+
+ return result;
+ }
+
+
/*************************************************************************/
/* */
/* <Function> */
@@ -447,6 +552,20 @@
if ( !error )
error = tt_face_load_prep( face, stream );
+ /* Check the scalable flag based on `loca'. */
+ if ( !ttface->internal->incremental_interface &&
+ ttface->num_fixed_sizes &&
+ face->glyph_locations &&
+ tt_check_single_notdef( ttface ) )
+ {
+ FT_TRACE5(( "tt_face_init:"
+ " Only the `.notdef' glyph has an outline.\n"
+ " "
+ " Resetting scalable flag to FALSE.\n" ));
+
+ ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
+ }
+
#else
if ( !error )
@@ -458,6 +577,19 @@
if ( !error )
error = tt_face_load_prep( face, stream );
+ /* Check the scalable flag based on `loca'. */
+ if ( ttface->num_fixed_sizes &&
+ face->glyph_locations &&
+ tt_check_single_notdef( ttface ) )
+ {
+ FT_TRACE5(( "tt_face_init:"
+ " Only the `.notdef' glyph has an outline.\n"
+ " "
+ " Resetting scalable flag to FALSE.\n" ));
+
+ ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
+ }
+
#endif
}
@@ -570,13 +702,16 @@
/* Run the font program. */
/* */
/* <Input> */
- /* size :: A handle to the size object. */
+ /* size :: A handle to the size object. */
+ /* */
+ /* pedantic :: Set if bytecode execution should be pedantic. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
- tt_size_run_fpgm( TT_Size size )
+ tt_size_run_fpgm( TT_Size size,
+ FT_Bool pedantic )
{
TT_Face face = (TT_Face)size->root.face;
TT_ExecContext exec;
@@ -594,15 +729,17 @@
TT_Load_Context( exec, face, size );
- exec->callTop = 0;
- exec->top = 0;
+ exec->callTop = 0;
+ exec->top = 0;
exec->period = 64;
exec->phase = 0;
exec->threshold = 0;
exec->instruction_trap = FALSE;
- exec->F_dot_P = 0x10000L;
+ exec->F_dot_P = 0x10000L;
+
+ exec->pedantic_hinting = pedantic;
{
FT_Size_Metrics* metrics = &exec->metrics;
@@ -659,13 +796,16 @@
/* Run the control value program. */
/* */
/* <Input> */
- /* size :: A handle to the size object. */
+ /* size :: A handle to the size object. */
+ /* */
+ /* pedantic :: Set if bytecode execution should be pedantic. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
- tt_size_run_prep( TT_Size size )
+ tt_size_run_prep( TT_Size size,
+ FT_Bool pedantic )
{
TT_Face face = (TT_Face)size->root.face;
TT_ExecContext exec;
@@ -688,6 +828,8 @@
exec->instruction_trap = FALSE;
+ exec->pedantic_hinting = pedantic;
+
TT_Set_CodeRange( exec,
tt_coderange_cvt,
face->cvt_program,
@@ -766,7 +908,8 @@
/* Initialize bytecode-related fields in the size object. */
/* We do this only if bytecode interpretation is really needed. */
static FT_Error
- tt_size_init_bytecode( FT_Size ftsize )
+ tt_size_init_bytecode( FT_Size ftsize,
+ FT_Bool pedantic )
{
FT_Error error;
TT_Size size = (TT_Size)ftsize;
@@ -839,7 +982,7 @@
}
/* Fine, now run the font program! */
- error = tt_size_run_fpgm( size );
+ error = tt_size_run_fpgm( size, pedantic );
Exit:
if ( error )
@@ -850,14 +993,15 @@
FT_LOCAL_DEF( FT_Error )
- tt_size_ready_bytecode( TT_Size size )
+ tt_size_ready_bytecode( TT_Size size,
+ FT_Bool pedantic )
{
FT_Error error = TT_Err_Ok;
if ( !size->bytecode_ready )
{
- error = tt_size_init_bytecode( (FT_Size)size );
+ error = tt_size_init_bytecode( (FT_Size)size, pedantic );
if ( error )
goto Exit;
}
@@ -889,7 +1033,7 @@
size->GS = tt_default_graphics_state;
- error = tt_size_run_prep( size );
+ error = tt_size_run_prep( size, pedantic );
if ( !error )
size->cvt_ready = 1;
}
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index 30c8669..087b3c2 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
/* */
/* Objects manager (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/* Copyright 1996-2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -390,13 +390,16 @@ FT_BEGIN_HEADER
#ifdef TT_USE_BYTECODE_INTERPRETER
FT_LOCAL( FT_Error )
- tt_size_run_fpgm( TT_Size size );
+ tt_size_run_fpgm( TT_Size size,
+ FT_Bool pedantic );
FT_LOCAL( FT_Error )
- tt_size_run_prep( TT_Size size );
+ tt_size_run_prep( TT_Size size,
+ FT_Bool pedantic );
FT_LOCAL( FT_Error )
- tt_size_ready_bytecode( TT_Size size );
+ tt_size_ready_bytecode( TT_Size size,
+ FT_Bool pedantic );
#endif /* TT_USE_BYTECODE_INTERPRETER */
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index 68a5453..818b29d 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
/* */
/* TrueType-specific tables loader (body). */
/* */
-/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 1996-2002, 2004-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -110,15 +110,16 @@
face->num_locations = table_len >> shift;
}
- if ( face->num_locations != (FT_ULong)face->root.num_glyphs )
+ if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
{
FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",
- face->num_locations, face->root.num_glyphs ));
+ face->num_locations - 1, face->root.num_glyphs ));
/* we only handle the case where `maxp' gives a larger value */
- if ( face->num_locations < (FT_ULong)face->root.num_glyphs )
+ if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
{
- FT_Long new_loca_len = (FT_Long)face->root.num_glyphs << shift;
+ FT_Long new_loca_len =
+ ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift;
TT_Table entry = face->dir_tables;
TT_Table limit = entry + face->num_tables;
@@ -145,7 +146,7 @@
if ( new_loca_len <= dist )
{
- face->num_locations = face->root.num_glyphs;
+ face->num_locations = face->root.num_glyphs + 1;
table_len = new_loca_len;
FT_TRACE2(( "adjusting num_locations to %d\n",