[CMAKE]
[reactos.git] / lib / 3rdparty / freetype / src / truetype / ttinterp.c
index 85c8529..f55b8ee 100644 (file)
@@ -4,8 +4,9 @@
 /*                                                                         */
 /*    TrueType bytecode interpreter (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by             */
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
+/*            2010                                                         */
+/*  by David Turner, Robert Wilhelm, and Werner Lemberg.                   */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
 /*  modified, and distributed under the terms of the FreeType project      */
 
   /*************************************************************************/
   /*                                                                       */
-  /* A simple bounds-checking macro.                                       */
+  /* Two simple bounds-checking macros.                                    */
   /*                                                                       */
-#define BOUNDS( x, n )  ( (FT_UInt)(x) >= (FT_UInt)(n) )
+#define BOUNDS( x, n )   ( (FT_UInt)(x)  >= (FT_UInt)(n)  )
+#define BOUNDSL( x, n )  ( (FT_ULong)(x) >= (FT_ULong)(n) )
 
 #undef  SUCCESS
 #define SUCCESS  0
     return TT_Err_Ok;
 
   Fail_Memory:
-    FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
-               (FT_Long)exec ));
+    FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
     TT_Done_Context( exec );
 
     return error;
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
   /*                                                                       */
-  static FT_Error
+  FT_LOCAL_DEF( FT_Error )
   Update_Max( FT_Memory  memory,
               FT_ULong*  size,
               FT_Long    multiplier,
       exec->storage   = size->storage;
 
       exec->twilight  = size->twilight;
+
+      /* In case of multi-threading it can happen that the old size object */
+      /* no longer exists, thus we must clear all glyph zone references.   */
+      ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) );
+      exec->zp1 = exec->zp0;
+      exec->zp2 = exec->zp0;
     }
 
     /* XXX: We reserve a little more elements on the stack to deal safely */
   /*    exec  :: A handle to the target execution context.                 */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    TrueTyoe error code.  0 means success.                             */
+  /*    TrueType error code.  0 means success.                             */
   /*                                                                       */
   /* <Note>                                                                */
   /*    Only the glyph loader and debugger should call this function.      */
   }
 
 
+  /* The default value for `scan_control' is documented as FALSE in the */
+  /* TrueType specification.  This is confusing since it implies a      */
+  /* Boolean value.  However, this is not the case, thus both the       */
+  /* default values of our `scan_type' and `scan_control' fields (which */
+  /* the documentation's `scan_control' variable is split into) are     */
+  /* zero.                                                              */
+
   const TT_GraphicsState  tt_default_graphics_state =
   {
     0, 0, 0,
 
     1, 64, 1,
     TRUE, 68, 0, 0, 9, 3,
-    0, FALSE, 2, 1, 1, 1
+    0, FALSE, 0, 1, 1, 1
   };
 
 
 
       /* allocate object */
       if ( FT_NEW( exec ) )
-        goto Exit;
+        goto Fail;
 
-      /* initialize it */
+      /* initialize it; in case of error this deallocates `exec' too */
       error = Init_Context( exec, memory );
       if ( error )
         goto Fail;
       driver->context = exec;
     }
 
-  Exit:
     return driver->context;
 
   Fail:
-    FT_FREE( exec );
-
-    return 0;
+    return NULL;
   }
 
 
   };
 
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+  static
+  const char*  const opcode_name[256] =
+  {
+    "SVTCA y",
+    "SVTCA x",
+    "SPvTCA y",
+    "SPvTCA x",
+    "SFvTCA y",
+    "SFvTCA x",
+    "SPvTL ||",
+    "SPvTL +",
+    "SFvTL ||",
+    "SFvTL +",
+    "SPvFS",
+    "SFvFS",
+    "GPV",
+    "GFV",
+    "SFvTPv",
+    "ISECT",
+
+    "SRP0",
+    "SRP1",
+    "SRP2",
+    "SZP0",
+    "SZP1",
+    "SZP2",
+    "SZPS",
+    "SLOOP",
+    "RTG",
+    "RTHG",
+    "SMD",
+    "ELSE",
+    "JMPR",
+    "SCvTCi",
+    "SSwCi",
+    "SSW",
+
+    "DUP",
+    "POP",
+    "CLEAR",
+    "SWAP",
+    "DEPTH",
+    "CINDEX",
+    "MINDEX",
+    "AlignPTS",
+    "INS_$28",
+    "UTP",
+    "LOOPCALL",
+    "CALL",
+    "FDEF",
+    "ENDF",
+    "MDAP[0]",
+    "MDAP[1]",
+
+    "IUP[0]",
+    "IUP[1]",
+    "SHP[0]",
+    "SHP[1]",
+    "SHC[0]",
+    "SHC[1]",
+    "SHZ[0]",
+    "SHZ[1]",
+    "SHPIX",
+    "IP",
+    "MSIRP[0]",
+    "MSIRP[1]",
+    "AlignRP",
+    "RTDG",
+    "MIAP[0]",
+    "MIAP[1]",
+
+    "NPushB",
+    "NPushW",
+    "WS",
+    "RS",
+    "WCvtP",
+    "RCvt",
+    "GC[0]",
+    "GC[1]",
+    "SCFS",
+    "MD[0]",
+    "MD[1]",
+    "MPPEM",
+    "MPS",
+    "FlipON",
+    "FlipOFF",
+    "DEBUG",
+
+    "LT",
+    "LTEQ",
+    "GT",
+    "GTEQ",
+    "EQ",
+    "NEQ",
+    "ODD",
+    "EVEN",
+    "IF",
+    "EIF",
+    "AND",
+    "OR",
+    "NOT",
+    "DeltaP1",
+    "SDB",
+    "SDS",
+
+    "ADD",
+    "SUB",
+    "DIV",
+    "MUL",
+    "ABS",
+    "NEG",
+    "FLOOR",
+    "CEILING",
+    "ROUND[0]",
+    "ROUND[1]",
+    "ROUND[2]",
+    "ROUND[3]",
+    "NROUND[0]",
+    "NROUND[1]",
+    "NROUND[2]",
+    "NROUND[3]",
+
+    "WCvtF",
+    "DeltaP2",
+    "DeltaP3",
+    "DeltaCn[0]",
+    "DeltaCn[1]",
+    "DeltaCn[2]",
+    "SROUND",
+    "S45Round",
+    "JROT",
+    "JROF",
+    "ROFF",
+    "INS_$7B",
+    "RUTG",
+    "RDTG",
+    "SANGW",
+    "AA",
+
+    "FlipPT",
+    "FlipRgON",
+    "FlipRgOFF",
+    "INS_$83",
+    "INS_$84",
+    "ScanCTRL",
+    "SDVPTL[0]",
+    "SDVPTL[1]",
+    "GetINFO",
+    "IDEF",
+    "ROLL",
+    "MAX",
+    "MIN",
+    "ScanTYPE",
+    "InstCTRL",
+    "INS_$8F",
+
+    "INS_$90",
+    "INS_$91",
+    "INS_$92",
+    "INS_$93",
+    "INS_$94",
+    "INS_$95",
+    "INS_$96",
+    "INS_$97",
+    "INS_$98",
+    "INS_$99",
+    "INS_$9A",
+    "INS_$9B",
+    "INS_$9C",
+    "INS_$9D",
+    "INS_$9E",
+    "INS_$9F",
+
+    "INS_$A0",
+    "INS_$A1",
+    "INS_$A2",
+    "INS_$A3",
+    "INS_$A4",
+    "INS_$A5",
+    "INS_$A6",
+    "INS_$A7",
+    "INS_$A8",
+    "INS_$A9",
+    "INS_$AA",
+    "INS_$AB",
+    "INS_$AC",
+    "INS_$AD",
+    "INS_$AE",
+    "INS_$AF",
+
+    "PushB[0]",
+    "PushB[1]",
+    "PushB[2]",
+    "PushB[3]",
+    "PushB[4]",
+    "PushB[5]",
+    "PushB[6]",
+    "PushB[7]",
+    "PushW[0]",
+    "PushW[1]",
+    "PushW[2]",
+    "PushW[3]",
+    "PushW[4]",
+    "PushW[5]",
+    "PushW[6]",
+    "PushW[7]",
+
+    "MDRP[00]",
+    "MDRP[01]",
+    "MDRP[02]",
+    "MDRP[03]",
+    "MDRP[04]",
+    "MDRP[05]",
+    "MDRP[06]",
+    "MDRP[07]",
+    "MDRP[08]",
+    "MDRP[09]",
+    "MDRP[10]",
+    "MDRP[11]",
+    "MDRP[12]",
+    "MDRP[13]",
+    "MDRP[14]",
+    "MDRP[15]",
+
+    "MDRP[16]",
+    "MDRP[17]",
+    "MDRP[18]",
+    "MDRP[19]",
+    "MDRP[20]",
+    "MDRP[21]",
+    "MDRP[22]",
+    "MDRP[23]",
+    "MDRP[24]",
+    "MDRP[25]",
+    "MDRP[26]",
+    "MDRP[27]",
+    "MDRP[28]",
+    "MDRP[29]",
+    "MDRP[30]",
+    "MDRP[31]",
+
+    "MIRP[00]",
+    "MIRP[01]",
+    "MIRP[02]",
+    "MIRP[03]",
+    "MIRP[04]",
+    "MIRP[05]",
+    "MIRP[06]",
+    "MIRP[07]",
+    "MIRP[08]",
+    "MIRP[09]",
+    "MIRP[10]",
+    "MIRP[11]",
+    "MIRP[12]",
+    "MIRP[13]",
+    "MIRP[14]",
+    "MIRP[15]",
+
+    "MIRP[16]",
+    "MIRP[17]",
+    "MIRP[18]",
+    "MIRP[19]",
+    "MIRP[20]",
+    "MIRP[21]",
+    "MIRP[22]",
+    "MIRP[23]",
+    "MIRP[24]",
+    "MIRP[25]",
+    "MIRP[26]",
+    "MIRP[27]",
+    "MIRP[28]",
+    "MIRP[29]",
+    "MIRP[30]",
+    "MIRP[31]"
+  };
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+
   static
   const FT_Char  opcode_length[256] =
   {
       if ( distance && val < 0 )
         val = 0;
     }
-    else {
+    else
+    {
       val = distance - compensation;
       if ( val > 0 )
         val = 0;
     FT_ASSERT( !CUR.face->unpatented_hinting );
 #endif
 
-    return TT_DotFix14( dx, dy,
+    return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
                         CUR.GS.projVector.x,
                         CUR.GS.projVector.y );
   }
   Dual_Project( EXEC_OP_ FT_Pos  dx,
                          FT_Pos  dy )
   {
-    return TT_DotFix14( dx, dy,
+    return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
                         CUR.GS.dualVector.x,
                         CUR.GS.dualVector.y );
   }
   }
 
 
-#define DO_JROT               \
-    if ( args[1] != 0 )       \
-    {                         \
-      CUR.IP      += args[0]; \
-      CUR.step_ins = FALSE;   \
+#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]; \
+#define DO_JMPR                        \
+    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]; \
-      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;              \
     }
 
 
     args[0] = FT_PIX_CEIL( args[0] );
 
 
-#define DO_RS                          \
-   {                                   \
-     FT_ULong  I = (FT_ULong)args[0];  \
-                                       \
-                                       \
-     if ( BOUNDS( I, CUR.storeSize ) ) \
-     {                                 \
-       if ( CUR.pedantic_hinting )     \
-       {                               \
-         ARRAY_BOUND_ERROR;            \
-       }                               \
-       else                            \
-         args[0] = 0;                  \
-     }                                 \
-     else                              \
-       args[0] = CUR.storage[I];       \
+#define DO_RS                           \
+   {                                    \
+     FT_ULong  I = (FT_ULong)args[0];   \
+                                        \
+                                        \
+     if ( BOUNDSL( I, CUR.storeSize ) ) \
+     {                                  \
+       if ( CUR.pedantic_hinting )      \
+       {                                \
+         ARRAY_BOUND_ERROR;             \
+       }                                \
+       else                             \
+         args[0] = 0;                   \
+     }                                  \
+     else                               \
+       args[0] = CUR.storage[I];        \
    }
 
 
-#define DO_WS                          \
-   {                                   \
-     FT_ULong  I = (FT_ULong)args[0];  \
-                                       \
-                                       \
-     if ( BOUNDS( I, CUR.storeSize ) ) \
-     {                                 \
-       if ( CUR.pedantic_hinting )     \
-       {                               \
-         ARRAY_BOUND_ERROR;            \
-       }                               \
-     }                                 \
-     else                              \
-       CUR.storage[I] = args[1];       \
+#define DO_WS                           \
+   {                                    \
+     FT_ULong  I = (FT_ULong)args[0];   \
+                                        \
+                                        \
+     if ( BOUNDSL( I, CUR.storeSize ) ) \
+     {                                  \
+       if ( CUR.pedantic_hinting )      \
+       {                                \
+         ARRAY_BOUND_ERROR;             \
+       }                                \
+     }                                  \
+     else                               \
+       CUR.storage[I] = args[1];        \
    }
 
 
      FT_ULong  I = (FT_ULong)args[0];    \
                                          \
                                          \
-     if ( BOUNDS( I, CUR.cvtSize ) )     \
+     if ( BOUNDSL( I, CUR.cvtSize ) )    \
      {                                   \
        if ( CUR.pedantic_hinting )       \
        {                                 \
      FT_ULong  I = (FT_ULong)args[0];    \
                                          \
                                          \
-     if ( BOUNDS( I, CUR.cvtSize ) )     \
+     if ( BOUNDSL( I, CUR.cvtSize ) )    \
      {                                   \
        if ( CUR.pedantic_hinting )       \
        {                                 \
      FT_ULong  I = (FT_ULong)args[0];                           \
                                                                 \
                                                                 \
-     if ( BOUNDS( I, CUR.cvtSize ) )                            \
+     if ( BOUNDSL( I, CUR.cvtSize ) )                           \
      {                                                          \
        if ( CUR.pedantic_hinting )                              \
        {                                                        \
       CUR.numFDefs++;
     }
 
+    /* Although FDEF takes unsigned 32-bit integer,  */
+    /* func # must be within unsigned 16-bit integer */
+    if ( n > 0xFFFFU )
+    {
+      CUR.error = TT_Err_Too_Many_Function_Defs;
+      return;
+    }
+
     rec->range  = CUR.curRange;
-    rec->opc    = n;
+    rec->opc    = (FT_UInt16)n;
     rec->start  = CUR.IP + 1;
     rec->active = TRUE;
 
     if ( n > CUR.maxFunc )
-      CUR.maxFunc = n;
+      CUR.maxFunc = (FT_UInt16)n;
 
     /* Now skip the whole function definition. */
     /* We don't allow nested IDEFS & FDEFs.    */
     /* first of all, check the index */
 
     F = args[0];
-    if ( BOUNDS( F, CUR.maxFunc + 1 ) )
+    if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
       goto Fail;
 
     /* Except for some old Apple fonts, all functions in a TrueType */
 
     /* first of all, check the index */
     F = args[1];
-    if ( BOUNDS( F, CUR.maxFunc + 1 ) )
+    if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
       goto Fail;
 
     /* Except for some old Apple fonts, all functions in a TrueType */
       CUR.numIDefs++;
     }
 
-    def->opc    = args[0];
-    def->start  = CUR.IP+1;
+    /* opcode must be unsigned 8-bit integer */
+    if ( 0 > args[0] || args[0] > 0x00FF )
+    {
+      CUR.error = TT_Err_Too_Many_Instruction_Defs;
+      return;
+    }
+
+    def->opc    = (FT_Byte)args[0];
+    def->start  = CUR.IP + 1;
     def->range  = CUR.curRange;
     def->active = TRUE;
 
     if ( (FT_ULong)args[0] > CUR.maxIns )
-      CUR.maxIns = args[0];
+      CUR.maxIns = (FT_Byte)args[0];
 
     /* Now skip the whole function definition. */
     /* We don't allow nested IDEFs & FDEFs.    */
 
     L = (FT_ULong)args[0];
 
-    if ( BOUNDS( L, CUR.zp2.n_points ) )
+    if ( BOUNDSL( L, CUR.zp2.n_points ) )
     {
       if ( CUR.pedantic_hinting )
       {
     K = (FT_UShort)args[1];
     L = (FT_UShort)args[0];
 
-    if( BOUNDS( L, CUR.zp0.n_points ) ||
-        BOUNDS( K, CUR.zp1.n_points ) )
+    if ( BOUNDS( L, CUR.zp0.n_points ) ||
+         BOUNDS( K, CUR.zp1.n_points ) )
     {
       if ( CUR.pedantic_hinting )
       {
       if ( CUR.opcode & 1 )
         D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
       else
-        D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K );
+      {
+        FT_Vector*  vec1 = CUR.zp0.orus + L;
+        FT_Vector*  vec2 = CUR.zp1.orus + K;
+
+
+        if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
+        {
+          /* this should be faster */
+          D = CUR_Func_dualproj( vec1, vec2 );
+          D = TT_MULFIX( D, CUR.metrics.x_scale );
+        }
+        else
+        {
+          FT_Vector  vec;
+
+
+          vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
+          vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
+
+          D = CUR_fast_dualproj( &vec );
+        }
+      }
     }
 
     args[0] = D;
       return;
     }
 
-    A *= 64;
-
-#if 0
-    if ( ( args[0] & 0x100 ) != 0 && CUR.metrics.pointSize <= A )
+    if ( ( args[0] & 0x100 ) != 0 && CUR.tt_metrics.ppem <= A )
       CUR.GS.scan_control = TRUE;
-#endif
 
     if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
       CUR.GS.scan_control = TRUE;
     if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
       CUR.GS.scan_control = TRUE;
 
-#if 0
-    if ( ( args[0] & 0x800 ) != 0 && CUR.metrics.pointSize > A )
+    if ( ( args[0] & 0x800 ) != 0 && CUR.tt_metrics.ppem > A )
       CUR.GS.scan_control = FALSE;
-#endif
 
     if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
       CUR.GS.scan_control = FALSE;
   static void
   Ins_SCANTYPE( INS_ARG )
   {
-    /* for compatibility with future enhancements, */
-    /* we must ignore new modes                    */
-
-    if ( args[0] >= 0 && args[0] <= 5 )
-    {
-      if ( args[0] == 3 )
-        args[0] = 2;
-
+    if ( args[0] >= 0 )
       CUR.GS.scan_type = (FT_Int)args[0];
-    }
   }
 
 
 
     /* XXX: this is probably wrong... at least it prevents memory */
     /*      corruption when zp2 is the twilight zone              */
-    if ( last_point > CUR.zp2.n_points )
+    if ( BOUNDS( last_point, CUR.zp2.n_points ) )
     {
       if ( CUR.zp2.n_points > 0 )
         last_point = (FT_UShort)(CUR.zp2.n_points - 1);
   static void
   Ins_SHZ( INS_ARG )
   {
-    TT_GlyphZoneRec zp;
-    FT_UShort       refp;
-    FT_F26Dot6      dx,
-                    dy;
+    TT_GlyphZoneRec  zp;
+    FT_UShort        refp;
+    FT_F26Dot6       dx,
+                     dy;
 
-    FT_UShort       last_point, i;
+    FT_UShort        last_point, i;
 
 
     if ( BOUNDS( args[0], 2 ) )
     if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
       last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
     else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
+    {
       last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
+
+      if ( BOUNDS( last_point, CUR.zp2.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+          CUR.error = TT_Err_Invalid_Reference;
+        return;
+      }
+    }
     else
       last_point = 0;
 
     {
       if ( CUR.GS.both_x_axis )
       {
-        dx = TT_MulFix14( args[0], 0x4000 );
+        dx = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
         dy = 0;
       }
       else
       {
         dx = 0;
-        dy = TT_MulFix14( args[0], 0x4000 );
+        dy = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
       }
     }
     else
 #endif
     {
-      dx = TT_MulFix14( args[0], CUR.GS.freeVector.x );
-      dy = TT_MulFix14( args[0], CUR.GS.freeVector.y );
+      dx = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.x );
+      dy = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.y );
     }
 
     while ( CUR.GS.loop > 0 )
     cvtEntry = (FT_ULong)args[1];
     point    = (FT_UShort)args[0];
 
-    if ( BOUNDS( point,    CUR.zp0.n_points ) ||
-         BOUNDS( cvtEntry, CUR.cvtSize )      )
+    if ( BOUNDS( point,     CUR.zp0.n_points ) ||
+         BOUNDSL( cvtEntry, CUR.cvtSize )      )
     {
       if ( CUR.pedantic_hinting )
         CUR.error = TT_Err_Invalid_Reference;
 
     if ( CUR.GS.gep0 == 0 )   /* If in twilight zone */
     {
-      CUR.zp0.org[point].x = TT_MulFix14( distance, CUR.GS.freeVector.x );
-      CUR.zp0.org[point].y = TT_MulFix14( 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];
     }
 
     /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
 
     if ( BOUNDS( point,      CUR.zp1.n_points ) ||
-         BOUNDS( cvtEntry,   CUR.cvtSize + 1 )  ||
+         BOUNDSL( cvtEntry,  CUR.cvtSize + 1 )  ||
          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
     {
       if ( CUR.pedantic_hinting )
     if ( CUR.GS.gep1 == 0 )
     {
       CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
-                             TT_MulFix14( cvt_dist, CUR.GS.freeVector.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( cvt_dist, CUR.GS.freeVector.y );
+                             TT_MulFix14( (FT_UInt32)cvt_dist,
+                                          CUR.GS.freeVector.y );
 
       CUR.zp1.cur[point] = CUR.zp0.cur[point];
     }
     p1 = (FT_UShort)args[0];
     p2 = (FT_UShort)args[1];
 
-    if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
-         BOUNDS( args[1], CUR.zp0.n_points ) )
+    if ( BOUNDS( p1, CUR.zp1.n_points ) ||
+         BOUNDS( p2, CUR.zp0.n_points ) )
     {
       if ( CUR.pedantic_hinting )
         CUR.error = TT_Err_Invalid_Reference;
         org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
 
       cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
-      new_dist = ( old_range != 0 )
-                   ? TT_MULDIV( org_dist, cur_range, old_range )
-                   : cur_dist;
+
+      if ( org_dist )
+        new_dist = ( old_range != 0 )
+                     ? TT_MULDIV( org_dist, cur_range, old_range )
+                     : cur_dist;
+      else
+        new_dist = 0;
 
       CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
     }
 
 
   /* Local variables for Ins_IUP: */
-  typedef struct
+  typedef struct  IUP_WorkerRec_
   {
     FT_Vector*  orgs;   /* original and current coordinate */
     FT_Vector*  curs;   /* arrays                          */
           {
             scale_valid = 1;
             scale       = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
-                                     0x10000, orus2 - orus1 );
+                                     0x10000L, orus2 - orus1 );
           }
 
           x = ( org1 + delta1 ) +
       end_point   = CUR.pts.contours[contour] - CUR.pts.first_point;
       first_point = point;
 
+      if ( BOUNDS ( end_point, CUR.pts.n_points ) )
+        end_point = CUR.pts.n_points - 1;
+
       while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
         point++;
 
         {
           if ( ( CUR.pts.tags[point] & mask ) != 0 )
           {
-            if ( point > 0 )
-              _iup_worker_interpolate( &V,
-                                       cur_touched + 1,
-                                       point - 1,
-                                       cur_touched,
-                                       point );
+            _iup_worker_interpolate( &V,
+                                     cur_touched + 1,
+                                     point - 1,
+                                     cur_touched,
+                                     point );
             cur_touched = point;
           }
 
       A = (FT_ULong)CUR.stack[CUR.args + 1];
       B = CUR.stack[CUR.args];
 
-      if ( BOUNDS( A, CUR.cvtSize ) )
+      if ( BOUNDSL( A, CUR.cvtSize ) )
       {
         if ( CUR.pedantic_hinting )
         {
         call = CUR.callStack + CUR.callTop++;
 
         call->Caller_Range = CUR.curRange;
-        call->Caller_IP    = CUR.IP+1;
+        call->Caller_IP    = CUR.IP + 1;
         call->Cur_Count    = 1;
         call->Cur_Restart  = def->start;
 
     {
       CUR.opcode = CUR.code[CUR.IP];
 
+      FT_TRACE7(( "  " ));
+      FT_TRACE7(( opcode_name[CUR.opcode] ));
+      FT_TRACE7(( "\n" ));
+
       if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
       {
         if ( CUR.IP + 1 > CUR.codeSize )
     *exc = cur;
 #endif
 
+    /* If any errors have occurred, function tables may be broken. */
+    /* Force a re-execution of `prep' and `fpgm' tables if no      */
+    /* bytecode debugger is run.                                   */
+    if ( CUR.error && !CUR.instruction_trap )
+    {
+      FT_TRACE1(( "  The interpreter returned error 0x%x\n", CUR.error ));
+      exc->size->cvt_ready      = FALSE;  
+    }
+
     return CUR.error;
   }