]> git.eshelyaron.com Git - emacs.git/commitdiff
Enable the new font scaler
authorPo Lu <luangruo@yahoo.com>
Mon, 18 Dec 2023 03:10:40 +0000 (11:10 +0800)
committerPo Lu <luangruo@yahoo.com>
Mon, 18 Dec 2023 03:10:40 +0000 (11:10 +0800)
* src/sfnt.c (sfnt_curve_is_flat): Tighten threshold for flat
curves.
(sfnt_insert_raster_step): Rewrite loop for clarity.
(sfnt_poly_set_steps): New function; fill small spans with a
plain unexceptional loop rather than memset.
(sfnt_poly_steps): Call that function.
(sfnt_verbose, main): Adjust tests such that the scaler can be
selected at runtime.

* src/sfnt.h: Update prototypes.

* src/sfntfont.c (sfntfont_get_glyph_raster)
(syms_of_sfntfont) <sfnt_raster_glyphs_exactly>: New variable.

src/sfnt.c
src/sfnt.h
src/sfntfont.c

index 208d0139022a498c4c761b614a1000a1944a44a5..7d43f06b748ea2b760252834596047777aa16597 100644 (file)
@@ -3905,11 +3905,11 @@ sfnt_curve_is_flat (struct sfnt_point control0,
   h.x = endpoint.x - control0.x;
   h.y = endpoint.y - control0.y;
 
-  /* 2.0 is a constant describing the area covered at which point the
-     curve is considered "flat".  */
+  /* 1.0 is a constant representing the area covered at which point
+     the curve is considered "flat".  */
   return (abs (sfnt_mul_fixed (g.x, h.y)
               - sfnt_mul_fixed (g.y, h.x))
-         <= 0400000);
+         <= 0200000);
 }
 
 /* Recursively split the splines in the bezier curve formed from
@@ -4621,8 +4621,6 @@ sfnt_raster_glyph_outline (struct sfnt_glyph_outline *outline)
 
 \f
 
-#ifdef SFNT_EXACT_SCALING
-
 /* Exact coverage scaler.
 
    The foregoing routines calculate partial coverage for each pixel by
@@ -4910,13 +4908,8 @@ sfnt_insert_raster_step (struct sfnt_step_raster *raster,
 
   p_next = &raster->steps[scanline];
 
-  while (true)
+  while ((step = *p_next))
     {
-      step = *p_next;
-
-      if (!step)
-       break;
-
       if (step->x > x)
        break;
 
@@ -4926,7 +4919,8 @@ sfnt_insert_raster_step (struct sfnt_step_raster *raster,
       p_next = &step->next;
     }
 
-  if (!raster->chunks || raster->chunks->nused == SFNT_BLOCK_STEPS)
+  if (!raster->chunks
+      || raster->chunks->nused == SFNT_BLOCK_STEPS)
     {
       /* All chunks have been consumed, and consequently a new chunk
         must be allocated.  */
@@ -4989,7 +4983,7 @@ sfnt_fedge_sort (struct sfnt_fedge *edges, size_t size)
    guarantee that no steps generated extend past WIDTH, steps starting
    after width might be omitted, and as such it must be accurate.  */
 
-static void
+TEST_STATIC void
 sfnt_poly_edges_exact (struct sfnt_fedge *edges, size_t nedges,
                       size_t height, size_t width,
                       sfnt_step_raster_proc proc, void *dcontext)
@@ -5409,6 +5403,45 @@ sfnt_compute_fill (float value)
   return MIN (value * 255, 255);
 }
 
+/* Set N pixels at DATA to the value VALUE.  If N is large, call
+   memset; otherwise set this by hand.  */
+
+static void
+sfnt_poly_set_steps (unsigned char *data, int value, int n)
+{
+  unsigned char *p;
+
+  p = data;
+  switch (n)
+    {
+    case 7:
+      *p++ = value;
+      FALLTHROUGH;
+    case 6:
+      *p++ = value;
+      FALLTHROUGH;
+    case 5:
+      *p++ = value;
+      FALLTHROUGH;
+    case 4:
+      *p++ = value;
+      FALLTHROUGH;
+    case 3:
+      *p++ = value;
+      FALLTHROUGH;
+    case 2:
+      *p++ = value;
+      FALLTHROUGH;
+    case 1:
+      *p++ = value;
+      FALLTHROUGH;
+    case 0:
+      break;
+    default:
+      memset (data, value, n);
+    }
+}
+
 /* Transfer steps generated by sfnt_poly_edges_exact from STEPS to the
    provided raster RASTER.  */
 
@@ -5438,7 +5471,7 @@ sfnt_poly_steps (struct sfnt_step_raster *steps,
          xend = MIN (step->x, raster->width);
 
          if (fill)
-           memset (data + x, fill, xend - x);
+           sfnt_poly_set_steps (data + x, fill, xend - x);
 
          total += step->coverage;
          fill = sfnt_compute_fill (total);
@@ -5446,7 +5479,7 @@ sfnt_poly_steps (struct sfnt_step_raster *steps,
        }
 
       if (x < raster->width)
-       memset (data + x, fill, raster->width - x);
+        sfnt_poly_set_steps (data + x, fill, raster->width - x);
     }
 }
 
@@ -5499,8 +5532,6 @@ sfnt_raster_glyph_outline_exact (struct sfnt_glyph_outline *outline)
   return data;
 }
 
-#endif /* SFNT_EXACT_SCALING */
-
 \f
 
 /* Glyph metrics computation.  */
@@ -16464,10 +16495,6 @@ sfnt_read_post_table (int fd, struct sfnt_offset_subtable *subtable)
 
 #ifdef TEST
 
-#ifdef SFNT_EXACT_SCALING
-#define sfnt_raster_glyph_outline sfnt_raster_glyph_outline_exact
-#endif /* SFNT_EXACT_SCALING */
-
 struct sfnt_test_dcontext
 {
   /* Context for sfnt_test_get_glyph.  */
@@ -20124,6 +20151,11 @@ sfnt_identify_instruction (struct sfnt_interpreter *interpreter)
   return buffer;
 }
 
+/* Function called to rasterize a glyph outline.  */
+#define TYPE struct sfnt_glyph_outline *
+static struct sfnt_raster *(*test_raster_glyph_outline) (TYPE);
+#undef TYPE
+
 static void
 sfnt_verbose (struct sfnt_interpreter *interpreter)
 {
@@ -20157,7 +20189,7 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
              sfnt_coerce_fixed (outline->xmax),
              sfnt_coerce_fixed (outline->ymax));
 
-      raster = sfnt_raster_glyph_outline (outline);
+      raster = (*test_raster_glyph_outline) (outline);
 
       if (raster)
        sfnt_test_raster (raster, NULL, 0);
@@ -20380,6 +20412,11 @@ main (int argc, char **argv)
       exit (0);
     }
 
+  if (getenv ("SFNT_EXACT_SCALING"))
+    test_raster_glyph_outline = sfnt_raster_glyph_outline_exact;
+  else
+    test_raster_glyph_outline = sfnt_raster_glyph_outline;
+
   fd = open (argv[1], O_RDONLY);
 
   if (fd < 0)
@@ -20471,8 +20508,8 @@ main (int argc, char **argv)
       return 1;
     }
 
-#define FANCY_PPEM 12
-#define EASY_PPEM  12
+#define FANCY_PPEM 30
+#define EASY_PPEM  30
 
   interpreter = NULL;
   head = sfnt_read_head_table (fd, font);
@@ -20723,7 +20760,7 @@ main (int argc, char **argv)
 
          xfree (value);
 
-         raster = sfnt_raster_glyph_outline (outline);
+         raster = (*test_raster_glyph_outline) (outline);
 
          if (!raster)
            exit (7);
@@ -21028,10 +21065,10 @@ main (int argc, char **argv)
 
                  clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start);
 
-                 for (i = 0; i < 120; ++i)
+                 for (i = 0; i < 800; ++i)
                    {
                      xfree (raster);
-                     raster = sfnt_raster_glyph_outline (outline);
+                     raster = (*test_raster_glyph_outline) (outline);
                    }
 
                  clock_gettime (CLOCK_THREAD_CPUTIME_ID, &end);
@@ -21116,7 +21153,8 @@ main (int argc, char **argv)
 
                              if (outline)
                                {
-                                 raster = sfnt_raster_glyph_outline (outline);
+                                 raster
+                                   = (*test_raster_glyph_outline) (outline);
 
                                  if (raster)
                                    {
@@ -21142,7 +21180,7 @@ main (int argc, char **argv)
              printf ("time spent building edges: %lld sec %ld nsec\n",
                      (long long) sub1.tv_sec, sub1.tv_nsec);
              printf ("time spent rasterizing: %lld sec %ld nsec\n",
-                     (long long) sub2.tv_sec / 120, sub2.tv_nsec / 120);
+                     (long long) sub2.tv_sec / 800, sub2.tv_nsec / 800);
 
              xfree (outline);
            }
index a875c1a722d5051b19a90cb4fde27217e324c3cc..2ae47ad30cea72cb7c0a071bea818d08604196fc 100644 (file)
@@ -1512,6 +1512,7 @@ extern void sfnt_prepare_raster (struct sfnt_raster *,
 
 #define PROTOTYPE struct sfnt_glyph_outline *
 extern struct sfnt_raster *sfnt_raster_glyph_outline (PROTOTYPE);
+extern struct sfnt_raster *sfnt_raster_glyph_outline_exact (PROTOTYPE);
 #undef PROTOTYPE
 
 #define PROTOTYPE                      \
index f002712dc10a7cba8e8dd067af29d904a9b3c9d3..0a8797bfb3b41fbbc995a08b52d0a406005a2619 100644 (file)
@@ -2444,7 +2444,11 @@ sfntfont_get_glyph_raster (sfnt_glyph glyph_code,
     }
 
   /* Not already cached.  Raster the outline.  */
-  raster = sfnt_raster_glyph_outline (outline);
+
+  if (!sfnt_raster_glyphs_exactly)
+    raster = sfnt_raster_glyph_outline (outline);
+  else
+    raster = sfnt_raster_glyph_outline_exact (outline);
 
   if (!raster)
     return NULL;
@@ -4116,6 +4120,13 @@ eliminating artifacts and chance effects consequent upon the direct
 upscaling of glyph outline data.  Instruction code is occasionally
 incompatible with Emacs and must be disregarded.  */);
   Vsfnt_uninstructable_family_regexp = Qnil;
+
+  DEFVAR_BOOL ("sfnt-raster-glyphs-exactly", sfnt_raster_glyphs_exactly,
+    doc: /* How font glyph outlines should be converted to graphics.
+If non-nil, glyphs will be displayed in a more precise manner, at the
+cost of performance on devices where floating-point math operations
+are slow.  */);
+  sfnt_raster_glyphs_exactly = true;
 }
 
 void