ref: 3ea859f6e9c508b7a1044efeedf86ec4cd410891
parent: 0798f0c3ecfa52322498c58ceeaa4ee0aa0cc3c1
author: Graham Asher <[email protected]>
date: Fri Apr 25 07:40:46 EDT 2003
Added the unpatented hinting system, which is compiled only if TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING is defined in ftoption.h
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -43,9 +43,6 @@
#undef FT_COMPONENT
#define FT_COMPONENT trace_ttinterp
-#undef NO_APPLE_PATENT
-#define APPLE_THRESHOLD 0x4000000L
-
/*************************************************************************/
/* */
/* In order to detect infinite loops in the code, we set up a counter */
@@ -221,7 +218,6 @@
/* */
#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
-
#undef SUCCESS
#define SUCCESS 0
@@ -228,6 +224,16 @@
#undef FAILURE
#define FAILURE 1
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+#define GUESS_VECTOR( V ) \
+ if ( CUR.face->unpatented_hinting ) \
+ { \
+ CUR.GS.V.x = (FT_F2Dot14)(CUR.GS.both_x_axis ? 0x4000 : 0); \
+ CUR.GS.V.y = (FT_F2Dot14)(CUR.GS.both_x_axis ? 0 : 0x4000); \
+ }
+#else
+#define GUESS_VECTOR( V )
+#endif
/*************************************************************************/
/* */
@@ -719,6 +725,10 @@
exec->GS.freeVector = exec->GS.projVector;
exec->GS.dualVector = exec->GS.projVector;
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ exec->GS.both_x_axis = TRUE;
+#endif
+
exec->GS.round_state = 1;
exec->GS.loop = 1;
@@ -746,6 +756,11 @@
{ 0x4000, 0 },
{ 0x4000, 0 },
{ 0x4000, 0 },
+
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ TRUE,
+#endif
+
1, 64, 1,
TRUE, 68, 0, 0, 9, 3,
0, FALSE, 2, 1, 1, 1
@@ -1344,24 +1359,35 @@
static FT_Long
Current_Ratio( EXEC_OP )
{
- if ( CUR.tt_metrics.ratio )
- return CUR.tt_metrics.ratio;
-
- if ( CUR.GS.projVector.y == 0 )
- CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
-
- else if ( CUR.GS.projVector.x == 0 )
- CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
-
- else
+ if ( !CUR.tt_metrics.ratio )
{
- FT_Long x, y;
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ if ( CUR.face->unpatented_hinting )
+ {
+ if ( CUR.GS.both_x_axis )
+ CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
+ else
+ CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
+ }
+ else
+#endif
+ {
+ if ( CUR.GS.projVector.y == 0 )
+ CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
- x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x4000 );
- y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x4000 );
- CUR.tt_metrics.ratio = TT_VecLen( x, y );
- }
+ else if ( CUR.GS.projVector.x == 0 )
+ CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
+ else
+ {
+ FT_Long x, y;
+
+ x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x4000 );
+ y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x4000 );
+ CUR.tt_metrics.ratio = TT_VecLen( x, y );
+ }
+ }
+ }
return CUR.tt_metrics.ratio;
}
@@ -1529,8 +1555,12 @@
FT_UShort point,
FT_F26Dot6 distance )
{
+
FT_F26Dot6 v;
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ FT_ASSERT(!CUR.face->unpatented_hinting);
+#endif
v = CUR.GS.freeVector.x;
@@ -1537,19 +1567,10 @@
if ( v != 0 )
{
-#ifdef NO_APPLE_PATENT
-
- if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
- zone->cur[point].x += distance;
-
-#else
-
zone->cur[point].x += TT_MULDIV( distance,
v * 0x10000L,
CUR.F_dot_P );
-#endif
-
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -1558,21 +1579,13 @@
if ( v != 0 )
{
-#ifdef NO_APPLE_PATENT
-
- if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
- zone->cur[point].y += distance;
-
-#else
-
zone->cur[point].y += TT_MULDIV( distance,
v * 0x10000L,
CUR.F_dot_P );
-#endif
-
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
+
}
@@ -2110,6 +2123,9 @@
Project( EXEC_OP_ FT_Vector* v1,
FT_Vector* v2 )
{
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ FT_ASSERT(!CUR.face->unpatented_hinting);
+#endif
return TT_DotFix14( v1->x - v2->x,
v1->y - v2->y,
CUR.GS.projVector.x,
@@ -2116,7 +2132,6 @@
CUR.GS.projVector.y );
}
-
/*************************************************************************/
/* */
/* <Function> */
@@ -2164,6 +2179,9 @@
Free_Project( EXEC_OP_ FT_Vector* v1,
FT_Vector* v2 )
{
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ FT_ASSERT(!CUR.face->unpatented_hinting);
+#endif
return TT_DotFix14( v1->x - v2->x,
v1->y - v2->y,
CUR.GS.freeVector.x,
@@ -2170,7 +2188,6 @@
CUR.GS.freeVector.y );
}
-
/*************************************************************************/
/* */
/* <Function> */
@@ -2235,6 +2252,53 @@
static void
Compute_Funcs( EXEC_OP )
{
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ if ( CUR.face->unpatented_hinting )
+ {
+ /* If both vectors point rightwards along the x axis, set */
+ /* 'both-x-axis' true, otherwise set it false. The x values only */
+ /* need be tested because the vector has been normalised to a unit */
+ /* vector of length 0x4000 = unity. */
+ CUR.GS.both_x_axis = (FT_Bool)(CUR.GS.projVector.x == 0x4000 && CUR.GS.freeVector.x == 0x4000);
+
+ /* Throw away projection and freedom vector information */
+ /* because the patents don't allow them to be stored. */
+ /* The relevant US Patents are 5155805 and 5325479. */
+ CUR.GS.projVector.x = 0;
+ CUR.GS.projVector.y = 0;
+ CUR.GS.freeVector.x = 0;
+ CUR.GS.freeVector.y = 0;
+
+ if ( CUR.GS.both_x_axis )
+ {
+ CUR.func_project = Project_x;
+ CUR.func_freeProj = Project_x;
+ CUR.func_move = Direct_Move_X;
+ }
+ else
+ {
+ CUR.func_project = Project_y;
+ CUR.func_freeProj = Project_y;
+ CUR.func_move = Direct_Move_Y;
+ }
+
+ if ( CUR.GS.dualVector.x == 0x4000 )
+ CUR.func_dualproj = Project_x;
+ else
+ {
+ if ( CUR.GS.dualVector.y == 0x4000 )
+ CUR.func_dualproj = Project_y;
+ else
+ CUR.func_dualproj = Dual_Project;
+ }
+
+ /* Force recalculation of cached aspect ratio */
+ CUR.tt_metrics.ratio = 0;
+
+ return;
+ }
+#endif
+
if ( CUR.GS.freeVector.x == 0x4000 )
{
CUR.func_freeProj = (TT_Project_Func)Project_x;
@@ -2503,6 +2567,8 @@
CUR.GS.projVector.y = B; \
CUR.GS.dualVector.y = B; \
\
+ GUESS_VECTOR( freeVector ); \
+ \
COMPUTE_Funcs(); \
}
@@ -2518,6 +2584,8 @@
CUR.GS.freeVector.x = A; \
CUR.GS.freeVector.y = B; \
\
+ GUESS_VECTOR( projVector ); \
+ \
COMPUTE_Funcs(); \
}
@@ -2529,6 +2597,7 @@
&CUR.GS.projVector ) == SUCCESS ) \
{ \
CUR.GS.dualVector = CUR.GS.projVector; \
+ GUESS_VECTOR( freeVector ); \
COMPUTE_Funcs(); \
}
@@ -2538,10 +2607,12 @@
(FT_UShort)args[0], \
CUR.opcode, \
&CUR.GS.freeVector ) == SUCCESS ) \
+ GUESS_VECTOR( projVector ); \
COMPUTE_Funcs();
#define DO_SFVTPV \
+ GUESS_VECTOR( projVector ); \
CUR.GS.freeVector = CUR.GS.projVector; \
COMPUTE_Funcs();
@@ -2561,6 +2632,7 @@
NORMalize( X, Y, &CUR.GS.projVector ); \
\
CUR.GS.dualVector = CUR.GS.projVector; \
+ GUESS_VECTOR( freeVector ); \
COMPUTE_Funcs(); \
}
@@ -2578,18 +2650,47 @@
X = S; \
\
NORMalize( X, Y, &CUR.GS.freeVector ); \
+ GUESS_VECTOR( projVector ); \
COMPUTE_Funcs(); \
}
-#define DO_GPV \
- args[0] = CUR.GS.projVector.x; \
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+#define DO_GPV \
+ if ( CUR.face->unpatented_hinting ) \
+ { \
+ args[0] = CUR.GS.both_x_axis ? 0x4000 : 0;\
+ args[1] = CUR.GS.both_x_axis ? 0 : 0x4000;\
+ } \
+ else \
+ { \
+ args[0] = CUR.GS.projVector.x; \
+ args[1] = CUR.GS.projVector.y; \
+ }
+#else
+#define DO_GPV \
+ args[0] = CUR.GS.projVector.x; \
args[1] = CUR.GS.projVector.y;
+#endif
-#define DO_GFV \
- args[0] = CUR.GS.freeVector.x; \
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+#define DO_GFV \
+ if ( CUR.face->unpatented_hinting ) \
+ { \
+ args[0] = CUR.GS.both_x_axis ? 0x4000 : 0;\
+ args[1] = CUR.GS.both_x_axis ? 0 : 0x4000;\
+ } \
+ else \
+ { \
+ args[0] = CUR.GS.freeVector.x; \
+ args[1] = CUR.GS.freeVector.y; \
+ }
+#else
+#define DO_GFV \
+ args[0] = CUR.GS.freeVector.x; \
args[1] = CUR.GS.freeVector.y;
+#endif
#define DO_SRP0 \
@@ -4750,6 +4851,8 @@
NORMalize( A, B, &CUR.GS.projVector );
+ GUESS_VECTOR( freeVector );
+
COMPUTE_Funcs();
}
@@ -5123,22 +5226,31 @@
d = CUR_Func_project( zp.cur + p, zp.org + p );
-#ifdef NO_APPLE_PATENT
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ if ( CUR.face->unpatented_hinting )
+ {
+ if ( CUR.GS.both_x_axis )
+ {
+ *x = d;
+ *y = 0;
+ }
+ else
+ {
+ *x = 0;
+ *y = d;
+ }
+ }
+ else
+#endif
+ {
+ *x = TT_MULDIV( d,
+ (FT_Long)CUR.GS.freeVector.x * 0x10000L,
+ CUR.F_dot_P );
+ *y = TT_MULDIV( d,
+ (FT_Long)CUR.GS.freeVector.y * 0x10000L,
+ CUR.F_dot_P );
+ }
- *x = TT_MulFix14( d, CUR.GS.freeVector.x );
- *y = TT_MulFix14( d, CUR.GS.freeVector.y );
-
-#else
-
- *x = TT_MULDIV( d,
- (FT_Long)CUR.GS.freeVector.x * 0x10000L,
- CUR.F_dot_P );
- *y = TT_MULDIV( d,
- (FT_Long)CUR.GS.freeVector.y * 0x10000L,
- CUR.F_dot_P );
-
-#endif /* NO_APPLE_PATENT */
-
return SUCCESS;
}
@@ -5149,6 +5261,25 @@
FT_F26Dot6 dy,
FT_Bool touch )
{
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ if (CUR.face->unpatented_hinting)
+ {
+ if ( CUR.GS.both_x_axis )
+ {
+ CUR.zp2.cur[point].x += dx;
+ if ( touch )
+ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
+ }
+ else
+ {
+ CUR.zp2.cur[point].y += dy;
+ if ( touch )
+ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
+ }
+ return;
+ }
+#endif
+
if ( CUR.GS.freeVector.x != 0 )
{
CUR.zp2.cur[point].x += dx;
@@ -5334,8 +5465,26 @@
return;
}
- dx = TT_MulFix14( args[0], CUR.GS.freeVector.x );
- dy = TT_MulFix14( args[0], CUR.GS.freeVector.y );
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ if ( CUR.face->unpatented_hinting)
+ {
+ if ( CUR.GS.both_x_axis )
+ {
+ dx = TT_MulFix14( args[0], 0x4000 );
+ dy = 0;
+ }
+ else
+ {
+ dx = 0;
+ dy = TT_MulFix14( args[0], 0x4000 );
+ }
+ }
+ else
+#endif
+ {
+ dx = TT_MulFix14( args[0], CUR.GS.freeVector.x );
+ dy = TT_MulFix14( args[0], CUR.GS.freeVector.y );
+ }
while ( CUR.GS.loop > 0 )
{
@@ -6231,7 +6380,23 @@
FT_ULong C;
FT_Long B;
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ /* Delta hinting is covered by US Patent 5159668. */
+ if ( CUR.face->unpatented_hinting )
+ {
+ FT_Long n = args[0] * 2;
+ if ( CUR.args < n )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ return;
+ }
+ CUR.args -= n;
+ CUR.new_top = CUR.args;
+ return;
+ }
+#endif
+
nump = (FT_ULong)args[0]; /* some points theoretically may occur more
than once, thus UShort isn't enough */
@@ -6306,7 +6471,23 @@
FT_ULong A, C;
FT_Long B;
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ /* Delta hinting is covered by US Patent 5159668. */
+ if ( CUR.face->unpatented_hinting )
+ {
+ FT_Long n = args[0] * 2;
+ if ( CUR.args < n )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ return;
+ }
+ CUR.args -= n;
+ CUR.new_top = CUR.args;
+ return;
+ }
+#endif
+
nump = (FT_ULong)args[0];
for ( k = 1; k <= nump; k++ )
@@ -6870,11 +7051,19 @@
CUR.GS.dualVector.x = AA;
CUR.GS.dualVector.y = BB;
}
+ else
+ {
+ GUESS_VECTOR( projVector );
+ }
if ( ( opcode & 2 ) == 0 )
{
CUR.GS.freeVector.x = AA;
CUR.GS.freeVector.y = BB;
+ }
+ else
+ {
+ GUESS_VECTOR( freeVector );
}
COMPUTE_Funcs();
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -34,6 +34,9 @@
#include "ttinterp.h"
#endif
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+#include FT_TRUETYPE_UNPATENTED_H
+#endif
/*************************************************************************/
/* */
@@ -221,6 +224,26 @@
#endif
}
+
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+
+ /* Determine whether unpatented hinting is to be used for this face. */
+
+#ifdef TT_CONFIG_OPTION_FORCE_UNPATENTED_HINTING
+ face->unpatented_hinting = TRUE;
+#else
+ face->unpatented_hinting = FALSE;
+ {
+ int i;
+
+ for ( i = 0; i < num_params && !face->unpatented_hinting;
+ i++ )
+ if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING )
+ face->unpatented_hinting = TRUE;
+ }
+#endif
+
+#endif
/* initialize standard glyph loading routines */
TT_Init_Glyph_Loading( face );
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -83,6 +83,10 @@
FT_UnitVector projVector;
FT_UnitVector freeVector;
+#ifdef TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING
+ FT_Bool both_x_axis;
+#endif
+
FT_Long loop;
FT_F26Dot6 minimum_distance;
FT_Int round_state;