Here is the updated patch for 2.6.4 - there are some minor collisions with the
new subpixel hinting mode.
while updating the diff I looked into the global variable issue. Putting the
diagnostic messaging pointer inside TT_Face is fairly straight forward, and it
isn't too hard to do it per TT_Face, which is even better than per FT_Library.
However
- diagnostics on parallel threads seem a bit of over-design - most people are
unlikely ever to test multiple faces in parallel. Testing on single face is
demanding enough - did I mention that it took about 5 days of CPU time to run
the MS 2003 binary through the MS shipped fonts in win 8.1?
- extracting the face handle and passing it back increases the complexity of
the C<->C# interface. Before implementing the rasterization test, I have relied
on SharpFont ( https://github.com/Robmaister/SharpFont ) to handle the C<->C#
interaction. And I have enhanced SharpFont on the way as needed. The current
change by-passes SharpFont. I do not want to spend time increasing the
complexity of what's really a temporary by-pass.
Anyway, you or others are welcomed to improve the patch. I'm going to start
packaging after this e-mail, and hope to release the next Font Val (with a
patched freetype 2.6.4 backend) in the next few days.
--------------------------------------------
On Mon, 4/7/16, Behdad Esfahbod <[email protected]> wrote:
global variable is not desirable. Put it on the FT_Library
at least.
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 2e3f9ef..534e30f 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -90,12 +90,29 @@
#define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) )
+typedef int (*diagnostics_Function)(const char* message, const char* const opcode, int range_base, int is_composite, int IP, int callTop, int opc, int start);
+
+static diagnostics_Function diagnostics = NULL;
+
#undef SUCCESS
#define SUCCESS 0
#undef FAILURE
#define FAILURE 1
+ FT_EXPORT_DEF( void )
+ TT_diagnostics_unset( void )
+ {
+ diagnostics = NULL;
+ }
+
+ FT_EXPORT_DEF( void )
+ TT_diagnostics_set( diagnostics_Function funcptr )
+ {
+ diagnostics = funcptr;
+ }
+
+#define DIAGNOSTICS(message, context) if (diagnostics) (*diagnostics)(message, opcode_name[(context)->opcode] + 2, ( (context)->callTop ? (context)->callStack->Caller_Range : (context)->curRange ), (context)->is_composite , (context)->IP, (context)->callTop, ((context)->callTop ? ((context)->callStack + (context)->callTop - 1)->Def->opc : 0), ((context)->callTop ? ((context)->callStack + (context)->callTop - 1)->Def->start : 0))
/*************************************************************************/
/* */
@@ -910,7 +927,7 @@
};
-#ifdef FT_DEBUG_LEVEL_TRACE
+#if defined(FT_DEBUG_LEVEL_TRACE) || defined(DIAGNOSTICS)
/* the first hex digit gives the length of the opcode name; the space */
/* after the digit is here just to increase readability of the source */
@@ -1664,17 +1681,19 @@
FT_F26Dot6 distance )
{
FT_F26Dot6 v;
+ FT_Long F_dot_P = 0, moved_x = 0, moved_y = 0;
v = exc->GS.freeVector.x;
if ( v != 0 )
{
+ moved_x = FT_MulDiv( distance, v, exc->F_dot_P );
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
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 += moved_x;
else
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
@@ -1683,12 +1702,12 @@
/* 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 );
+ zone->cur[point].x += moved_x;
else
#endif
if ( NO_SUBPIXEL_HINTING )
- zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->cur[point].x += moved_x;
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -1697,16 +1716,27 @@
if ( v != 0 )
{
+ moved_y = FT_MulDiv( distance, v, exc->F_dot_P );
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
if ( !( SUBPIXEL_HINTING_MINIMAL &&
exc->backwards_compatibility &&
exc->iupx_called &&
exc->iupy_called ) )
#endif
- zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->cur[point].y += moved_y;
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
+
+ F_dot_P =
+ ( (FT_Long)exc->GS.projVector.x * exc->GS.freeVector.x +
+ (FT_Long)exc->GS.projVector.y * exc->GS.freeVector.y ) >> 14;
+
+ if ( FT_ABS( F_dot_P ) < 0x400L )
+ {
+ if ( (moved_x == 0 || moved_y == 0) && distance != 0 )
+ DIAGNOSTICS("_rast_W_PF_VECTORS_AT_OR_NEAR_PERP", exc );
+ }
}
@@ -3982,6 +4012,10 @@
}
exc->numIDefs++;
}
+ else
+ {
+ DIAGNOSTICS("_rast_E_INSTR_DEFD_BY_FS", exc );
+ }
/* opcode must be unsigned 8-bit integer */
if ( 0 > args[0] || args[0] > 0x00FF )
@@ -4161,6 +4195,7 @@
if ( BOUNDS( aIdx1, exc->zp2.n_points ) ||
BOUNDS( aIdx2, exc->zp1.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
return FAILURE;
@@ -4307,6 +4342,7 @@
{
FT_Short S;
FT_Long X, Y;
+ FT_Long P_dot_P;
/* Only use low 16bits, then sign extend */
@@ -4315,6 +4351,11 @@
S = (FT_Short)args[0];
X = (FT_Long)S;
+ P_dot_P = ( X * X + Y * Y ) >> 14;
+
+ if ( P_dot_P < 0x3C00 ) /* arbitrary - expect 0x4000 */
+ DIAGNOSTICS("_rast_E_VECTOR_XY_INVALID", exc );
+
Normalize( X, Y, &exc->GS.projVector );
exc->GS.dualVector = exc->GS.projVector;
@@ -4334,6 +4375,7 @@
{
FT_Short S;
FT_Long X, Y;
+ FT_Long F_dot_F;
/* Only use low 16bits, then sign extend */
@@ -4342,6 +4384,11 @@
S = (FT_Short)args[0];
X = S;
+ F_dot_F = ( X * X + Y * Y ) >> 14;
+
+ if ( F_dot_F < 0x3C00 ) /* arbitrary - expect 0x4000 */
+ DIAGNOSTICS("_rast_E_VECTOR_XY_INVALID", exc );
+
Normalize( X, Y, &exc->GS.freeVector );
Compute_Funcs( exc );
}
@@ -4683,6 +4730,7 @@
if ( BOUNDSL( L, exc->zp2.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
R = 0;
@@ -4721,6 +4769,7 @@
if ( BOUNDS( L, exc->zp2.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
return;
@@ -4766,6 +4815,7 @@
if ( BOUNDS( L, exc->zp0.n_points ) ||
BOUNDS( K, exc->zp1.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
D = 0;
@@ -4846,6 +4896,7 @@
if ( BOUNDS( p2, exc->zp1.n_points ) ||
BOUNDS( p1, exc->zp2.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
return;
@@ -5074,6 +5125,9 @@
exc->GS.instruct_control &= ~(FT_Byte)Kf;
exc->GS.instruct_control |= (FT_Byte)L;
+ if ( exc->callTop && ( exc->callStack->Caller_Range == tt_coderange_glyph ) )
+ DIAGNOSTICS("_rast_E_NOT_CALLED_FROM_PREPROGRAM", exc );
+
if ( K == 3 )
{
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
@@ -5199,6 +5253,7 @@
if ( BOUNDS( point, exc->pts.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
{
exc->error = FT_THROW( Invalid_Reference );
@@ -5245,6 +5300,7 @@
if ( BOUNDS( K, exc->pts.n_points ) ||
BOUNDS( L, exc->pts.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
return;
@@ -5283,6 +5339,7 @@
if ( BOUNDS( K, exc->pts.n_points ) ||
BOUNDS( L, exc->pts.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
return;
@@ -5318,6 +5375,7 @@
if ( BOUNDS( p, zp.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
*refp = 0;
@@ -5405,6 +5463,7 @@
if ( BOUNDS( point, exc->zp2.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
{
exc->error = FT_THROW( Invalid_Reference );
@@ -5574,6 +5633,7 @@
if ( BOUNDS( point, exc->zp2.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
{
exc->error = FT_THROW( Invalid_Reference );
@@ -5721,6 +5781,7 @@
if ( BOUNDS( point, exc->zp1.n_points ) ||
BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
return;
@@ -5775,6 +5836,7 @@
if ( BOUNDS( point, exc->zp0.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
return;
@@ -5841,6 +5903,8 @@
if ( BOUNDS( point, exc->zp0.n_points ) ||
BOUNDSL( cvtEntry, exc->cvtSize ) )
{
+ if ( BOUNDS( point, exc->zp0.n_points ) )
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
goto Fail;
@@ -5950,6 +6014,7 @@
if ( BOUNDS( point, exc->zp1.n_points ) ||
BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
goto Fail;
@@ -6105,6 +6170,9 @@
BOUNDSL( cvtEntry, exc->cvtSize + 1 ) ||
BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
{
+ if ( BOUNDS( point, exc->zp1.n_points ) ||
+ BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
goto Fail;
@@ -6315,6 +6383,8 @@
if ( exc->top < exc->GS.loop ||
BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
{
+ if ( BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
goto Fail;
@@ -6328,6 +6398,7 @@
if ( BOUNDS( point, exc->zp1.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
{
exc->error = FT_THROW( Invalid_Reference );
@@ -6389,6 +6460,7 @@
BOUNDS( a1, exc->zp1.n_points ) ||
BOUNDS( point, exc->zp2.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
return;
@@ -6468,6 +6540,7 @@
if ( BOUNDS( p1, exc->zp1.n_points ) ||
BOUNDS( p2, exc->zp0.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
return;
@@ -6514,6 +6587,7 @@
if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
goto Fail;
@@ -6533,6 +6607,7 @@
if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) ||
BOUNDS( exc->GS.rp2, exc->zp1.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
old_range = 0;
cur_range = 0;
}
@@ -6567,6 +6642,7 @@
/* check point bounds */
if ( BOUNDS( point, exc->zp2.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
{
exc->error = FT_THROW( Invalid_Reference );
@@ -6615,13 +6691,18 @@
/* new_dist - cur_dist = delta , */
/* new_dist - cur_dist = org_dist - cur_dist , */
/* new_dist = org_dist . */
-
new_dist = org_dist;
+ DIAGNOSTICS("_rast_E_RP1_RP2_SAME_POS_ON_PROJ", exc );
}
}
else
new_dist = 0;
+ /*
+ if ( (new_dist - cur_dist) != 0 && (new_dist - org_dist) == 0)
+ DIAGNOSTICS("_rast_E_RP1_RP2_SAME_POS_ON_PROJ", exc );
+ */
+
exc->func_move( exc,
&exc->zp2,
(FT_UShort)point,
@@ -6652,6 +6733,7 @@
if ( BOUNDS( point, exc->zp0.n_points ) )
{
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
return;
@@ -6877,8 +6959,10 @@
end_point = exc->pts.contours[contour] - exc->pts.first_point;
first_point = point;
- if ( BOUNDS( end_point, exc->pts.n_points ) )
+ if ( BOUNDS( end_point, exc->pts.n_points ) ) {
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
end_point = exc->pts.n_points - 1;
+ }
while ( point <= end_point && ( exc->pts.tags[point] & mask ) == 0 )
point++;
@@ -7086,8 +7170,11 @@
}
}
else
+ {
+ DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc );
if ( exc->pedantic_hinting )
exc->error = FT_THROW( Invalid_Reference );
+ }
}
Fail:
_______________________________________________
Freetype-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/freetype-devel