freetype-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [ft-devel] updated patch for 2.6.4 Re: proposed patch for diagnostic


From: Werner LEMBERG
Subject: Re: [ft-devel] updated patch for 2.6.4 Re: proposed patch for diagnostics
Date: Wed, 06 Jul 2016 08:59:59 +0200 (CEST)

> Here is the updated patch for 2.6.4 - there are some minor
> collisions with the new subpixel hinting mode.

Attached is something that would fit better into FreeType
w.r.t. formatting, macro definitions, and function names.  I suggest
to provide a public header file `ftdiag.h' that defines, similar to
`fterrdef.h', enumeration values `FT_DIAG_XXX' instead of the
currently used strings, together with proper declarations for
`TT_Diagnostics_{Unset,Set}' (which probably should use an `FT_'
prefix instead).

> 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.

OK.

> 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?

It's not about running the diagnostics in parallel but simply avoiding
global variables in general in case you want to have it integrated
into upstream FreeType.  Right now, your changes are very small and
non-invasive, so I could easily add them.

> - 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.

Well, I can't comment on this.


    Werner
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 8fe83c5..e75bcfa 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -82,6 +82,19 @@
 #define BOUNDSL( x, n )  ( (FT_ULong)(x) >= (FT_ULong)(n) )
 
 
+  typedef int
+  (*diagnosticsFunc)( const char*        message,
+                      const char* const  opcode,
+                      int                range_base,
+                      int                is_composite,
+                      int                IP,
+                      int                callTop,
+                      int                opc,
+                      int                start );
+
+  static diagnosticsFunc  diagnostics = NULL;
+
+
 #undef  SUCCESS
 #define SUCCESS  0
 
@@ -89,6 +102,47 @@
 #define FAILURE  1
 
 
+  FT_EXPORT_DEF( void )
+  TT_Diagnostics_Unset( void )
+  {
+    diagnostics = NULL;
+  }
+
+
+  FT_EXPORT_DEF( void )
+  TT_Diagnostics_Set( diagnosticsFunc  funcptr )
+  {
+    diagnostics = funcptr;
+  }
+
+
+#ifdef FT_DIAGNOSTICS
+#define DIAGNOSTICS( message, context )                                    \
+          do                                                               \
+          {                                                                \
+            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 ) )                                    \
+          } while ( 0 )
+#else
+#define DIAGNOSTICS( message, context )  do { } while ( 0 )
+#endif
+
+
   /*************************************************************************/
   /*                                                                       */
   /*                        CODERANGE FUNCTIONS                            */
@@ -902,7 +956,7 @@
   };
 
 
-#ifdef FT_DEBUG_LEVEL_TRACE
+#if defined( FT_DEBUG_LEVEL_TRACE ) || defined( FT_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 */
@@ -1656,17 +1710,21 @@
                FT_F26Dot6      distance )
   {
     FT_F26Dot6  v;
+    FT_Long     moved_x = 0;
+    FT_Long     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 */
 
@@ -1675,12 +1733,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;
     }
@@ -1689,16 +1747,33 @@
 
     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;
     }
+
+#ifdef FT_DIAGNOSTICS
+    {
+      FT_Long  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 );
+      }
+    }
+#endif /* FT_DIAGNOSTICS */
   }
 
 
@@ -3974,6 +4049,10 @@
       }
       exc->numIDefs++;
     }
+#ifdef FT_DIAGNOSTICS
+    else
+      DIAGNOSTICS("_rast_E_INSTR_DEFD_BY_FS", exc );
+#endif
 
     /* opcode must be unsigned 8-bit integer */
     if ( 0 > args[0] || args[0] > 0x00FF )
@@ -4153,6 +4232,8 @@
     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 +4388,16 @@
     S = (FT_Short)args[0];
     X = (FT_Long)S;
 
+#ifdef FT_DIAGNOSTICS
+    {
+      FT_Long  P_dot_P = ( X * X +  Y * Y ) >> 14;
+
+
+      if ( P_dot_P < 0x3C00 ) /* arbitrary - expect 0x4000 */
+        DIAGNOSTICS("_rast_E_VECTOR_XY_INVALID", exc );
+    }
+#endif
+
     Normalize( X, Y, &exc->GS.projVector );
 
     exc->GS.dualVector = exc->GS.projVector;
@@ -4334,6 +4425,16 @@
     S = (FT_Short)args[0];
     X = S;
 
+#ifdef FT_DIAGNOSTICS
+    {
+      FT_Long  F_dot_F = ( X * X +  Y * Y ) >> 14;
+
+
+      if ( F_dot_F < 0x3C00 ) /* arbitrary - expect 0x4000 */
+        DIAGNOSTICS("_rast_E_VECTOR_XY_INVALID", exc );
+    }
+#endif
+
     Normalize( X, Y, &exc->GS.freeVector );
     Compute_Funcs( exc );
   }
@@ -4675,6 +4776,8 @@
 
     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;
@@ -4713,6 +4816,8 @@
 
     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;
@@ -4758,6 +4863,8 @@
     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;
@@ -4838,6 +4945,8 @@
     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;
@@ -5066,6 +5175,12 @@
     exc->GS.instruct_control &= ~(FT_Byte)Kf;
     exc->GS.instruct_control |= (FT_Byte)L;
 
+#ifdef FT_DIAGNOSTICS
+    if ( exc->callTop                                           &&
+         ( exc->callStack->Caller_Range == tt_coderange_glyph ) )
+      DIAGNOSTICS( "_rast_E_NOT_CALLED_FROM_PREPROGRAM", exc );
+#endif
+
     if ( K == 3 )
     {
 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
@@ -5191,6 +5306,8 @@
 
       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 );
@@ -5237,6 +5354,8 @@
     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;
@@ -5275,6 +5394,8 @@
     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;
@@ -5310,6 +5431,8 @@
 
     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;
@@ -5397,6 +5520,8 @@
 
       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 );
@@ -5566,6 +5691,8 @@
 
       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 );
@@ -5713,6 +5840,8 @@
     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;
@@ -5767,6 +5896,8 @@
 
     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;
@@ -5833,6 +5964,11 @@
     if ( BOUNDS( point,     exc->zp0.n_points ) ||
          BOUNDSL( cvtEntry, exc->cvtSize )      )
     {
+#ifdef FT_DIAGNOSTICS
+      if ( BOUNDS( point, exc->zp0.n_points ) )
+        DIAGNOSTICS( "_rast_E_POINT_OUT_OF_RANGE", exc );
+#endif
+
       if ( exc->pedantic_hinting )
         exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
@@ -5942,6 +6078,8 @@
     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;
@@ -6097,6 +6235,12 @@
          BOUNDSL( cvtEntry,   exc->cvtSize + 1 )  ||
          BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
     {
+#ifdef FT_DIAGNOSTICS
+      if ( BOUNDS( point,       exc->zp1.n_points ) ||
+           BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
+        DIAGNOSTICS( "_rast_E_POINT_OUT_OF_RANGE", exc );
+#endif
+
       if ( exc->pedantic_hinting )
         exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
@@ -6307,6 +6451,11 @@
     if ( exc->top < exc->GS.loop                  ||
          BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
     {
+#ifdef FT_DIAGNOSTICS
+      if ( BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
+        DIAGNOSTICS( "_rast_E_POINT_OUT_OF_RANGE", exc );
+#endif
+
       if ( exc->pedantic_hinting )
         exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
@@ -6320,6 +6469,8 @@
 
       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 );
@@ -6381,6 +6532,8 @@
          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;
@@ -6460,6 +6613,8 @@
     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;
@@ -6506,6 +6661,8 @@
 
     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;
@@ -6525,6 +6682,8 @@
     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;
     }
@@ -6559,6 +6718,8 @@
       /* 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 );
@@ -6609,11 +6770,18 @@
           /*              new_dist = org_dist                .       */
 
           new_dist = org_dist;
+
+          DIAGNOSTICS( "_rast_E_RP1_RP2_SAME_POS_ON_PROJ", exc );
         }
       }
       else
         new_dist = 0;
 
+#if 0
+      if ( ( new_dist - cur_dist ) != 0 && ( new_dist - org_dist ) == 0 )
+        DIAGNOSTICS( "_rast_E_RP1_RP2_SAME_POS_ON_PROJ", exc );
+#endif
+
       exc->func_move( exc,
                       &exc->zp2,
                       (FT_UShort)point,
@@ -6644,6 +6812,8 @@
 
     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;
@@ -6870,7 +7040,11 @@
       first_point = point;
 
       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++;
@@ -7078,8 +7252,12 @@
         }
       }
       else
+      {
+        DIAGNOSTICS( "_rast_E_POINT_OUT_OF_RANGE", exc );
+
         if ( exc->pedantic_hinting )
           exc->error = FT_THROW( Invalid_Reference );
+      }
     }
 
   Fail:

reply via email to

[Prev in Thread] Current Thread [Next in Thread]