emacs-diffs
[Top][All Lists]
Advanced

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

feature/android a2c3b9a787 1/3: Update Android port


From: Po Lu
Subject: feature/android a2c3b9a787 1/3: Update Android port
Date: Sat, 4 Feb 2023 06:55:24 -0500 (EST)

branch: feature/android
commit a2c3b9a7879e3127602c611fddaf28d3701d4622
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Update Android port
    
    * src/sfnt.c (sfnt_multiply_divide_signed):
    (struct sfnt_interpreter_zone):
    (struct sfnt_graphics_state):
    (struct sfnt_interpreter):
    (sfnt_mul_f2dot14):
    (sfnt_interpret_trap):
    (WCVTF):
    (ALIGNPTS):
    (sfnt_scale_by_freedom_vector):
    (sfnt_interpret_utp):
    (sfnt_address_zp2):
    (sfnt_address_zp1):
    (sfnt_address_zp0):
    (sfnt_check_zp2):
    (sfnt_move_zp0):
    (sfnt_move_zp1):
    (sfnt_move_glyph_zone):
    (sfnt_move_twilight_zone):
    (sfnt_direct_move_zp2):
    (sfnt_interpret_alignpts):
    (sfnt_interpret_isect):
    (sfnt_line_to_vector):
    (sfnt_deltac):
    (sfnt_interpret_mdap):
    (sfnt_interpret_call):
    (sfnt_dot_fix_14):
    (sfnt_move_x):
    (sfnt_move_y):
    (sfnt_move):
    (sfnt_validate_gs):
    (sfnt_interpret_shz):
    (sfnt_interpret_shc):
    (sfnt_interpret_shp):
    (sfnt_interpret_iup_1):
    (sfnt_interpret_iup):
    (sfnt_interpret_run):
    (sfnt_interpret_font_program):
    (sfnt_interpret_control_value_program):
    (sfnt_interpret_simple_glyph):
    (jrot_test_args):
    (jrof_test_args):
    (all_tests):
    (main): Check in more WIP code.
---
 src/sfnt.c | 968 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 895 insertions(+), 73 deletions(-)

diff --git a/src/sfnt.c b/src/sfnt.c
index 9a18e934b2..0d87ed36da 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -3210,7 +3210,7 @@ sfnt_multiply_divide (unsigned int a, unsigned int b, 
unsigned int c)
 /* The same as sfnt_multiply_divide, but handle signed values
    instead.  */
 
-static MAYBE_UNUSED int
+MAYBE_UNUSED static int
 sfnt_multiply_divide_signed (int a, int b, int c)
 {
   int sign;
@@ -4870,12 +4870,12 @@ struct sfnt_interpreter_zone
   /* Pointer to the X axis point data.  */
   sfnt_f26dot6 *restrict x_points;
 
-  /* Pointer to the Y axis point data.  */
-  sfnt_f26dot6 *restrict y_points;
-
   /* Pointer to the X axis current point data.  */
   sfnt_f26dot6 *restrict x_current;
 
+  /* Pointer to the Y axis point data.  */
+  sfnt_f26dot6 *restrict y_points;
+
   /* Pointer to the Y axis current point data.  */
   sfnt_f26dot6 *restrict y_current;
 
@@ -4915,10 +4915,11 @@ struct sfnt_graphics_state
   sfnt_f26dot6 (*project) (sfnt_f26dot6, sfnt_f26dot6,
                           struct sfnt_interpreter *);
 
-  /* Pointer to the function used to move a specified point
+  /* Pointer to the function used to move specified points
      along the freedom vector by a distance specified in terms
      of the projection vector.  */
-  void (*move) (sfnt_f26dot6 *, sfnt_f26dot6 *,
+  void (*move) (sfnt_f26dot6 *restrict,
+               sfnt_f26dot6 *restrict, size_t,
                struct sfnt_interpreter *,
                sfnt_f26dot6, unsigned char *);
 
@@ -5067,10 +5068,10 @@ struct sfnt_interpreter
   size_t cvt_size;
 
   /* Pointer to instructions currently being executed.  */
-  unsigned char *instructions;
+  unsigned char *restrict instructions;
 
   /* The twilight zone.  May not be NULL.  */
-  sfnt_f26dot6 *twilight_x, *twilight_y;
+  sfnt_f26dot6 *restrict twilight_x, *restrict twilight_y;
 
   /* The scaled outlines being manipulated.  May be NULL.  */
   struct sfnt_interpreter_zone *glyph_zone;
@@ -5174,6 +5175,34 @@ sfnt_mul_f26dot6 (sfnt_f26dot6 a, sfnt_f26dot6 b)
 #endif
 }
 
+/* Multiply the specified 2.14 number with another signed 32 bit
+   number.  Return the result as a signed 32 bit number.  */
+
+static int32_t
+sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b)
+{
+#ifdef INT64_MAX
+  int64_t product;
+
+  product = (int64_t) a * (int64_t) b;
+
+  return product / (int64_t) 16384;
+#else
+  int sign;
+
+  sign = 1;
+
+  if (a < 0)
+    sign = -sign;
+
+  if (b < 0)
+    sign = -sign;
+
+  return sfnt_multiply_divide (abs (a), abs (b),
+                              16384) * sign;
+#endif
+}
+
 /* Multiply the specified 26.6 fixed point number X by the specified
    16.16 fixed point number Y.
 
@@ -5429,17 +5458,18 @@ enum sfnt_interpreter_run_context
   };
 
 /* Cancel execution of the program in INTERPRETER with the specified
-   error REASON.
+   error REASON and reset the loop counter to 1.
 
    After this is called, it is probably okay to reuse INTERPRETER.
    However, instructions must always be reloaded.  */
 
-static void
+_Noreturn static void
 sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
                     const char *reason)
 {
   interpreter->trap_reason = reason;
   interpreter->call_depth = 0;
+  interpreter->state.loop = 1;
   longjmp (interpreter->trap, 1);
 }
 
@@ -6160,6 +6190,51 @@ sfnt_interpret_trap (struct sfnt_interpreter 
*interpreter,
         / 1024);                               \
   }
 
+#define JROT()                                 \
+  {                                            \
+    uint32_t e;                                        \
+    int32_t offset;                            \
+                                               \
+    e = POP ();                                        \
+    offset = POP ();                           \
+                                               \
+    if (!e)                                    \
+      break;                                   \
+                                               \
+    if (interpreter->IP + offset < 0           \
+       || (interpreter->IP + offset            \
+           > interpreter->num_instructions))   \
+      TRAP ("JMPR out of bounds");             \
+                                               \
+    interpreter->IP += offset;                 \
+    goto skip_step;                            \
+  }
+
+#define JROF()                                 \
+  {                                            \
+    uint32_t e;                                        \
+    int32_t offset;                            \
+                                               \
+    e = POP ();                                        \
+    offset = POP ();                           \
+                                               \
+    if (e)                                     \
+      break;                                   \
+                                               \
+    if (interpreter->IP + offset < 0           \
+       || (interpreter->IP + offset            \
+           > interpreter->num_instructions))   \
+      TRAP ("JMPR out of bounds");             \
+                                               \
+    interpreter->IP += offset;                 \
+    goto skip_step;                            \
+  }
+
+#define ILLEGAL_INSTRUCTION()                  \
+  {                                            \
+    TRAP ("MS reserved illegal instruction");  \
+  }
+
 #define SCANCTRL()                             \
   {                                            \
     uint32_t value;                            \
@@ -6593,6 +6668,76 @@ sfnt_interpret_trap (struct sfnt_interpreter 
*interpreter,
                             p2);               \
   }
 
+#define UTP()                                  \
+  {                                            \
+    uint32_t p;                                        \
+                                               \
+    p = POP ();                                        \
+    sfnt_interpret_utp (interpreter, p);       \
+  }
+
+#define MDAP()                                 \
+  {                                            \
+    uint32_t p;                                        \
+                                               \
+    p = POP ();                                        \
+    sfnt_interpret_mdap (interpreter, p,       \
+                        opcode);               \
+  }
+
+#define IUP()                                  \
+  {                                            \
+    sfnt_interpret_iup (interpreter, opcode);  \
+  }
+
+#define SHP()                                  \
+  {                                            \
+    sfnt_interpret_shp (interpreter, opcode);  \
+  }
+
+#define SHC()                                  \
+  {                                            \
+    uint32_t contour;                          \
+                                               \
+    contour = POP ();                          \
+                                               \
+    sfnt_interpret_shc (interpreter, contour,  \
+                       opcode);                \
+  }
+
+#define SHZ()                                  \
+  {                                            \
+    uint32_t e;                                        \
+                                               \
+    e = POP ();                                        \
+                                               \
+    if (e > 1)                                 \
+      TRAP ("invalid zone!");                  \
+                                               \
+    sfnt_interpret_shz (interpreter, e,                \
+                       opcode);                \
+  }
+
+#define SHPIX()                                        \
+  {                                            \
+    sfnt_f26dot6 pixels, dx, dy;               \
+    uint32_t p;                                        \
+                                               \
+    pixels = POP ();                           \
+    sfnt_scale_by_freedom_vector (interpreter, \
+                                 pixels, &dx,  \
+                                 &dy);         \
+                                               \
+    while (interpreter->state.loop--)          \
+      {                                                \
+       p = POP ();                             \
+       sfnt_direct_move_zp2 (interpreter,      \
+                             p, dx, dy);       \
+      }                                                \
+                                               \
+    interpreter->state.loop = 1;               \
+  }
+
 
 
 #define NOT_IMPLEMENTED()                      \
@@ -6601,6 +6746,47 @@ sfnt_interpret_trap (struct sfnt_interpreter 
*interpreter,
 
 
 
+/* Multiply the specified MAGNITUDE by the contents of INTERPRETER's
+   freedom vector and return the result in *DX and *DY.  */
+
+static void
+sfnt_scale_by_freedom_vector (struct sfnt_interpreter *interpreter,
+                             sfnt_f26dot6 magnitude, sfnt_f26dot6 *dx,
+                             sfnt_f26dot6 *dy)
+{
+  struct sfnt_unit_vector *vector;
+
+  vector = &interpreter->state.freedom_vector;
+  *dx = sfnt_mul_f2dot14 (vector->x, magnitude);
+  *dy = sfnt_mul_f2dot14 (vector->y, magnitude);
+}
+
+/* Interpret a UTP instruction with the point P in INTERPRETER.
+   Unset any ``touched'' flag inside the point P, relative to the
+   zone in INTERPRETER's ZP0 register.
+
+   Trap upon encountering an out of bounds point.  */
+
+static void
+sfnt_interpret_utp (struct sfnt_interpreter *interpreter,
+                   uint32_t p)
+{
+  if (!interpreter->state.zp0)
+    {
+      if (p >= interpreter->twilight_zone_size)
+       TRAP ("UTP[] p lies outside twilight zone");
+
+      /* There are no flags in the twilight zone.  */
+      return;
+    }
+
+  if (!interpreter->glyph_zone
+      || p >= interpreter->glyph_zone->num_points)
+    TRAP ("UTP[] p lies outside glyph zone");
+
+  interpreter->glyph_zone->flags[p] &= ~SFNT_POINT_TOUCHED_X;
+}
+
 /* Save the specified unit VECTOR into INTERPRETER's graphics
    state.  */
 
@@ -6628,12 +6814,16 @@ sfnt_save_freedom_vector (struct sfnt_interpreter 
*interpreter,
 /* Return the values of the point NUMBER in the zone pointed to by
    INTERPRETER's ZP2 register.
 
+   If X_ORG and Y_ORG are set, return the original values (prior to
+   any instruction interpretations) in those two locations.
+
    Trap if NUMBER is out of bounds or the zone is inaccessible.  */
 
 static void
 sfnt_address_zp2 (struct sfnt_interpreter *interpreter,
                  uint32_t number,
-                 sfnt_f26dot6 *x, sfnt_f26dot6 *y)
+                 sfnt_f26dot6 *x, sfnt_f26dot6 *y,
+                 sfnt_f26dot6 *x_org, sfnt_f26dot6 *y_org)
 {
   if (!interpreter->state.zp2)
     {
@@ -6643,6 +6833,13 @@ sfnt_address_zp2 (struct sfnt_interpreter *interpreter,
 
       *x = interpreter->twilight_x[number];
       *y = interpreter->twilight_y[number];
+
+      if (!x_org || !y_org)
+       return;
+
+      /* The twilight zone is initially all zero.  */
+      *x_org = 0;
+      *y_org = 0;
       return;
     }
 
@@ -6656,6 +6853,12 @@ sfnt_address_zp2 (struct sfnt_interpreter *interpreter,
 
   *x = interpreter->glyph_zone->x_current[number];
   *y = interpreter->glyph_zone->y_current[number];
+
+  if (x_org && y_org)
+    {
+      *x_org = interpreter->glyph_zone->x_points[number];
+      *y_org = interpreter->glyph_zone->y_points[number];
+    }
 }
 
 /* Return the values of the point NUMBER in the zone pointed to by
@@ -6666,7 +6869,8 @@ sfnt_address_zp2 (struct sfnt_interpreter *interpreter,
 static void
 sfnt_address_zp1 (struct sfnt_interpreter *interpreter,
                  uint32_t number,
-                 sfnt_f26dot6 *x, sfnt_f26dot6 *y)
+                 sfnt_f26dot6 *x, sfnt_f26dot6 *y,
+                 sfnt_f26dot6 *x_org, sfnt_f26dot6 *y_org)
 {
   if (!interpreter->state.zp1)
     {
@@ -6676,6 +6880,13 @@ sfnt_address_zp1 (struct sfnt_interpreter *interpreter,
 
       *x = interpreter->twilight_x[number];
       *y = interpreter->twilight_y[number];
+
+      if (!x_org || !y_org)
+       return;
+
+      /* The twilight zone is initially all zero.  */
+      *x_org = 0;
+      *y_org = 0;
       return;
     }
 
@@ -6689,6 +6900,12 @@ sfnt_address_zp1 (struct sfnt_interpreter *interpreter,
 
   *x = interpreter->glyph_zone->x_current[number];
   *y = interpreter->glyph_zone->y_current[number];
+
+  if (x_org && y_org)
+    {
+      *x_org = interpreter->glyph_zone->x_points[number];
+      *y_org = interpreter->glyph_zone->y_points[number];
+    }
 }
 
 /* Return the values of the point NUMBER in the zone pointed to by
@@ -6699,7 +6916,8 @@ sfnt_address_zp1 (struct sfnt_interpreter *interpreter,
 static void
 sfnt_address_zp0 (struct sfnt_interpreter *interpreter,
                  uint32_t number,
-                 sfnt_f26dot6 *x, sfnt_f26dot6 *y)
+                 sfnt_f26dot6 *x, sfnt_f26dot6 *y,
+                 sfnt_f26dot6 *x_org, sfnt_f26dot6 *y_org)
 {
   if (!interpreter->state.zp0)
     {
@@ -6709,6 +6927,13 @@ sfnt_address_zp0 (struct sfnt_interpreter *interpreter,
 
       *x = interpreter->twilight_x[number];
       *y = interpreter->twilight_y[number];
+
+      if (!x_org || !y_org)
+       return;
+
+      /* The twilight zone is initially all zero.  */
+      *x_org = 0;
+      *y_org = 0;
       return;
     }
 
@@ -6722,6 +6947,12 @@ sfnt_address_zp0 (struct sfnt_interpreter *interpreter,
 
   *x = interpreter->glyph_zone->x_current[number];
   *y = interpreter->glyph_zone->y_current[number];
+
+  if (x_org && y_org)
+    {
+      *x_org = interpreter->glyph_zone->x_points[number];
+      *y_org = interpreter->glyph_zone->y_points[number];
+    }
 }
 
 /* Set the point NUMBER in the zone referenced by INTERPRETER's ZP2
@@ -6787,48 +7018,153 @@ sfnt_line_to_standard_form (sfnt_f26dot6 x1, 
sfnt_f26dot6 y1,
 
 #endif
 
-/* Move the specified POINT in the zone addressed by INTERPRETER's ZP0
-   register by the given DISTANCE along the freedom vector.
+/* Check that the specified POINT lies within the zone addressed by
+   INTERPRETER's ZP2 register.  Trap if it does not.  */
+
+static void
+sfnt_check_zp2 (struct sfnt_interpreter *interpreter, uint32_t point)
+{
+  if (!interpreter->state.zp2)
+    {
+      if (point >= interpreter->twilight_zone_size)
+       TRAP ("point lies outside twilight zone (ZP2)");
+    }
+  else if (!interpreter->glyph_zone
+          || point >= interpreter->glyph_zone->num_points)
+    TRAP ("point lies outside glyph zone (ZP2)");
+}
+
+/* Move N points starting from the specified POINT in the zone
+   addressed by INTERPRETER's ZP0 register by the given DISTANCE along
+   the freedom vector.
 
    No checking is done to ensure that POINT lies inside the zone, or
    even that the zone exists at all.  */
 
 static void
 sfnt_move_zp0 (struct sfnt_interpreter *interpreter, uint32_t point,
-              sfnt_f26dot6 distance)
+              size_t n, sfnt_f26dot6 distance)
 {
   if (!interpreter->state.zp0)
     interpreter->state.move (&interpreter->twilight_x[point],
                             &interpreter->twilight_y[point],
-                            interpreter, distance, NULL);
+                            n, interpreter, distance, NULL);
   else
     interpreter->state.move (&interpreter->glyph_zone->x_current[point],
                             &interpreter->glyph_zone->y_current[point],
-                            interpreter, distance,
+                            n, interpreter, distance,
                             &interpreter->glyph_zone->flags[point]);
 }
 
-/* Move the specified POINT in the zone addressed by INTERPRETER's ZP1
-   register by the given DISTANCE along the freedom vector.
+/* Move N points starting from the specified POINT in the zone
+   addressed by INTERPRETER's ZP1 register by the given DISTANCE along
+   the freedom vector.
 
    No checking is done to ensure that POINT lies inside the zone, or
    even that the zone exists at all.  */
 
 static void
 sfnt_move_zp1 (struct sfnt_interpreter *interpreter, uint32_t point,
-              sfnt_f26dot6 distance)
+              size_t n, sfnt_f26dot6 distance)
 {
   if (!interpreter->state.zp1)
     interpreter->state.move (&interpreter->twilight_x[point],
                             &interpreter->twilight_y[point],
-                            interpreter, distance, NULL);
+                            n, interpreter, distance, NULL);
+  else
+    interpreter->state.move (&interpreter->glyph_zone->x_current[point],
+                            &interpreter->glyph_zone->y_current[point],
+                            n, interpreter, distance,
+                            &interpreter->glyph_zone->flags[point]);
+}
+
+/* Move N points starting from the specified POINT in the zone
+   addressed by INTERPRETER's ZP1 register by the given DISTANCE along
+   the freedom vector.
+
+   No checking is done to ensure that POINT lies inside the zone, or
+   even that the zone exists at all.  */
+
+static void
+sfnt_move_zp2 (struct sfnt_interpreter *interpreter, uint32_t point,
+              size_t n, sfnt_f26dot6 distance)
+{
+  if (!interpreter->state.zp2)
+    interpreter->state.move (&interpreter->twilight_x[point],
+                            &interpreter->twilight_y[point],
+                            n, interpreter, distance, NULL);
   else
     interpreter->state.move (&interpreter->glyph_zone->x_current[point],
                             &interpreter->glyph_zone->y_current[point],
-                            interpreter, distance,
+                            n, interpreter, distance,
                             &interpreter->glyph_zone->flags[point]);
 }
 
+/* Move N points from the specified POINT in INTERPRETER's glyph zone
+   by the given DISTANCE along the freedom vector.
+
+   No checking is done to ensure that POINT lies inside the zone, or
+   even that the zone exists at all.  */
+
+static void
+sfnt_move_glyph_zone (struct sfnt_interpreter *interpreter, uint32_t point,
+                     size_t n, sfnt_f26dot6 distance)
+{
+  interpreter->state.move (&interpreter->glyph_zone->x_current[point],
+                          &interpreter->glyph_zone->y_current[point],
+                          n, interpreter, distance,
+                          &interpreter->glyph_zone->flags[point]);
+}
+
+/* Move N points from the specified POINT in INTERPRETER's twilight
+   zone by the given DISTANCE along the freedom vector.
+
+   No checking is done to ensure that POINT lies inside the zone, or
+   even that the zone exists at all.  */
+
+static void
+sfnt_move_twilight_zone (struct sfnt_interpreter *interpreter, uint32_t point,
+                        size_t n, sfnt_f26dot6 distance)
+{
+  interpreter->state.move (&interpreter->twilight_x[point],
+                          &interpreter->twilight_y[point],
+                          n, interpreter, distance, NULL);
+}
+
+/* Move the point P in the zone pointed to by the ZP2 register in
+   INTERPRETER's graphics state by DX, and DY.
+
+   Check that P is valid; if not, trap.  Else, perform the move
+   directly without converting it from the projection vector or to the
+   freedom vector.  */
+
+static void
+sfnt_direct_move_zp2 (struct sfnt_interpreter *interpreter, uint32_t p,
+                     sfnt_f26dot6 dx, sfnt_f26dot6 dy)
+{
+  if (!interpreter->state.zp2)
+    {
+      if (p >= interpreter->twilight_zone_size)
+       TRAP ("point out of bounds");
+
+      interpreter->twilight_x[p]
+       = sfnt_add (interpreter->twilight_x[p], dx);
+      interpreter->twilight_y[p]
+       = sfnt_add (interpreter->twilight_y[p], dy);
+    }
+  else
+    {
+      if (!interpreter->glyph_zone
+         || p >= interpreter->glyph_zone->num_points)
+       TRAP ("point out of bounds");
+
+      interpreter->glyph_zone->x_current[p]
+       = sfnt_add (interpreter->glyph_zone->x_current[p], dx);
+      interpreter->glyph_zone->y_current[p]
+       = sfnt_add (interpreter->glyph_zone->y_current[p], dy);
+    }
+}
+
 /* Project the vector VX, VY onto INTERPRETER's projection vector.
    Return the magnitude of the projection.  */
 
@@ -6854,8 +7190,8 @@ sfnt_interpret_alignpts (struct sfnt_interpreter 
*interpreter,
   sfnt_f26dot6 p1x, p1y, p2x, p2y;
   sfnt_f26dot6 magnitude;
 
-  sfnt_address_zp0 (interpreter, p1, &p1x, &p1y);
-  sfnt_address_zp1 (interpreter, p2, &p2x, &p2y);
+  sfnt_address_zp0 (interpreter, p1, &p1x, &p1y, NULL, NULL);
+  sfnt_address_zp1 (interpreter, p2, &p2x, &p2y, NULL, NULL);
 
   magnitude = sfnt_project_vector (interpreter,
                                   sfnt_sub (p1x, p2x),
@@ -6863,8 +7199,8 @@ sfnt_interpret_alignpts (struct sfnt_interpreter 
*interpreter,
   magnitude = magnitude / 2;
 
   /* Now move both points along the freedom vector.  */
-  sfnt_move_zp0 (interpreter, p1, magnitude);
-  sfnt_move_zp1 (interpreter, p2, -magnitude);
+  sfnt_move_zp0 (interpreter, p1, 1, magnitude);
+  sfnt_move_zp1 (interpreter, p2, 1, -magnitude);
 }
 
 /* Set the point P in the zone referenced in INTERPRETER's ZP2
@@ -6893,10 +7229,10 @@ sfnt_interpret_isect (struct sfnt_interpreter 
*interpreter,
 #endif
 
   /* Load points.  */
-  sfnt_address_zp0 (interpreter, point_a0, &a0x, &a0y);
-  sfnt_address_zp0 (interpreter, point_a1, &a1x, &a1y);
-  sfnt_address_zp1 (interpreter, point_b0, &b0x, &b0y);
-  sfnt_address_zp1 (interpreter, point_b1, &b1x, &b1y);
+  sfnt_address_zp0 (interpreter, point_a0, &a0x, &a0y, NULL, NULL);
+  sfnt_address_zp0 (interpreter, point_a1, &a1x, &a1y, NULL, NULL);
+  sfnt_address_zp1 (interpreter, point_b0, &b0x, &b0y, NULL, NULL);
+  sfnt_address_zp1 (interpreter, point_b1, &b1x, &b1y, NULL, NULL);
 
 #if 0
   /* The system is determined from the standard form (look this up) of
@@ -7112,8 +7448,8 @@ sfnt_line_to_vector (struct sfnt_interpreter *interpreter,
   sfnt_f26dot6 x1, y1;
   sfnt_f26dot6 a, b, temp;
 
-  sfnt_address_zp2 (interpreter, p2, &x2, &y2);
-  sfnt_address_zp1 (interpreter, p1, &x1, &y1);
+  sfnt_address_zp2 (interpreter, p2, &x2, &y2, NULL, NULL);
+  sfnt_address_zp1 (interpreter, p1, &x1, &y1, NULL, NULL);
 
   /* Calculate the vector between X2, Y2, and X1, Y1.  */
   a = sfnt_sub (x1, x2);
@@ -7247,6 +7583,10 @@ sfnt_deltac (int number, struct sfnt_interpreter 
*interpreter,
     case 15:
       delta = 8;
       break;
+
+      /* To pacify -fanalyzer.  */
+    default:
+      abort ();
     }
 
   /* Now, scale up the delta by the step size, which is determined by
@@ -7258,6 +7598,42 @@ sfnt_deltac (int number, struct sfnt_interpreter 
*interpreter,
                                      delta);
 }
 
+/* Interpret an MDAP (Move Direct Absolute Point) instruction with the
+   opcode OPCODE and the operand P in INTERPRETER.
+
+   Touch the point P (within the zone specified in zp0) in the
+   directions specified in the freedom vector.  Then, if OPCODE is
+   0x7f, round the point and move it the rounded distance along the
+   freedom vector.
+
+   Finally, set the RP0 and RP1 registers to P.  */
+
+static void
+sfnt_interpret_mdap (struct sfnt_interpreter *interpreter,
+                    uint32_t p, uint32_t opcode)
+{
+  sfnt_f26dot6 distance, px, py;
+
+  sfnt_address_zp0 (interpreter, p, &px, &py, NULL, NULL);
+
+  if (opcode == 0x7f)
+    {
+      /* Measure distance, round, then move by distance.  */
+      distance = sfnt_project_vector (interpreter, px, py);
+      distance = sfnt_sub (interpreter->state.round (distance,
+                                                    interpreter),
+                          distance);
+    }
+  else
+    /* Don't move.  Just touch the point.  */
+    distance = 0;
+
+  sfnt_move_zp0 (interpreter, p, 1, distance);
+
+  interpreter->state.rp0 = p;
+  interpreter->state.rp1 = p;
+}
+
 /* Needed by sfnt_interpret_call.  */
 static void sfnt_interpret_run (struct sfnt_interpreter *,
                                enum sfnt_interpreter_run_context);
@@ -7293,6 +7669,7 @@ sfnt_interpret_call (struct sfnt_interpreter_definition 
*definition,
   /* Load and run the definition.  */
   interpreter->num_instructions = definition->instruction_count;
   interpreter->instructions = definition->instructions;
+  interpreter->glyph_zone = NULL;
   interpreter->IP = 0;
   sfnt_interpret_run (interpreter, context);
 
@@ -7803,6 +8180,7 @@ sfnt_project_onto_y_axis_vector (sfnt_f26dot6 vx, 
sfnt_f26dot6 vy,
 static int32_t
 sfnt_dot_fix_14 (int32_t ax, int32_t ay, int bx, int by)
 {
+#ifndef INT64_MAX
   int32_t m, s, hi1, hi2, hi;
   uint32_t l, lo1, lo2, lo;
 
@@ -7821,20 +8199,32 @@ sfnt_dot_fix_14 (int32_t ax, int32_t ay, int bx, int by)
   lo2 = l + ((uint32_t) m << 16);
   hi2 = (m >> 16) + ((int32_t) l >> 31) + (lo2 < l);
 
-  /* add them */
+  /* Add them.  */
   lo = lo1 + lo2;
   hi = hi1 + hi2 + (lo < lo1);
 
-  /* divide the result by 2^14 with rounding */
-  s   = hi >> 31;
-  l   = lo + (uint32_t) s;
+  /* Divide the result by 2^14 with rounding.  */
+  s = hi >> 31;
+  l = lo + (uint32_t) s;
   hi += s + (l < lo);
-  lo  = l;
+  lo = l;
 
-  l   = lo + 0x2000u;
+  l = lo + 0x2000u;
   hi += (l < lo);
 
   return (int32_t) (((uint32_t) hi << 18) | (l >> 14));
+#else
+  int64_t xx, yy;
+
+  xx = (int64_t) ax * bx;
+  yy = (int64_t) ay * by;
+
+  xx += yy;
+  yy = xx >> 63;
+  xx += 0x2000 + yy;
+
+  return (int32_t) (yy / (2 << 14));
+#endif
 }
 
 /* Project the specified vector VX and VY onto the unit vector that is
@@ -7852,48 +8242,51 @@ sfnt_project_onto_any_vector (sfnt_f26dot6 vx, 
sfnt_f26dot6 vy,
                          interpreter->state.projection_vector.y);
 }
 
-/* Move the point at *X, *Y by DISTANCE along INTERPRETER's freedom
+/* Move N points at *X, *Y by DISTANCE along INTERPRETER's freedom
    vector.  Set *FLAGS where appropriate and when non-NULL.
 
    Assume both vectors are aligned to the X axis.  */
 
 static void
-sfnt_move_x (sfnt_f26dot6 *x, sfnt_f26dot6 *y,
-            struct sfnt_interpreter *interpreter,
+sfnt_move_x (sfnt_f26dot6 *restrict x, sfnt_f26dot6 *restrict y,
+            size_t n, struct sfnt_interpreter *interpreter,
             sfnt_f26dot6 distance, unsigned char *flags)
 {
-  *x = sfnt_add (*x, distance);
+  while (n--)
+    *x = sfnt_add (*x, distance);
 
   if (flags)
     *flags |= SFNT_POINT_TOUCHED_X;
 }
 
-/* Move the point at *X, *Y by DISTANCE along INTERPRETER's freedom
+/* Move N points at *X, *Y by DISTANCE along INTERPRETER's freedom
    vector.  Set *FLAGS where appropriate and when non-NULL.
 
    Assume both vectors are aligned to the Y axis.  */
 
 static void
-sfnt_move_y (sfnt_f26dot6 *x, sfnt_f26dot6 *y,
-            struct sfnt_interpreter *interpreter,
+sfnt_move_y (sfnt_f26dot6 *restrict x, sfnt_f26dot6 *restrict y,
+            size_t n, struct sfnt_interpreter *interpreter,
             sfnt_f26dot6 distance, unsigned char *flags)
 {
-  *y = sfnt_add (*y, distance);
+  while (n--)
+    *y = sfnt_add (*y, distance);
 
   if (flags)
     *flags |= SFNT_POINT_TOUCHED_Y;
 }
 
-/* Move the point at *X, *Y by DISTANCE along INTERPRETER's freedom
+/* Move N points at *X, *Y by DISTANCE along INTERPRETER's freedom
    vector.  Set *FLAGS where appropriate and when non-NULL.  */
 
 static void
-sfnt_move (sfnt_f26dot6 *x, sfnt_f26dot6 *y,
-          struct sfnt_interpreter *interpreter,
+sfnt_move (sfnt_f26dot6 *restrict x, sfnt_f26dot6 *restrict y,
+          size_t n, struct sfnt_interpreter *interpreter,
           sfnt_f26dot6 distance, unsigned char *flags)
 {
   sfnt_f26dot6 versor;
   sfnt_f2dot14 dot_product;
+  size_t num;
 
   dot_product = interpreter->state.vector_dot_product;
 
@@ -7905,9 +8298,15 @@ sfnt_move (sfnt_f26dot6 *x, sfnt_f26dot6 *y,
     {
       /* Move along X axis, converting the distance to the freedom
         vector.  */
-      *x = sfnt_add (*x, sfnt_multiply_divide_signed (distance,
-                                                     versor,
-                                                     dot_product));
+      num = n;
+
+      while (num--)
+       {
+         *x = sfnt_add (*x, sfnt_multiply_divide_signed (distance,
+                                                         versor,
+                                                         dot_product));
+         x++;
+       }
 
       if (flags)
        *flags |= SFNT_POINT_TOUCHED_X;
@@ -7919,9 +8318,15 @@ sfnt_move (sfnt_f26dot6 *x, sfnt_f26dot6 *y,
     {
       /* Move along X axis, converting the distance to the freedom
         vector.  */
-      *y = sfnt_add (*y, sfnt_multiply_divide_signed (distance,
-                                                     versor,
-                                                     dot_product));
+      num = n;
+
+      while (num--)
+       {
+         *y = sfnt_add (*y, sfnt_multiply_divide_signed (distance,
+                                                         versor,
+                                                         dot_product));
+         y++;
+       }
 
       if (flags)
        *flags |= SFNT_POINT_TOUCHED_Y;
@@ -7980,7 +8385,7 @@ sfnt_validate_gs (struct sfnt_graphics_state *gs)
 
   if (gs->projection_vector.x == 040000)
     gs->project = sfnt_project_onto_x_axis_vector;
-  else if (gs->projection_vector.y == 0x40000)
+  else if (gs->projection_vector.y == 040000)
     gs->project = sfnt_project_onto_y_axis_vector;
   else
     gs->project = sfnt_project_onto_any_vector;
@@ -8043,12 +8448,368 @@ sfnt_set_projection_vector (struct sfnt_interpreter 
*interpreter,
   sfnt_validate_gs (&interpreter->state);
 }
 
+/* Interpret an SHZ instruction with the specified OPCODE.  Like
+   sfnt_interpret_shc, but do the move for each point in the entire
+   specified ZONE.  */
+
+static void
+sfnt_interpret_shz (struct sfnt_interpreter *interpreter,
+                   uint32_t zone, unsigned int opcode)
+{
+  sfnt_f26dot6 x, y, original_x, original_y;
+  sfnt_f26dot6 magnitude;
+
+  if (zone != 0 && !interpreter->glyph_zone)
+    /* There are no points in the glyph zone.  */
+    return;
+
+  if (opcode == 0x37)
+    sfnt_address_zp0 (interpreter, interpreter->state.rp1,
+                     &x, &y, &original_x, &original_y);
+  else
+    sfnt_address_zp1 (interpreter, interpreter->state.rp2,
+                     &x, &y, &original_x, &original_y);
+
+  magnitude = sfnt_project_vector (interpreter,
+                                  sfnt_sub (x, original_x),
+                                  sfnt_sub (y, original_y));
+
+  if (zone == 0)
+    sfnt_move_twilight_zone (interpreter, 0,
+                            interpreter->twilight_zone_size,
+                            magnitude);
+  else
+    sfnt_move_glyph_zone (interpreter, 0,
+                         interpreter->glyph_zone->num_points,
+                         magnitude);
+}
+
+/* Interpret an SHC instruction with the specified OPCODE and CONTOUR.
+   Like sfnt_interpret_shp, but do the move for each point in the
+   specified contour.  */
+
+static void
+sfnt_interpret_shc (struct sfnt_interpreter *interpreter,
+                   uint32_t contour, unsigned int opcode)
+{
+  sfnt_f26dot6 x, y, original_x, original_y;
+  sfnt_f26dot6 magnitude;
+  size_t start, end, n;
+
+  if (!interpreter->glyph_zone)
+    TRAP ("SHC without glyph zone");
+
+  /* Check that the contour is within bounds.  */
+  if (contour >= interpreter->glyph_zone->num_contours)
+    TRAP ("contour out of bounds");
+
+  /* Figure out the magnitude of the change, measured from the
+     projection vector.  */
+
+  if (opcode == 0x35)
+    sfnt_address_zp0 (interpreter, interpreter->state.rp1,
+                     &x, &y, &original_x, &original_y);
+  else
+    sfnt_address_zp1 (interpreter, interpreter->state.rp2,
+                     &x, &y, &original_x, &original_y);
+
+  magnitude = sfnt_project_vector (interpreter,
+                                  sfnt_sub (x, original_x),
+                                  sfnt_sub (y, original_y));
+
+  /* Now obtain the start and end of the contour.
+     Verify that both are valid.  */
+
+  if (contour)
+    start = interpreter->glyph_zone->contour_end_points[contour - 1];
+  else
+    start = 0;
+
+  end = interpreter->glyph_zone->contour_end_points[contour];
+
+  if (start > end || end >= interpreter->glyph_zone->num_points)
+    TRAP ("invalid contour data in glyph");
+
+  /* Compute the number of points to move.  */
+  n = end - start + 1;
+
+  /* Move that many points.  */
+  sfnt_move_glyph_zone (interpreter, start, n, magnitude);
+}
+
+/* Interpret an SHP instruction with the specified OPCODE.  Move a
+   popped point in ZP2 along the freedom vector by the distance
+   between a specified point from its original position, which is RP1
+   in ZP0 if OPCODE is 0x33, and RP2 in ZP1 if OPCODE is 0x32.
+
+   Repeat for the number of iterations specified by a prior SLOOP
+   instruction.  */
+
+static void
+sfnt_interpret_shp (struct sfnt_interpreter *interpreter,
+                   unsigned int opcode)
+{
+  sfnt_f26dot6 x, y, original_x, original_y;
+  sfnt_f26dot6 magnitude;
+  uint32_t point;
+
+  /* Figure out the magnitude of the change, measured from the
+     projection vector.  */
+
+  if (opcode == 0x33)
+    sfnt_address_zp0 (interpreter, interpreter->state.rp1,
+                     &x, &y, &original_x, &original_y);
+  else
+    sfnt_address_zp1 (interpreter, interpreter->state.rp2,
+                     &x, &y, &original_x, &original_y);
+
+  magnitude = sfnt_project_vector (interpreter,
+                                  sfnt_sub (x, original_x),
+                                  sfnt_sub (y, original_y));
+
+  /* Now project it onto the freedom vector and move the point that
+     much for loop variable times.  */
+
+  while (interpreter->state.loop--)
+    {
+      point = POP ();
+
+      sfnt_move_zp2 (interpreter, point, 1, magnitude);
+      sfnt_check_zp2 (interpreter, point);
+    }
+
+  /* Restore interpreter->state.loop to 1.  */
+  interpreter->state.loop = 1;
+}
+
+/* Interpolate untouched points in the contour between and including
+   START and END inside INTERPRETER's glyph zone according to the
+   rules specified for an IUP instruction.  Perform interpolation on
+   the axis specified by OPCODE and MASK.  */
+
+static void
+sfnt_interpret_iup_1 (struct sfnt_interpreter *interpreter,
+                     size_t start, size_t end,
+                     unsigned char opcode, int mask)
+{
+  size_t point;
+  size_t touch_start, touch_end;
+  size_t first_point;
+  size_t point_min, point_max, i;
+  sfnt_f26dot6 position, min_pos, max_pos, delta;
+  sfnt_f26dot6 original_max_pos;
+  sfnt_f26dot6 original_min_pos;
+
+#define load_point(p)                          \
+  (opcode == 0x31                              \
+   ? interpreter->glyph_zone->x_current[p]     \
+   : interpreter->glyph_zone->x_current[p])
+
+#define store_point(p, val)                            \
+  (opcode == 0x31                                      \
+   ? (interpreter->glyph_zone->x_current[p] = (val))   \
+   : (interpreter->glyph_zone->y_current[p] = (val)))
+
+#define load_original(p)                       \
+  (opcode == 0x31                              \
+   ? interpreter->glyph_zone->x_points[p]      \
+   : interpreter->glyph_zone->y_points[p])
+
+  /* Find the first touched point.  If none is found, simply
+     return.  */
+
+  for (point = start; point <= end; ++point)
+    {
+      if (interpreter->glyph_zone->flags[point] & mask)
+       goto touched;
+    }
+
+  goto untouched;
+
+ touched:
+
+  point = start;
+
+  while (true)
+    {
+      /* first_point says when to stop looking for a closing
+        point.  */
+      first_point = point;
+
+      /* Find the next untouched point.  */
+      while (interpreter->glyph_zone->flags[point] & mask)
+       {
+         point++;
+
+         /* Move back to start if point has gone past the end of the
+            contour.  */
+         if (point > end)
+           point = start;
+
+         if (point == first_point)
+           /* There are no more untouched points.  */
+           goto untouched;
+       }
+
+      /* touch_start is now the first untouched point.  */
+      touch_start = point;
+
+      /* Find the next touched point.  */
+      while (!(interpreter->glyph_zone->flags[point] & mask))
+       {
+         point++;
+
+         /* Move back to start if point has gone past the end of the
+            contour.  */
+         if (point > end)
+           point = start;
+
+         if (point == touch_start)
+           /* There are no more touched points.  */
+           goto untouched;
+       }
+
+      /* touch_end is now the next touched point.  */
+      touch_end = point;
+
+      /* Now make touch_start the first point before, i.e. the first
+        touched point in this pair.  */
+
+      if (touch_start == start)
+       touch_start = end;
+      else
+       touch_start = touch_start - 1;
+
+      /* Set point_min and point_max based on which glyph is at a
+        lower value.  */
+
+      if (load_original (touch_start) < touch_end)
+       {
+         point_min = touch_start;
+         point_max = touch_end;
+       }
+      else
+       {
+         point_max = touch_start;
+         point_min = touch_end;
+       }
+
+      min_pos = load_point (point_min);
+      max_pos = load_point (point_max);
+
+      /* This is needed for interpolation.  */
+      original_max_pos = load_original (max_pos);
+      original_min_pos = load_original (min_pos);
+
+      /* Now process points between touch_start and touch_end.  */
+
+      i = touch_start;
+
+      do
+       {
+         ++i;
+
+         if (i == end)
+           i = start;
+
+         /* Movement is always relative to the original position of
+            the point.  */
+         position = load_original (i);
+
+         /* If i is in between touch_start and touch_end...  */
+         if (position >= original_min_pos
+             && position <= original_max_pos)
+           {
+             /* ... linearly interpolate i between min_pos and
+                max_pos...  */
+             delta = sfnt_sub (max_pos, min_pos) / 2;
+             store_point (i, sfnt_add (max_pos, delta));
+           }
+         else
+           {
+             /* ... otherwise, move i by how much the nearest touched
+                point moved.  */
+
+             if (position >= original_max_pos)
+               delta = sfnt_sub (max_pos, original_max_pos);
+             else
+               delta = sfnt_sub (min_pos, original_min_pos);
+
+             store_point (i, position + delta);
+           }
+       }
+      while (i != touch_end);
+
+      /* Handle the degenerate case where the first and last points of
+        the entire contour are touched, and as a result the loop
+        continues forever.  */
+      if (touch_start == touch_end)
+       goto untouched;
+    }
+
+#undef load_point
+#undef store_point
+#undef load_original
+
+ untouched:
+  /* No points were touched or all points have been considered, so
+     return immediately.  */
+  return;
+}
+
+/* Interpret an IUP (``interpolate untouched points'') instruction.
+   INTERPRETER is the interpreter, and OPCODE is the instruction
+   number.  See the TrueType Reference Manual for more details.  */
+
+static void
+sfnt_interpret_iup (struct sfnt_interpreter *interpreter,
+                   unsigned char opcode)
+{
+  int mask;
+  size_t i, point, end, first_point;
+
+  /* Check that the zone is the glyph zone.  */
+
+  if (!interpreter->state.zp2)
+    TRAP ("trying to iup in twilight zone");
+
+  if (!interpreter->glyph_zone)
+    TRAP ("iup without loaded glyph!");
+
+  /* Figure out what axis to interpolate in based on the opcode.  */
+  if (opcode == 0x31)
+    mask = SFNT_POINT_TOUCHED_Y;
+  else
+    mask = SFNT_POINT_TOUCHED_X;
+
+  /* Now, for each contour, interpolate untouched points.  */
+  point = 0;
+  for (i = 0; i < interpreter->glyph_zone->num_contours; ++i)
+    {
+      first_point = point;
+      end = interpreter->glyph_zone->contour_end_points[i];
+
+      if (point >= interpreter->glyph_zone->num_points
+         || end >= interpreter->glyph_zone->num_points)
+       TRAP ("glyph contains out of bounds contour end point"
+             " data!");
+
+      sfnt_interpret_iup_1 (interpreter, first_point, end,
+                           opcode, mask);
+      point = end + 1;
+    }
+}
+
 /* Execute the program now loaded into INTERPRETER.
    WHY specifies why the interpreter is being run, and is used to
    control the behavior of instructions such IDEF[] and FDEF[].
 
-   Control may be transferred to INTERPRETER->trap if interpretation
-   fails.  */
+   Transfer control to INTERPRETER->trap if interpretation is aborted
+   due to an error, and set INTERPRETER->trap_reason to a string
+   describing the error.
+
+   INTERPRETER->glyph_zone should be cleared before calling this
+   function.  */
 
 static void
 sfnt_interpret_run (struct sfnt_interpreter *interpreter,
@@ -8231,7 +8992,7 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
          break;
 
        case 0x29:  /* UTP */
-         NOT_IMPLEMENTED ();
+         UTP ();
          break;
 
        case 0x2A:  /* LOOPCALL */
@@ -8252,31 +9013,31 @@ sfnt_interpret_run (struct sfnt_interpreter 
*interpreter,
 
        case 0x2E:  /* MDAP */
        case 0x2F:  /* MDAP */
-         NOT_IMPLEMENTED ();
+         MDAP ();
          break;
 
        case 0x30:  /* IUP */
        case 0x31:  /* IUP */
-         NOT_IMPLEMENTED ();
+         IUP ();
          break;
 
        case 0x32:  /* SHP */
        case 0x33:  /* SHP */
-         NOT_IMPLEMENTED ();
+         SHP ();
          break;
 
        case 0x34:  /* SHC */
        case 0x35:  /* SHC */
-         NOT_IMPLEMENTED ();
+         SHC ();
          break;
 
        case 0x36:  /* SHZ */
        case 0x37:  /* SHZ */
-         NOT_IMPLEMENTED ();
+         SHZ ();
          break;
 
        case 0x38:  /* SHPIX */
-         NOT_IMPLEMENTED ();
+         SHPIX ();
          break;
 
        case 0x39:  /* IP    */
@@ -8499,19 +9260,19 @@ sfnt_interpret_run (struct sfnt_interpreter 
*interpreter,
          break;
 
        case 0x78:  /* JROT */
-         NOT_IMPLEMENTED ();
+         JROT ();
          break;
 
        case 0x79:  /* JROF */
-         NOT_IMPLEMENTED ();
+         JROF ();
          break;
 
        case 0x7A:  /* ROFF */
          ROFF ();
          break;
 
-       case 0x7B:  /* ???? */
-         NOT_IMPLEMENTED ();
+       case 0x7B:  /* ILLEGAL_INSTRUCTION */
+         ILLEGAL_INSTRUCTION ();
          break;
 
        case 0x7C:  /* RUTG */
@@ -8642,6 +9403,7 @@ sfnt_interpret_font_program (struct sfnt_interpreter 
*interpreter,
   interpreter->SP = interpreter->stack;
   interpreter->instructions = fpgm->instructions;
   interpreter->num_instructions = fpgm->num_instructions;
+  interpreter->glyph_zone = NULL;
 
   sfnt_interpret_run (interpreter, SFNT_RUN_CONTEXT_FONT_PROGRAM);
   return NULL;
@@ -8666,6 +9428,7 @@ sfnt_interpret_control_value_program (struct 
sfnt_interpreter *interpreter,
   interpreter->SP = interpreter->stack;
   interpreter->instructions = prep->instructions;
   interpreter->num_instructions = prep->num_instructions;
+  interpreter->glyph_zone = NULL;
 
   sfnt_interpret_run (interpreter,
                      SFNT_RUN_CONTEXT_CONTROL_VALUE_PROGRAM);
@@ -8812,9 +9575,9 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
   zone->contour_end_points = (size_t *) (glyph + 1);
   zone->x_points = (sfnt_f26dot6 *) (zone->contour_end_points
                                     + zone->num_points);
-  zone->y_points = zone->x_points + zone->num_points;
-  zone->x_current = zone->y_points + zone->num_points;
-  zone->y_current = zone->x_current + zone->num_points;
+  zone->x_current = zone->x_points + zone->num_points;
+  zone->y_points = zone->x_current + zone->num_points;
+  zone->y_current = zone->y_points + zone->num_points;
   zone->flags = (unsigned char *) (zone->y_current
                                   + zone->num_points);
 
@@ -8840,6 +9603,8 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
   /* Load phantom points.  */
   zone->x_points[i] = phantom_point_1_x;
   zone->x_points[i + 1] = phantom_point_2_x;
+  zone->x_current[i] = phantom_point_1_x;
+  zone->x_current[i + 1] = phantom_point_2_x;
 
   /* Load y_points and y_current, along with flags.  */
   for (i = 0; i < glyph->simple->number_of_points; ++i)
@@ -8862,6 +9627,8 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
   /* Load phantom points.  */
   zone->y_points[i] = phantom_point_1_y;
   zone->y_points[i + 1] = phantom_point_2_y;
+  zone->y_current[i] = phantom_point_1_x;
+  zone->y_current[i + 1] = phantom_point_2_x;
 
   /* Load contour end points.  */
   for (i = 0; i < zone->num_contours; ++i)
@@ -10153,6 +10920,22 @@ static struct sfnt_generic_test_args wcvtf_test_args =
     7,
   };
 
+static struct sfnt_generic_test_args jrot_test_args =
+  {
+    (uint32_t []) { 40, 40, },
+    2,
+    false,
+    13,
+  };
+
+static struct sfnt_generic_test_args jrof_test_args =
+  {
+    (uint32_t []) { 4, },
+    1,
+    false,
+    13,
+  };
+
 static struct sfnt_generic_test_args deltac1_test_args =
   {
     (uint32_t []) { ((50 * 17 * 65535 / 800) >> 10) + 8,
@@ -11520,6 +12303,42 @@ static struct sfnt_interpreter_test all_tests[] =
       &wcvtf_test_args,
       sfnt_generic_check,
     },
+    {
+      "JROT",
+      /* PUSHB[1] 4 0
+        JROT[] ; this should not skip past the next instruction
+        PUSHB[1] 40 40
+        PUSHB[1] 3 1
+        JROT[] ; this should skip past the next instruction
+        PUSHB[0] 4 */
+      (unsigned char []) { 0xb1, 4, 0,
+                          0x78,
+                          0xb1, 40, 40,
+                          0xb1, 3, 1,
+                          0x78,
+                          0xb0, 4, },
+      13,
+      &jrot_test_args,
+      sfnt_generic_check,
+    },
+    {
+      "JROF",
+      /* PUSHB[1] 4 0
+        JROF[] ; this should skip past the next instruction
+        PUSHB[1] 40 40
+        PUSHB[1] 3 1
+        JROF[] ; this should not skip past the next instruction
+        PUSHB[0] 4 */
+      (unsigned char []) { 0xb1, 4, 0,
+                          0x79,
+                          0xb1, 40, 40,
+                          0xb1, 3, 1,
+                          0x79,
+                          0xb0, 4, },
+      13,
+      &jrof_test_args,
+      sfnt_generic_check,
+    },
     {
       "DELTAC1",
       /* PUSHB[0] 2
@@ -11872,6 +12691,9 @@ main (int argc, char **argv)
     {
       interpreter = sfnt_make_test_interpreter ();
 
+      if (!interpreter)
+       abort ();
+
       for (i = 0; i < ARRAYELTS (all_tests); ++i)
        sfnt_run_interpreter_test (&all_tests[i], interpreter);
 



reply via email to

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