Hi Werner,

Here is likely the final form of mod to freetype that I am putting in as part 
of the next release of font validator. Mostly it is just two new APIs : to set 
and unset an external diagnostics messaging routine, and a macro which wrap 
around it to call it in a nicer way: DIAGNOSTICS("message", where).

The rest is just a lot of scattered:
     "DIAGNOSTICS('message", where)",
or 
     "if (simple_condition)  DIAGNOSTICS('message", where)".

If you re-define the macro to nothing, it causes no functionality change to 
freetype at all.

The end result is simplier than I thought, as mostly freetype already detects 
and silently works around the errors; so it is mostly about finding out or 
deciding *where* to put the DIANOSTICS().

Sorry that the "message" part is a string - it turns out to be more convenient 
for me to have it as a string on the freetype side, instead of having it as a 
enum. The set of such strings - I only use 6, but eventually there will be 70+ 
of them - are a subset of the ~800 enums
(those that starts with "_rast_") in

https://github.com/HinTak/Font-Validator/blob/master/OTFontFileVal/atoms.cs

Trimming (i.e. removing the "_rast_" part) or name-space prepending 
("FontVal_rast_") don't add any trouble to me. So if that's more preferable?

Hin-Tak
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index ccbb1d7..7575fe1 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -79,12 +79,31 @@
 #define BOUNDSL( x, n )  ( (FT_ULong)(x) >= (FT_ULong)(n) )
 
 
+typedef int (*diagnostics_Function)(char *message, char *opcode, 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)->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))
+
+
 
   /*************************************************************************/
   /*                                                                       */
@@ -1649,6 +1668,7 @@
                FT_F26Dot6      distance )
   {
     FT_F26Dot6  v;
+    FT_Long F_dot_P = 0, moved_x = 0, moved_y = 0;
 
 
     v = exc->GS.freeVector.x;
@@ -1660,7 +1680,8 @@
            ( !exc->ignore_x_mode                                ||
              ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-        zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+        moved_x = FT_MulDiv( distance, v, exc->F_dot_P );
+        zone->cur[point].x += moved_x;
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
     }
@@ -1669,10 +1690,21 @@
 
     if ( v != 0 )
     {
-      zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
+      moved_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);
+      }
   }
 
 
@@ -3951,6 +3983,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 )
@@ -4130,6 +4166,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;
@@ -4276,7 +4313,7 @@
   {
     FT_Short  S;
     FT_Long   X, Y;
-
+    FT_Long P_dot_P;
 
     /* Only use low 16bits, then sign extend */
     S = (FT_Short)args[1];
@@ -4284,6 +4321,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;
@@ -4303,7 +4345,7 @@
   {
     FT_Short  S;
     FT_Long   X, Y;
-
+    FT_Long F_dot_F;
 
     /* Only use low 16bits, then sign extend */
     S = (FT_Short)args[1];
@@ -4311,6 +4353,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 );
   }
@@ -4652,6 +4699,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;
@@ -4690,6 +4738,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;
@@ -4735,6 +4784,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;
@@ -4815,6 +4865,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;
@@ -5043,6 +5094,9 @@
     exc->GS.instruct_control &= ~(FT_Byte)Kf;
     exc->GS.instruct_control |= (FT_Byte)L;
 
+    if ( exc->curRange != tt_coderange_font )
+      DIAGNOSTICS("_rast_E_NOT_CALLED_FROM_PREPROGRAM", exc);
+
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
     /* INSTCTRL modifying flag 3 also has an effect */
     /* outside of the CVT program                   */
@@ -5148,6 +5202,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 );
@@ -5185,6 +5240,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;
@@ -5214,6 +5270,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;
@@ -5249,6 +5306,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;
@@ -5323,6 +5381,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 );
@@ -5487,6 +5546,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 );
@@ -5621,6 +5681,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;
@@ -5675,6 +5736,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;
@@ -5741,6 +5803,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;
@@ -5850,6 +5914,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;
@@ -6004,6 +6069,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;
@@ -6214,6 +6282,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;
@@ -6227,6 +6297,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 );
@@ -6288,6 +6359,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;
@@ -6365,6 +6437,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;
@@ -6411,6 +6484,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;
@@ -6430,6 +6504,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;
     }
@@ -6464,6 +6539,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 );
@@ -6512,13 +6588,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,
@@ -6549,6 +6630,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;
@@ -6757,8 +6839,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++;
@@ -6950,8 +7034,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

Reply via email to