emacs-diffs
[Top][All Lists]
Advanced

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

feature/android 87cdbbeb8a 1/3: Update Android port


From: Po Lu
Subject: feature/android 87cdbbeb8a 1/3: Update Android port
Date: Sun, 5 Feb 2023 08:15:58 -0500 (EST)

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

    Update Android port
    
    * src/sfnt.c (struct sfnt_graphics_state):
    (LOOPCALL):
    (DELTAC3):
    (PROJECT):
    (SHPIX):
    (sfnt_save_projection_vector):
    (sfnt_check_zp0):
    (sfnt_dual_project_vector):
    (sfnt_interpret_scfs):
    (sfnt_round_symmetric):
    (sfnt_interpret_miap):
    (sfnt_interpret_alignrp_1):
    (sfnt_interpret_alignrp):
    (sfnt_measure_distance):
    (sfnt_interpret_msirp):
    (sfnt_interpret_ip):
    (sfnt_interpret_mdap):
    (sfnt_deltap):
    (sfnt_dual_project_onto_any_vector):
    (sfnt_validate_gs):
    (sfnt_set_projection_vector):
    (sfnt_interpret_shp):
    (sfnt_interpret_run):
    (sfnt_check_sloop):
    (main): Check in more WIP font code.
---
 src/sfnt.c | 693 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 666 insertions(+), 27 deletions(-)

diff --git a/src/sfnt.c b/src/sfnt.c
index 0d87ed36da..6d060fde7d 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -1,4 +1,4 @@
-/* sfnt format font support for GNU Emacs.
+/* TrueType format font support for GNU Emacs.
 
 Copyright (C) 2023 Free Software Foundation, Inc.
 
@@ -106,7 +106,21 @@ xfree (void *ptr)
 
    Try not to keep this file too dependent on Emacs.  Everything Lisp
    related goes in sfntfont.c.  The author wants to keep using it for
-   some other (free) software.  */
+   some other (free) software.
+
+   The source of reference is the TrueType Reference Manual, published
+   by Apple Computer, which is currently found at:
+
+     https://developer.apple.com/fonts/TrueType-Reference-Manual/
+
+   Apple's TrueType implementation is notably missing features
+   provided by Microsoft's extended OpenType scaler, such as the two
+   additional phantom points on the Y axis, and also behaves
+   differently, especially when it comes to considering phantom points
+   as anchors in compound glyphs.
+
+   As a result, do not expect this scaler to work well with Microsoft
+   fonts such as Arial.  */
 
 
 
@@ -4915,6 +4929,12 @@ struct sfnt_graphics_state
   sfnt_f26dot6 (*project) (sfnt_f26dot6, sfnt_f26dot6,
                           struct sfnt_interpreter *);
 
+  /* Pointer to the function used to project euclidean vectors onto
+     the dual projection vector.  Value is the magnitude of the
+     projected vector.  */
+  sfnt_f26dot6 (*dual_project) (sfnt_f26dot6, sfnt_f26dot6,
+                               struct sfnt_interpreter *);
+
   /* Pointer to the function used to move specified points
      along the freedom vector by a distance specified in terms
      of the projection vector.  */
@@ -5776,6 +5796,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
                                                \
     id = POP ();                               \
     n = POP ();                                        \
+    def = NULL; /* Pacify -fanalyzer.  */      \
                                                \
     if (n > 65535)                             \
       TRAP ("invalid LOOPCALL count");         \
@@ -6444,7 +6465,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
 
 
 
-/* CVT delta exception instructions.
+/* CVT and point delta exception instructions.
 
    ``Exceptions'' can be placed directly inside the control value
    table, as it is reloaded every time the point size changes.  */
@@ -6503,6 +6524,54 @@ sfnt_interpret_trap (struct sfnt_interpreter 
*interpreter,
     goto deltac3_start;                                \
   }
 
+#define DELTAP1()                              \
+  {                                            \
+    uint32_t n, argn, pn;                      \
+                                               \
+    n = POP ();                                        \
+                                               \
+  deltap1_start:                               \
+    if (!n)                                    \
+      break;                                   \
+                                               \
+    argn = POP ();                             \
+    pn = POP ();                               \
+    sfnt_deltap (1, interpreter, argn, pn);    \
+    goto deltap1_start;                                \
+  }
+
+#define DELTAP2()                              \
+  {                                            \
+    uint32_t n, argn, pn;                      \
+                                               \
+    n = POP ();                                        \
+                                               \
+  deltap2_start:                               \
+    if (!n)                                    \
+      break;                                   \
+                                               \
+    argn = POP ();                             \
+    pn = POP ();                               \
+    sfnt_deltap (2, interpreter, argn, pn);    \
+    goto deltap2_start;                                \
+  }
+
+#define DELTAP3()                              \
+  {                                            \
+    uint32_t n, argn, pn;                      \
+                                               \
+    n = POP ();                                        \
+                                               \
+  deltap3_start:                               \
+    if (!n)                                    \
+      break;                                   \
+                                               \
+    argn = POP ();                             \
+    pn = POP ();                               \
+    sfnt_deltap (3, interpreter, argn, pn);    \
+    goto deltap3_start;                                \
+  }
+
 
 
 /* Anachronistic angle instructions.  */
@@ -6521,6 +6590,12 @@ sfnt_interpret_trap (struct sfnt_interpreter 
*interpreter,
 
 /* Projection and freedom vector operations.  */
 
+#define PROJECT(x, y)                          \
+  sfnt_project_vector (interpreter, x, y)
+
+#define DUAL_PROJECT(x, y)                     \
+  sfnt_dual_project_vector (interpreter, x, y)
+
 #define SVTCAy()                               \
   {                                            \
     sfnt_set_freedom_vector (interpreter,      \
@@ -6738,6 +6813,85 @@ sfnt_interpret_trap (struct sfnt_interpreter 
*interpreter,
     interpreter->state.loop = 1;               \
   }
 
+#define IP()                                   \
+  {                                            \
+    sfnt_interpret_ip (interpreter);           \
+  }
+
+#define MSIRP()                                        \
+  {                                            \
+    sfnt_f26dot6 d;                            \
+    uint32_t p;                                        \
+                                               \
+    d = POP ();                                        \
+    p = POP ();                                        \
+                                               \
+    sfnt_interpret_msirp (interpreter, d, p,   \
+                         opcode);              \
+  }
+
+#define ALIGNRP()                              \
+  {                                            \
+    sfnt_interpret_alignrp (interpreter);      \
+  }
+
+#define MIAP()                                 \
+  {                                            \
+    uint32_t cvt;                              \
+    uint32_t p;                                        \
+                                               \
+    cvt = POP ();                              \
+    p = POP ();                                        \
+                                               \
+    sfnt_interpret_miap (interpreter, cvt, p,  \
+                        opcode);               \
+  }
+
+#define GC()                                   \
+  {                                            \
+    uint32_t p;                                        \
+    sfnt_f26dot6 x, y, value;                  \
+    sfnt_f26dot6 org_x, org_y;                 \
+                                               \
+    p = POP ();                                        \
+                                               \
+    sfnt_address_zp2 (interpreter, p, &x, &y,  \
+                     &org_x, &org_y);          \
+                                               \
+    if (opcode == 0x47)                                \
+      value = DUAL_PROJECT (org_x, org_y);     \
+    else                                       \
+      value = PROJECT (x, y);                  \
+                                               \
+    PUSH (value);                              \
+  }
+
+#define SCFS()                                 \
+  {                                            \
+    uint32_t p;                                        \
+    sfnt_f26dot6 c;                            \
+                                               \
+    c = POP ();                                        \
+    p = POP ();                                        \
+                                               \
+    sfnt_interpret_scfs (interpreter, c, p);   \
+  }
+
+#define MD()                                   \
+  {                                            \
+    uint32_t p1, p2;                           \
+    sfnt_f26dot6 distance;                     \
+                                               \
+    p1 = POP ();                               \
+    p2 = POP ();                               \
+                                               \
+    distance                                   \
+      = sfnt_measure_distance (interpreter,    \
+                              p1, p2,          \
+                              opcode);         \
+    PUSH (distance);                           \
+  }
+
 
 
 #define NOT_IMPLEMENTED()                      \
@@ -6787,14 +6941,15 @@ sfnt_interpret_utp (struct sfnt_interpreter 
*interpreter,
   interpreter->glyph_zone->flags[p] &= ~SFNT_POINT_TOUCHED_X;
 }
 
-/* Save the specified unit VECTOR into INTERPRETER's graphics
-   state.  */
+/* Save the specified unit VECTOR into INTERPRETER's graphics state as
+   both the projection and the dual projection vectors.  */
 
 static void
 sfnt_save_projection_vector (struct sfnt_interpreter *interpreter,
                             struct sfnt_unit_vector *vector)
 {
   interpreter->state.projection_vector = *vector;
+  interpreter->state.dual_projection_vector = *vector;
 
   sfnt_validate_gs (&interpreter->state);
 }
@@ -7034,6 +7189,22 @@ sfnt_check_zp2 (struct sfnt_interpreter *interpreter, 
uint32_t point)
     TRAP ("point lies outside glyph zone (ZP2)");
 }
 
+/* Check that the specified POINT lies within the zone addressed by
+   INTERPRETER's ZP0 register.  Trap if it does not.  */
+
+static void
+sfnt_check_zp0 (struct sfnt_interpreter *interpreter, uint32_t point)
+{
+  if (!interpreter->state.zp0)
+    {
+      if (point >= interpreter->twilight_zone_size)
+       TRAP ("point lies outside twilight zone (ZP0)");
+    }
+  else if (!interpreter->glyph_zone
+          || point >= interpreter->glyph_zone->num_points)
+    TRAP ("point lies outside glyph zone (ZP0)");
+}
+
 /* 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.
@@ -7175,6 +7346,147 @@ sfnt_project_vector (struct sfnt_interpreter 
*interpreter,
   return interpreter->state.project (vx, vy, interpreter);
 }
 
+/* Project the vector VX, VY onto INTERPRETER's dual projection
+   vector.  Return the magnitude of the projection.  */
+
+static sfnt_f26dot6
+sfnt_dual_project_vector (struct sfnt_interpreter *interpreter,
+                         sfnt_f26dot6 vx, sfnt_f26dot6 vy)
+{
+  return interpreter->state.dual_project (vx, vy, interpreter);
+}
+
+/* Interpret an SCFS instruction.
+   Move P in ZP2 along the freedom vector until its projection is
+   equal to C.  */
+
+static void
+sfnt_interpret_scfs (struct sfnt_interpreter *interpreter,
+                    uint32_t p, sfnt_f26dot6 c)
+{
+  sfnt_f26dot6 x, y, distance;
+
+  sfnt_address_zp2 (interpreter, p, &x, &y, NULL, NULL);
+  distance = PROJECT (x, y);
+  sfnt_move_zp2 (interpreter, p, 1, sfnt_sub (c, distance));
+}
+
+/* Symmetrically round the 26.6 fixed point value X using the rounding
+   mode in INTERPRETER.  Return the result.  */
+
+static sfnt_f26dot6
+sfnt_round_symmetric (struct sfnt_interpreter *interpreter, sfnt_f26dot6 x)
+{
+  int sign;
+
+  sign = 1;
+
+  if (x < 0)
+    {
+      sign = -1;
+      x = -x;
+    }
+
+  return interpreter->state.round (x, interpreter) * sign;
+}
+
+/* Interpret an MIAP (``Move Indirect Absolute Point'') instruction
+   using INTERPRETER.
+
+   Move P in ZP0 along the freedom vector until its projection on the
+   projection vector is equal to CVT units in the projection vector.
+
+   Finally, set RP0 and RP1 to P.
+
+   If OPCODE is 0x3f, then in addition check the CVT value against the
+   control value cut-in, and round the magnitudes of the movement.  */
+
+static void
+sfnt_interpret_miap (struct sfnt_interpreter *interpreter,
+                    uint32_t cvt, uint32_t p, unsigned char opcode)
+{
+  sfnt_f26dot6 x, y, distance, value, delta;
+
+  sfnt_address_zp0 (interpreter, p, &x, &y, NULL, NULL);
+
+  /* Read the cvt value.  */
+
+  if (cvt >= interpreter->cvt_size)
+    TRAP ("out of bounds read to cvt");
+
+  value = interpreter->cvt[cvt];
+
+  /* Obtain the original distance.  */
+  distance = sfnt_project_vector (interpreter, x, y);
+
+  /* Round the distance and apply the cvt cut in if necessary.  */
+
+  if (opcode == 0x3f)
+    {
+      delta = sfnt_sub (value, distance);
+
+      if (delta < 0)
+       delta = -delta;
+
+      /* If delta is more than the cvt cut in (more aptly named ``cut
+        out''), use the original distance.  */
+
+      if (delta > interpreter->state.cvt_cut_in)
+       value = distance;
+
+      /* Round value.  */
+      value = sfnt_round_symmetric (interpreter, value);
+    }
+
+  /* Move the point by the distance.  */
+  sfnt_move_zp0 (interpreter, p, 1, sfnt_sub (value, distance));
+
+  /* Set reference points.  */
+  interpreter->state.rp0 = p;
+  interpreter->state.rp1 = p;
+}
+
+/* Perform a single iteration of sfnt_interpret_alignrp.  RP0X and
+   RP0Y should be the position of the reference point RP0 in ZP0.  */
+
+static void
+sfnt_interpret_alignrp_1 (struct sfnt_interpreter *interpreter,
+                         sfnt_f26dot6 rp0x, sfnt_f26dot6 rp0y)
+{
+  sfnt_f26dot6 distance, x, y;
+  uint32_t point;
+
+  point = POP ();
+
+  /* Load this point.  */
+  sfnt_address_zp1 (interpreter, point, &x, &y, NULL, NULL);
+
+  /* Measure the distance from here to rp0.  */
+  distance = sfnt_project_vector (interpreter, sfnt_sub (x, rp0x),
+                                 sfnt_sub (y, rp0y));
+
+  /* Move by the opposite.  */
+  sfnt_move_zp1 (interpreter, point, 1, -distance);
+}
+
+/* For loop times, pop a point in ZP1 and align it to RP0 in ZP0 by
+   moving it along the freedom vector until its projected distance
+   from RP0 becomes 0.  */
+
+static void
+sfnt_interpret_alignrp (struct sfnt_interpreter *interpreter)
+{
+  sfnt_f26dot6 rp0x, rp0y;
+
+  sfnt_address_zp0 (interpreter, interpreter->state.rp0,
+                   &rp0x, &rp0y, NULL, NULL);
+
+  while (interpreter->state.loop--)
+    sfnt_interpret_alignrp_1 (interpreter, rp0x, rp0y);
+
+  interpreter->state.loop = 1;
+}
+
 /* Align the two points P1 and P2 relative to the projection vector.
    P1 is addressed relative to ZP0, and P2 is addressed relative to
    ZP1.
@@ -7468,14 +7780,184 @@ sfnt_line_to_vector (struct sfnt_interpreter 
*interpreter,
   sfnt_normalize_vector (a, b, vector);
 }
 
+/* Measure the distance between P1 in ZP0 and P2 in ZP1,
+   relative to the projection or dual projection vector.
+
+   Return the distance of P1 and P2 relative to their original
+   un-instructed positions should OPCODE be 0x49, and to their
+   instructed positions should OPCODE be 0x4A.  */
+
+static sfnt_f26dot6
+sfnt_measure_distance (struct sfnt_interpreter *interpreter,
+                      uint32_t p1, uint32_t p2,
+                      unsigned char opcode)
+{
+  sfnt_f26dot6 p1x, p1y, p1_original_x, p1_original_y;
+  sfnt_f26dot6 p2x, p2y, p2_original_x, p2_original_y;
+
+  /* P1 is relative to ZP0 and P2 is relative to ZP1.
+     Apple's manual says this, Microsoft's does not.  */
+
+  sfnt_address_zp0 (interpreter, p1, &p1x, &p1y,
+                   &p1_original_x, &p1_original_y);
+  sfnt_address_zp1 (interpreter, p2, &p2x, &p2y,
+                   &p2_original_x, &p2_original_y);
+
+  if (opcode == 0x49)
+    {
+      /* When measuring in the glyph zone, measure the distance using
+        the dual projection vector, relative to the ``original
+        original outlines''.
+
+        This is not written down anywhere, leading you to believe
+         that the distance is measured using the scaled outline prior
+         to instructing.  */
+
+      if (interpreter->state.zp0 == 1
+         && interpreter->state.zp1 == 1)
+       return sfnt_div_fixed (DUAL_PROJECT (sfnt_sub (p1x, p2x),
+                                            sfnt_sub (p1y, p2y)),
+                              interpreter->scale);
+
+      return DUAL_PROJECT (sfnt_sub (p1x, p2x),
+                          sfnt_sub (p1y, p2y));
+    }
+
+  return PROJECT (sfnt_sub (p1x, p2x),
+                 sfnt_sub (p1y, p2y));
+}
+
+/* Interpret an MSIRP instruction in INTERPRETER.
+   Take a point P, and make the distance between P in ZP1 and the
+   current position of RP0 in ZP0 equal to D.
+
+   Then, if OPCODE is equal to 0x3b, make P RP0.  */
+
+static void
+sfnt_interpret_msirp (struct sfnt_interpreter *interpreter,
+                     uint32_t p, sfnt_f26dot6 d, unsigned char opcode)
+{
+  sfnt_f26dot6 rp0x, rp0y;
+  sfnt_f26dot6 x, y;
+  sfnt_f26dot6 old_distance;
+
+  sfnt_address_zp0 (interpreter, interpreter->state.rp0,
+                   &rp0x, &rp0y, NULL, NULL);
+  sfnt_address_zp1 (interpreter, p, &x, &y, NULL, NULL);
+
+  /* Compute the original distance.  */
+  old_distance = sfnt_project_vector (interpreter,
+                                     sfnt_sub (x, rp0x),
+                                     sfnt_sub (y, rp0y));
+
+  /* Move the point.  */
+  sfnt_move_zp1 (interpreter, p, 1, sfnt_sub (d, old_distance));
+
+  /* Nothing in the TrueType reference manual says directly that this
+     instruction should change rp1 and rp2.  However, it says this
+     instruction is ``very similar to the MIRP[] instruction
+     except...'', and FreeType seems to do this, so do it as well.  */
+
+  interpreter->state.rp1 = interpreter->state.rp0;
+  interpreter->state.rp2 = p;
+
+  if (opcode == 0x3b)
+    interpreter->state.rp0 = p;
+}
+
+/* Interpret an IP instruction in INTERPRETER.  For loop times, pop a
+   single point in ZP2, and interpolate it so that its original
+   relationship to the points RP1 in ZP0 and RP2 in ZP1 as measured
+   along the dual projection vector continues to hold true.  */
+
+static void
+sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
+{
+  sfnt_f26dot6 rp1x, rp1y, rp1_original_x, rp1_original_y;
+  sfnt_f26dot6 rp2x, rp2y, rp2_original_x, rp2_original_y;
+  sfnt_f26dot6 range, new_range, org_distance, cur_distance;
+  sfnt_f26dot6 new_distance;
+  uint32_t p;
+  sfnt_f26dot6 x, y, original_x, original_y;
+
+  /* First load both reference points.  */
+  sfnt_address_zp0 (interpreter, interpreter->state.rp1,
+                   &rp1x, &rp1y, &rp1_original_x,
+                   &rp1_original_y);
+  sfnt_address_zp1 (interpreter, interpreter->state.rp2,
+                   &rp2x, &rp2y, &rp2_original_x,
+                   &rp2_original_y);
+
+  /* Get the original distance between of RP1 and RP2 measured
+     relative to the dual projection vector.  */
+  range = sfnt_dual_project_vector (interpreter,
+                                   sfnt_sub (rp2_original_x,
+                                             rp2_original_y),
+                                   sfnt_sub (rp1_original_x,
+                                             rp1_original_y));
+
+  /* Get the new distance.  */
+  new_range = sfnt_dual_project_vector (interpreter,
+                                       sfnt_sub (rp2x, rp2y),
+                                       sfnt_sub (rp1x, rp1y));
+
+  while (interpreter->state.loop--)
+    {
+      p = POP ();
+
+      /* Load this point relative to zp2.  */
+      sfnt_address_zp2 (interpreter, p, &x, &y, &original_x,
+                       &original_y);
+
+      /* Now compute the old distance from this point to rp1.  */
+      org_distance
+       = sfnt_dual_project_vector (interpreter,
+                                   sfnt_sub (original_x,
+                                             rp1_original_x),
+                                   sfnt_sub (original_y,
+                                             rp1_original_y));
+
+      /* And the current distance from this point to rp1, so
+         how much to move can be determined.  */
+      cur_distance
+       = sfnt_dual_project_vector (interpreter,
+                                   sfnt_sub (x, rp1x),
+                                   sfnt_sub (y, rp1y));
+
+      /* Finally, apply the ratio of the new distance between RP1 and
+        RP2 to that of the old distance between the two reference
+        points to org_distance, making new_distance.
+
+         If both reference points occupy the same position on the dual
+         projection vector, then simply use the old distance.  */
+
+      if (org_distance)
+       {
+         if (range)
+           new_distance = sfnt_multiply_divide (org_distance, new_range,
+                                                range);
+         else
+           new_distance = org_distance;
+       }
+      else
+       new_distance = 0;
+
+      /* And move the point along the freedom vector to reflect the
+        change in distance.  */
+      sfnt_move_zp2 (interpreter, p, 1,
+                    sfnt_sub (new_distance, cur_distance));
+    }
+
+  interpreter->state.loop = 1;
+}
+
 /* Apply the delta specified by OPERAND to the control value table
    entry at INDEX currently loaded inside INTERPRETER.
 
    Trap if INDEX is out of bounds.
 
-   NUMBER is the number of the specific DELTAC instruction this
-   instruction is being applied on behalf of.  It must be between 1
-   and 3.  */
+   NUMBER is the number of the specific DELTAC instruction this delta
+   is being applied on behalf of.  It must be between 1 and 3.  */
 
 static void
 sfnt_deltac (int number, struct sfnt_interpreter *interpreter,
@@ -7612,17 +8094,19 @@ static void
 sfnt_interpret_mdap (struct sfnt_interpreter *interpreter,
                     uint32_t p, uint32_t opcode)
 {
-  sfnt_f26dot6 distance, px, py;
+  sfnt_f26dot6 here, distance, px, py;
 
   sfnt_address_zp0 (interpreter, p, &px, &py, NULL, NULL);
 
+  /* Measure the current distance.  */
+  here = sfnt_project_vector (interpreter, px, py);
+
   if (opcode == 0x7f)
     {
-      /* Measure distance, round, then move by distance.  */
+      /* Measure distance, round, then move to the distance.  */
       distance = sfnt_project_vector (interpreter, px, py);
-      distance = sfnt_sub (interpreter->state.round (distance,
-                                                    interpreter),
-                          distance);
+      distance = sfnt_round_symmetric (interpreter, distance);
+      distance = sfnt_sub (distance, here);
     }
   else
     /* Don't move.  Just touch the point.  */
@@ -7634,6 +8118,127 @@ sfnt_interpret_mdap (struct sfnt_interpreter 
*interpreter,
   interpreter->state.rp1 = p;
 }
 
+/* Apply the delta specified by OPERAND to the point P in ZP0
+   currently loaded inside INTERPRETER.
+
+   Trap if P is out of bounds.
+
+   NUMBER is the number of the specific DELTAP instruction this delta
+   is being applied on behalf of.  It must be between 1 and 3.  */
+
+static void
+sfnt_deltap (int number, struct sfnt_interpreter *interpreter,
+            unsigned char operand, unsigned int index)
+{
+  int ppem, delta;
+
+  /* Extract the ppem from OPERAND.  The format is the same as in
+     sfnt_deltac.  */
+
+  ppem = (operand >> 4) + interpreter->state.delta_base;
+
+  switch (number)
+    {
+    case 1:
+      break;
+
+    case 2:
+      ppem += 16;
+      break;
+
+    case 3:
+      ppem += 32;
+      break;
+    }
+
+  /* Don't apply the delta if the ppem size doesn't match.  */
+
+  if (interpreter->ppem != ppem)
+    return;
+
+  /* Now, determine the magnitude of the movement and find the
+     delta.  */
+
+  switch (operand & 0xf)
+    {
+    case 0:
+      delta = -8;
+      break;
+
+    case 1:
+      delta = -7;
+      break;
+
+    case 2:
+      delta = -6;
+      break;
+
+    case 3:
+      delta = -5;
+      break;
+
+    case 4:
+      delta = -4;
+      break;
+
+    case 5:
+      delta = -3;
+      break;
+
+    case 6:
+      delta = -2;
+      break;
+
+    case 7:
+      delta = -1;
+      break;
+
+    case 8:
+      delta = 1;
+      break;
+
+    case 9:
+      delta = 2;
+      break;
+
+    case 10:
+      delta = 3;
+      break;
+
+    case 11:
+      delta = 4;
+      break;
+
+    case 12:
+      delta = 5;
+      break;
+
+    case 13:
+      delta = 6;
+      break;
+
+    case 14:
+      delta = 7;
+      break;
+
+    case 15:
+      delta = 8;
+      break;
+
+      /* To pacify -fanalyzer.  */
+    default:
+      abort ();
+    }
+
+  /* Now, scale up the delta by the step size, which is determined by
+     the delta shift.  */
+  delta *= 1l << (6 - interpreter->state.delta_shift);
+
+  /* Move the point.  */
+  sfnt_check_zp0 (interpreter, index);
+  sfnt_move_zp0 (interpreter, index, 1, delta);
+}
+
 /* Needed by sfnt_interpret_call.  */
 static void sfnt_interpret_run (struct sfnt_interpreter *,
                                enum sfnt_interpreter_run_context);
@@ -8242,6 +8847,25 @@ sfnt_project_onto_any_vector (sfnt_f26dot6 vx, 
sfnt_f26dot6 vy,
                          interpreter->state.projection_vector.y);
 }
 
+/* Project the specified vector VX and VY onto the unit vector that is
+   INTERPRETER's dual projection vector, making only the assumption
+   that the dual projection vector is a valid unit vector.
+
+   The dual projection vector is a vector that is normally the
+   projection vector, but can be set using the original unscaled
+   coordinates of two points as well.
+
+   Value is the magnitude of the projected vector.  */
+
+static sfnt_f26dot6
+sfnt_dual_project_onto_any_vector (sfnt_f26dot6 vx, sfnt_f26dot6 vy,
+                                  struct sfnt_interpreter *interpreter)
+{
+  return sfnt_dot_fix_14 (vx, vy,
+                         interpreter->state.dual_projection_vector.x,
+                         interpreter->state.dual_projection_vector.y);
+}
+
 /* Move N points at *X, *Y by DISTANCE along INTERPRETER's freedom
    vector.  Set *FLAGS where appropriate and when non-NULL.
 
@@ -8390,6 +9014,15 @@ sfnt_validate_gs (struct sfnt_graphics_state *gs)
   else
     gs->project = sfnt_project_onto_any_vector;
 
+  /* Do the same for the dual projection vector.  */
+
+  if (gs->dual_projection_vector.x == 040000)
+    gs->dual_project = sfnt_project_onto_x_axis_vector;
+  else if (gs->dual_projection_vector.y == 040000)
+    gs->dual_project = sfnt_project_onto_y_axis_vector;
+  else
+    gs->dual_project = sfnt_dual_project_onto_any_vector;
+
   /* Compute dot product of the freedom and projection vectors.
      Handle the common case where the freedom vector is aligned
      to an axis.  */
@@ -8444,6 +9077,8 @@ sfnt_set_projection_vector (struct sfnt_interpreter 
*interpreter,
 {
   interpreter->state.projection_vector.x = x;
   interpreter->state.projection_vector.y = y;
+  interpreter->state.dual_projection_vector.x = x;
+  interpreter->state.dual_projection_vector.y = y;
 
   sfnt_validate_gs (&interpreter->state);
 }
@@ -8574,8 +9209,8 @@ sfnt_interpret_shp (struct sfnt_interpreter *interpreter,
     {
       point = POP ();
 
-      sfnt_move_zp2 (interpreter, point, 1, magnitude);
       sfnt_check_zp2 (interpreter, point);
+      sfnt_move_zp2 (interpreter, point, 1, magnitude);
     }
 
   /* Restore interpreter->state.loop to 1.  */
@@ -9041,16 +9676,16 @@ sfnt_interpret_run (struct sfnt_interpreter 
*interpreter,
          break;
 
        case 0x39:  /* IP    */
-         NOT_IMPLEMENTED ();
+         IP ();
          break;
 
        case 0x3A:  /* MSIRP */
        case 0x3B:  /* MSIRP */
-         NOT_IMPLEMENTED ();
+         MSIRP ();
          break;
 
-       case 0x3C:  /* AlignRP */
-         NOT_IMPLEMENTED ();
+       case 0x3C:  /* ALIGNRP */
+         ALIGNRP ();
          break;
 
        case 0x3D:  /* RTDG */
@@ -9059,7 +9694,7 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
 
        case 0x3E:  /* MIAP */
        case 0x3F:  /* MIAP */
-         NOT_IMPLEMENTED ();
+         MIAP ();
          break;
 
        case 0x40:  /* NPUSHB */
@@ -9088,16 +9723,16 @@ sfnt_interpret_run (struct sfnt_interpreter 
*interpreter,
 
        case 0x46:  /* GC */
        case 0x47:  /* GC */
-         NOT_IMPLEMENTED ();
+         GC ();
          break;
 
        case 0x48:  /* SCFS */
-         NOT_IMPLEMENTED ();
+         SCFS ();
          break;
 
        case 0x49:  /* MD */
        case 0x4A:  /* MD */
-         NOT_IMPLEMENTED ();
+         MD ();
          break;
 
        case 0x4B:  /* MPPEM */
@@ -9173,7 +9808,7 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
          break;
 
        case 0x5D:  /* DELTAP1 */
-         NOT_IMPLEMENTED ();
+         DELTAP1 ();
          break;
 
        case 0x5E:  /* SDB */
@@ -9235,8 +9870,11 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
          break;
 
        case 0x71:  /* DELTAP2 */
+         DELTAP2 ();
+         break;
+
        case 0x72:  /* DELTAP3 */
-         NOT_IMPLEMENTED ();
+         DELTAP3 ();
          break;
 
        case 0x73:  /* DELTAC1 */
@@ -10108,9 +10746,10 @@ static void
 sfnt_check_sloop (struct sfnt_interpreter *interpreter,
                  void *arg, bool trap)
 {
-  if (interpreter->state.loop != 2)
+  if (interpreter->state.loop != 1)
     {
-      fprintf (stderr, "failed, GS->loop should be 2, not %d\n",
+      /* The trap should've restored GS->loop to 1.  */
+      fprintf (stderr, "failed, GS->loop should be 1, not %d\n",
               interpreter->state.loop);
       return;
     }
@@ -12764,7 +13403,7 @@ main (int argc, char **argv)
   for (i = 0; i < table->num_subtables; ++i)
     {
       fprintf (stderr, "Found cmap table %"PRIu32": %p\n",
-              subtables[i].offset, data[i]);
+              subtables[i].offset, (void *) data[i]);
 
       if (data[i])
        fprintf (stderr, "  format: %"PRIu16"\n",



reply via email to

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