emacs-diffs
[Top][All Lists]
Advanced

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

feature/android 18b34e9ca01 4/6: Refactor sfntfont.c


From: Po Lu
Subject: feature/android 18b34e9ca01 4/6: Refactor sfntfont.c
Date: Mon, 27 Mar 2023 04:45:37 -0400 (EDT)

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

    Refactor sfntfont.c
    
    * src/sfnt.c (sfnt_build_glyph_outline): Take scale, not head
    and pixel size.
    (sfnt_scale_metrics_to_pixel_size): Delete function.
    (sfnt_get_scale): New function.
    (main): Update tests.
    * src/sfnt.h (PROTOTYPE): Update prototypes.
    * src/sfntfont.c (struct sfnt_outline_cache)
    (sfntfont_get_glyph_outline, struct sfnt_font_info)
    (sfntfont_open): Save scale in font information and use it.
    (sfntfont_measure_instructed_pcm): Delete function.
    (sfntfont_measure_pcm): Make this the only ``measure pcm''
    function.
    (sfntfont_draw): Rely on sfntfont_get_glyph_outline for the
    scale.
---
 src/sfnt.c     |  57 ++++++++-----------
 src/sfnt.h     |   6 +-
 src/sfntfont.c | 169 ++++++++++++++++++++-------------------------------------
 3 files changed, 85 insertions(+), 147 deletions(-)

diff --git a/src/sfnt.c b/src/sfnt.c
index 8e7a30e3b05..9a1094a1ca9 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -3760,21 +3760,21 @@ sfnt_curve_to_and_build (struct sfnt_point control,
 }
 
 /* Non-reentrantly build the outline for the specified GLYPH at the
-   given pixel size.  Return the outline data with a refcount of 0
+   given scale factor.  Return the outline data with a refcount of 0
    upon success, or NULL upon failure.
 
+   SCALE is a scale factor that converts between em space and device
+   space.
+
    Use the scaled glyph METRICS to determine the origin point of the
    outline.
 
    Call GET_GLYPH and FREE_GLYPH with the specified DCONTEXT to obtain
-   glyphs for compound glyph subcomponents.
-
-   HEAD should be the `head' table of the font.  */
+   glyphs for compound glyph subcomponents.  */
 
 TEST_STATIC struct sfnt_glyph_outline *
 sfnt_build_glyph_outline (struct sfnt_glyph *glyph,
-                         struct sfnt_head_table *head,
-                         int pixel_size,
+                         sfnt_fixed scale,
                          struct sfnt_glyph_metrics *metrics,
                          sfnt_get_glyph_proc get_glyph,
                          sfnt_free_glyph_proc free_glyph,
@@ -3805,19 +3805,8 @@ sfnt_build_glyph_outline (struct sfnt_glyph *glyph,
   outline->xmax = 0;
   outline->ymax = 0;
 
-  /* Figure out how to convert from font unit-space to pixel space.
-     To turn one unit to its corresponding pixel size given a ppem of
-     1, the unit must be divided by head->units_per_em.  Then, it must
-     be multipled by the ppem.  So,
-
-       PIXEL = UNIT / UPEM * PPEM
-
-     which means:
-
-       PIXEL = UNIT * PPEM / UPEM  */
-
-  build_outline_context.factor
-    = sfnt_div_fixed (pixel_size, head->units_per_em);
+  /* Set the scale factor.  */
+  build_outline_context.factor = scale;
 
   /* Decompose the outline.  */
   rc = sfnt_decompose_glyph (glyph, sfnt_move_to_and_build,
@@ -4536,21 +4525,24 @@ sfnt_scale_metrics (struct sfnt_glyph_metrics *metrics,
     = sfnt_mul_fixed (metrics->advance * 65536, factor);
 }
 
-/* Like `sfnt_scale_metrics', except it scales the specified metrics
-   by a factor calculated using the given PPEM and HEAD table's UPEM
-   value.  */
+/* Calculate the factor used to convert em space to device space for a
+   font with the specified HEAD table and PPEM value.  */
 
-MAYBE_UNUSED TEST_STATIC void
-sfnt_scale_metrics_to_pixel_size (struct sfnt_glyph_metrics *metrics,
-                                 int ppem,
-                                 struct sfnt_head_table *head)
+MAYBE_UNUSED TEST_STATIC sfnt_fixed
+sfnt_get_scale (struct sfnt_head_table *head, int ppem)
 {
-  sfnt_fixed factor;
+  /* Figure out how to convert from font unit-space to pixel space.
+     To turn one unit to its corresponding pixel size given a ppem of
+     1, the unit must be divided by head->units_per_em.  Then, it must
+     be multipled by the ppem.  So,
+
+       PIXEL = UNIT / UPEM * PPEM
+
+     which means:
+
+       PIXEL = UNIT * PPEM / UPEM  */
 
-  /* Now calculate the factor scale lbearing and advance up to the
-     given PPEM size.  */
-  factor = sfnt_div_fixed (ppem, head->units_per_em);
-  sfnt_scale_metrics (metrics, factor);
+  return sfnt_div_fixed (ppem, head->units_per_em);
 }
 
 
@@ -19419,8 +19411,7 @@ main (int argc, char **argv)
 
              /* Time this important bit.  */
              clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start);
-             outline = sfnt_build_glyph_outline (glyph, head,
-                                                 EASY_PPEM,
+             outline = sfnt_build_glyph_outline (glyph, scale,
                                                  &metrics,
                                                  sfnt_test_get_glyph,
                                                  sfnt_test_free_glyph,
diff --git a/src/sfnt.h b/src/sfnt.h
index 84e51ff6766..fb8cb80bae9 100644
--- a/src/sfnt.h
+++ b/src/sfnt.h
@@ -1370,8 +1370,7 @@ extern void sfnt_free_glyph (struct sfnt_glyph *);
 
 #define PROTOTYPE              \
   struct sfnt_glyph *,         \
-  struct sfnt_head_table *,    \
-  int,                         \
+  sfnt_fixed,                  \
   struct sfnt_glyph_metrics *, \
   sfnt_get_glyph_proc,         \
   sfnt_free_glyph_proc,                \
@@ -1403,8 +1402,7 @@ extern int sfnt_lookup_glyph_metrics (sfnt_glyph, int,
 
 extern void sfnt_scale_metrics (struct sfnt_glyph_metrics *,
                                sfnt_fixed);
-extern void sfnt_scale_metrics_to_pixel_size (struct sfnt_glyph_metrics *,
-                                             int, struct sfnt_head_table *);
+extern sfnt_fixed sfnt_get_scale (struct sfnt_head_table *, int);
 
 #define PROTOTYPE int, struct sfnt_offset_subtable *
 extern struct sfnt_name_table *sfnt_read_name_table (PROTOTYPE);
diff --git a/src/sfntfont.c b/src/sfntfont.c
index 09aa89a9cdd..346e145082a 100644
--- a/src/sfntfont.c
+++ b/src/sfntfont.c
@@ -1648,7 +1648,10 @@ enum
 
 /* Caching subsystem.  Generating outlines from glyphs is expensive,
    and so is rasterizing them, so two caches are maintained for both
-   glyph outlines and rasters.  */
+   glyph outlines and rasters.
+
+   Computing metrics also requires some expensive processing if the
+   glyph has instructions or distortions.  */
 
 struct sfnt_outline_cache
 {
@@ -1658,6 +1661,9 @@ struct sfnt_outline_cache
   /* Pointer to outline.  */
   struct sfnt_glyph_outline *outline;
 
+  /* Reference to glyph metrics.  */
+  struct sfnt_glyph_metrics metrics;
+
   /* What glyph this caches.  */
   sfnt_glyph glyph;
 };
@@ -1724,20 +1730,21 @@ sfntfont_dereference_outline (struct sfnt_glyph_outline 
*outline)
 }
 
 /* Get the outline corresponding to the specified GLYPH_CODE in CACHE.
-   Use the pixel size PIXEL_SIZE, the glyf table GLYF, and the head
-   table HEAD.  Keep *CACHE_SIZE updated with the number of elements
-   in the cache.
+   Use the scale factor SCALE, the glyf table GLYF, and the head table
+   HEAD.  Keep *CACHE_SIZE updated with the number of elements in the
+   cache.
 
    Use the offset information in the long or short loca tables
    LOCA_LONG and LOCA_SHORT, whichever is set.
 
-   Use the specified HMTX, HHEA and MAXP tables when instructing
+   Use the specified HMTX, HEAD, HHEA and MAXP tables when instructing
    compound glyphs.
 
-   If INTERPRETER is non-NULL, then possibly use the unscaled glyph
-   metrics in METRICS and the interpreter STATE to instruct the glyph.
-   Otherwise, METRICS must contain scaled glyph metrics used to
-   compute the origin point of the outline.
+   If INTERPRETER is non-NULL, then possibly use it and the
+   interpreter graphics STATE to instruct the glyph.
+
+   If METRICS is non-NULL, return the scaled glyph metrics after
+   variation and instructing.
 
    Return the outline with an incremented reference count and enter
    the generated outline into CACHE upon success, possibly discarding
@@ -1746,7 +1753,7 @@ sfntfont_dereference_outline (struct sfnt_glyph_outline 
*outline)
 static struct sfnt_glyph_outline *
 sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
                            struct sfnt_outline_cache *cache,
-                           int pixel_size, int *cache_size,
+                           sfnt_fixed scale, int *cache_size,
                            struct sfnt_glyf_table *glyf,
                            struct sfnt_head_table *head,
                            struct sfnt_hmtx_table *hmtx,
@@ -1785,6 +1792,9 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
          start->last->next = start;
          start->outline->refcount++;
 
+         if (metrics)
+           *metrics = start->metrics;
+
          return start->outline;
        }
     }
@@ -1804,6 +1814,12 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
   dcontext.loca_short = loca_short;
   dcontext.glyf = glyf;
 
+  /* Now load the glyph's unscaled metrics into TEMP.  */
+
+  if (sfnt_lookup_glyph_metrics (glyph_code, -1, &temp, hmtx, hhea,
+                                head, maxp))
+    goto fail;
+
   if (interpreter)
     {
       if (glyph->simple)
@@ -1813,7 +1829,7 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
          interpreter->state = *state;
 
          error = sfnt_interpret_simple_glyph (glyph, interpreter,
-                                              metrics, &value);
+                                              &temp, &value);
        }
       else
        /* Restoring the interpreter state is done by
@@ -1824,7 +1840,7 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
                                               sfntfont_get_glyph,
                                               sfntfont_free_glyph,
                                               hmtx, hhea, maxp,
-                                              metrics, &dcontext,
+                                              &temp, &dcontext,
                                               &value);
 
       if (!error)
@@ -1834,32 +1850,29 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
        }
     }
 
+  /* At this point, the glyph metrics are unscaled.  Scale them up.
+     If INTERPRETER is set, use the scale placed within.  */
+
+  sfnt_scale_metrics (&temp, scale);
+
   if (!outline)
     {
-      /* If INTERPRETER is NULL, METRICS contains scaled metrics.  */
-
       if (!interpreter)
-       outline = sfnt_build_glyph_outline (glyph, head, pixel_size,
-                                           metrics,
+       outline = sfnt_build_glyph_outline (glyph, scale,
+                                           &temp,
                                            sfntfont_get_glyph,
                                            sfntfont_free_glyph,
                                            &dcontext);
       else
-       {
-         /* But otherwise, they are unscaled, and must be scaled
-            before being used.  */
-
-         temp = *metrics;
-         sfnt_scale_metrics_to_pixel_size (&temp, pixel_size,
-                                           head);
-         outline = sfnt_build_glyph_outline (glyph, head, pixel_size,
-                                             &temp,
-                                             sfntfont_get_glyph,
-                                             sfntfont_free_glyph,
-                                             &dcontext);
-       }
+       outline = sfnt_build_glyph_outline (glyph, scale,
+                                           &temp,
+                                           sfntfont_get_glyph,
+                                           sfntfont_free_glyph,
+                                           &dcontext);
     }
 
+ fail:
+
   xfree (glyph);
 
   if (!outline)
@@ -1868,6 +1881,7 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
   start = xmalloc (sizeof *start);
   start->glyph = glyph_code;
   start->outline = outline;
+  start->metrics = temp;
 
   /* One reference goes to the cache.  The second reference goes to
      the caller.  */
@@ -1898,7 +1912,11 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
       (*cache_size)--;
     }
 
-  /* Return the cached outline.  */
+  /* Return the cached outline and metrics.  */
+
+  if (metrics)
+    *metrics = temp;
+
   return outline;
 }
 
@@ -2104,6 +2122,9 @@ struct sfnt_font_info
      programs.  */
   struct sfnt_graphics_state state;
 
+  /* Factor used to convert from em space to pixel space.  */
+  sfnt_fixed scale;
+
 #ifdef HAVE_MMAP
   /* Whether or not the glyph table has been mmapped.  */
   bool glyf_table_mapped;
@@ -2647,6 +2668,7 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
   font_info->raster_cache.last = &font_info->raster_cache;
   font_info->raster_cache_size = 0;
   font_info->interpreter = NULL;
+  font_info->scale = 0;
 #ifdef HAVE_MMAP
   font_info->glyf_table_mapped = false;
 #endif /* HAVE_MMAP */
@@ -2682,6 +2704,9 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
   font_info->cmap_subtable = tables->cmap_subtable;
   font_info->uvs = tables->uvs;
 
+  /* Calculate the font's scaling factor.  */
+  font_info->scale = sfnt_get_scale (font_info->head, pixel_size);
+
   /* Fill in font data.  */
   font = &font_info->font;
   font->pixel_size = pixel_size;
@@ -2819,21 +2844,16 @@ sfntfont_encode_char (struct font *font, int c)
    Value is 0 upon success, 1 otherwise.  */
 
 static int
-sfntfont_measure_instructed_pcm (struct sfnt_font_info *font, sfnt_glyph glyph,
-                                struct font_metrics *pcm)
+sfntfont_measure_pcm (struct sfnt_font_info *font, sfnt_glyph glyph,
+                     struct font_metrics *pcm)
 {
   struct sfnt_glyph_metrics metrics;
   struct sfnt_glyph_outline *outline;
 
-  /* Ask for unscaled metrics.  */
-  if (sfnt_lookup_glyph_metrics (glyph, -1, &metrics, font->hmtx,
-                                font->hhea, font->head, font->maxp))
-    return 1;
-
   /* Now get the glyph outline, which is required to obtain the rsb,
      ascent and descent.  */
   outline = sfntfont_get_glyph_outline (glyph, &font->outline_cache,
-                                       font->font.pixel_size,
+                                       font->scale,
                                        &font->outline_cache_size,
                                        font->glyf, font->head,
                                        font->hmtx, font->hhea,
@@ -2846,57 +2866,6 @@ sfntfont_measure_instructed_pcm (struct sfnt_font_info 
*font, sfnt_glyph glyph,
   if (!outline)
     return 1;
 
-  /* Scale the metrics by the interpreter's scale.  */
-  sfnt_scale_metrics (&metrics, font->interpreter->scale);
-
-  pcm->lbearing = metrics.lbearing >> 16;
-  pcm->rbearing = SFNT_CEIL_FIXED (outline->xmax) >> 16;
-
-  /* Round the advance, ascent and descent upwards.  */
-  pcm->width = SFNT_CEIL_FIXED (metrics.advance) >> 16;
-  pcm->ascent = SFNT_CEIL_FIXED (outline->ymax) >> 16;
-  pcm->descent = SFNT_CEIL_FIXED (-outline->ymin) >> 16;
-
-  sfntfont_dereference_outline (outline);
-  return 0;
-}
-
-/* Measure the single glyph GLYPH in the font FONT and return its
-   metrics in *PCM.  Value is 0 upon success, 1 otherwise.  */
-
-static int
-sfntfont_measure_pcm (struct sfnt_font_info *font, sfnt_glyph glyph,
-                     struct font_metrics *pcm)
-{
-  struct sfnt_glyph_metrics metrics;
-  struct sfnt_glyph_outline *outline;
-
-  if (font->interpreter)
-    /* Use a function which instructs the glyph.  */
-    return sfntfont_measure_instructed_pcm (font, glyph, pcm);
-
-  /* Get the glyph metrics first.  */
-  if (sfnt_lookup_glyph_metrics (glyph, font->font.pixel_size,
-                                &metrics, font->hmtx, font->hhea,
-                                font->head, font->maxp))
-    return 1;
-
-  /* Now get the glyph outline, which is required to obtain the rsb,
-     ascent and descent.  */
-  outline = sfntfont_get_glyph_outline (glyph, &font->outline_cache,
-                                       font->font.pixel_size,
-                                       &font->outline_cache_size,
-                                       font->glyf, font->head,
-                                       font->hmtx, font->hhea,
-                                       font->maxp,
-                                       font->loca_short,
-                                       font->loca_long, NULL,
-                                       &metrics, NULL);
-
-  if (!outline)
-    return 1;
-
-  /* How to round lbearing and rbearing? */
   pcm->lbearing = metrics.lbearing >> 16;
   pcm->rbearing = SFNT_CEIL_FIXED (outline->xmax) >> 16;
 
@@ -3049,15 +3018,10 @@ sfntfont_draw (struct glyph_string *s, int from, int to,
   struct font *font;
   struct sfnt_font_info *info;
   struct sfnt_glyph_metrics metrics;
-  int pixel_size;
 
   length = to - from;
   font = s->font;
   info = (struct sfnt_font_info *) font;
-  pixel_size = font->pixel_size;
-
-  if (info->interpreter)
-    pixel_size = -1;
 
   rasters = alloca (length * sizeof *rasters);
   x_coords = alloca (length * sizeof *x_coords);
@@ -3066,21 +3030,10 @@ sfntfont_draw (struct glyph_string *s, int from, int to,
   /* Get rasters and outlines for them.  */
   for (i = from; i < to; ++i)
     {
-      /* Look up the metrics for this glyph.  The metrics are unscaled
-        if INFO->interpreter is set.  */
-      if (sfnt_lookup_glyph_metrics (s->char2b[i], pixel_size,
-                                    &metrics, info->hmtx, info->hhea,
-                                    info->head, info->maxp))
-       {
-         rasters[i - from] = NULL;
-         x_coords[i - from] = 0;
-         continue;
-       }
-
       /* Look up the outline.  */
       outline = sfntfont_get_glyph_outline (s->char2b[i],
                                            &info->outline_cache,
-                                           font->pixel_size,
+                                           info->scale,
                                            &info->outline_cache_size,
                                            info->glyf, info->head,
                                            info->hmtx, info->hhea,
@@ -3098,10 +3051,6 @@ sfntfont_draw (struct glyph_string *s, int from, int to,
          continue;
        }
 
-      /* Scale the metrics if info->interpreter is set.  */
-      if (info->interpreter)
-       sfnt_scale_metrics (&metrics, info->interpreter->scale);
-
       /* Rasterize the outline.  */
       rasters[i - from] = sfntfont_get_glyph_raster (s->char2b[i],
                                                     &info->raster_cache,



reply via email to

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