[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 9aea075f5fd: Respect glyph metrics modified by instruction code
From: |
Po Lu |
Subject: |
master 9aea075f5fd: Respect glyph metrics modified by instruction code |
Date: |
Fri, 22 Dec 2023 22:22:47 -0500 (EST) |
branch: master
commit 9aea075f5fd6e1d6b7f6d7fe35de8f3da752c3e7
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Respect glyph metrics modified by instruction code
* src/sfnt.c (sfnt_read_glyph): Clear advance and origin
distortion returning an empty glyph.
(sfnt_build_instructed_outline): New parameter *ADVANCE_WIDTH,
in which the glyph's advance width is saved.
(sfnt_interpret_compound_glyph_1): Refine commentary.
(sfnt_verbose, main): Adjust tests.
* src/sfnt.h: Update prototypes correspondingly.
* src/sfntfont.c (sfntfont_get_glyph_outline): If an instructed
outline is available, derive the advance and lbearing from the
measurements within.
(sfntfont_probe_widths): Call sfntfont_measure_pcm to establish
average widths.
(sfntfont_open): Do so after instruction code initialization
completes.
(sfntfont_measure_pcm): Revise commentary.
---
src/sfnt.c | 64 ++++++++++++++++++++++++++++---------
src/sfnt.h | 2 +-
src/sfntfont.c | 99 +++++++++++++++++++++++++++++++++++++---------------------
3 files changed, 114 insertions(+), 51 deletions(-)
diff --git a/src/sfnt.c b/src/sfnt.c
index 1397e341aa8..6698c9c27df 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -2421,6 +2421,8 @@ sfnt_read_glyph (sfnt_glyph glyph_code,
glyph.ymin = 0;
glyph.xmax = 0;
glyph.ymax = 0;
+ glyph.advance_distortion = 0;
+ glyph.origin_distortion = 0;
glyph.simple = xmalloc (sizeof *glyph.simple);
glyph.compound = NULL;
memset (glyph.simple, 0, sizeof *glyph.simple);
@@ -12202,15 +12204,18 @@ sfnt_decompose_instructed_outline (struct
sfnt_instructed_outline *outline,
/* Decompose and build an outline for the specified instructed outline
INSTRUCTED. Return the outline data with a refcount of 0 upon
- success, or NULL upon failure.
+ success, and the advance width of the instructed glyph in
+ *ADVANCE_WIDTH, or NULL upon failure.
This function is not reentrant. */
TEST_STATIC struct sfnt_glyph_outline *
-sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed)
+sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed,
+ sfnt_fixed *advance_width)
{
struct sfnt_glyph_outline *outline;
int rc;
+ sfnt_f26dot6 x1, x2;
memset (&build_outline_context, 0, sizeof build_outline_context);
@@ -12247,10 +12252,23 @@ sfnt_build_instructed_outline (struct
sfnt_instructed_outline *instructed)
instructed. */
if (instructed->num_points > 1)
- outline->origin
- = instructed->x_points[instructed->num_points - 2];
+ {
+ x1 = instructed->x_points[instructed->num_points - 2];
+ x2 = instructed->x_points[instructed->num_points - 1];
+
+ /* Convert the origin point to a 16.16 fixed point number. */
+ outline->origin = x1 * 1024;
+
+ /* Do the same for the advance width. */
+ *advance_width = (x2 - x1) * 1024;
+ }
else
- outline->origin = 0;
+ {
+ /* Phantom points are absent from this outline, which is
+ impossible. */
+ *advance_width = 0;
+ outline->origin = 0;
+ }
if (rc)
{
@@ -13133,8 +13151,8 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph
*glyph,
}
/* Run the program for the entire compound glyph, if any. CONTEXT
- should not contain phantom points by this point, so append its
- own. */
+ should not contain phantom points by this point, so append the
+ points for this glyph as a whole. */
/* Compute phantom points. */
sfnt_compute_phantom_points (glyph, metrics, interpreter->scale,
@@ -20216,6 +20234,7 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
unsigned char opcode;
const char *name;
static unsigned int instructions;
+ sfnt_fixed advance;
/* Build a temporary outline containing the values of the
interpreter's glyph zone. */
@@ -20229,7 +20248,7 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
temp.y_points = interpreter->glyph_zone->y_current;
temp.flags = interpreter->glyph_zone->flags;
- outline = sfnt_build_instructed_outline (&temp);
+ outline = sfnt_build_instructed_outline (&temp, &advance);
if (!outline)
return;
@@ -20444,6 +20463,7 @@ main (int argc, char **argv)
struct sfnt_instance *instance;
struct sfnt_blend blend;
struct sfnt_metrics_distortion distortion;
+ sfnt_fixed advance;
if (argc < 2)
return 1;
@@ -20559,8 +20579,8 @@ main (int argc, char **argv)
return 1;
}
-#define FANCY_PPEM 14
-#define EASY_PPEM 14
+#define FANCY_PPEM 12
+#define EASY_PPEM 12
interpreter = NULL;
head = sfnt_read_head_table (fd, font);
@@ -20787,6 +20807,8 @@ main (int argc, char **argv)
if (instance && gvar)
sfnt_vary_simple_glyph (&blend, code, glyph,
&distortion);
+ else
+ memset (&distortion, 0, sizeof distortion);
if (sfnt_lookup_glyph_metrics (code, -1,
&metrics,
@@ -20804,7 +20826,10 @@ main (int argc, char **argv)
exit (5);
}
- outline = sfnt_build_instructed_outline (value);
+ outline = sfnt_build_instructed_outline (value, &advance);
+ advances[i] = (advance / 65536);
+
+ fprintf (stderr, "advance: %d\n", advances[i]);
if (!outline)
exit (6);
@@ -20819,8 +20844,6 @@ main (int argc, char **argv)
xfree (outline);
rasters[i] = raster;
- advances[i] = (sfnt_mul_fixed (metrics.advance, scale)
- + sfnt_mul_fixed (distortion.advance, scale));
}
sfnt_x_raster (rasters, advances, length, hhea, scale);
@@ -21085,7 +21108,7 @@ main (int argc, char **argv)
fprintf (stderr, "outline origin, rbearing: %"
PRIi32" %"PRIi32"\n",
outline->origin,
- outline->ymax - outline->origin);
+ outline->xmax - outline->origin);
sfnt_test_max = outline->ymax - outline->ymin;
for (i = 0; i < outline->outline_used; i++)
@@ -21199,9 +21222,20 @@ main (int argc, char **argv)
printf ("rasterizing instructed outline\n");
if (outline)
xfree (outline);
- outline = sfnt_build_instructed_outline (value);
+ outline
+ = sfnt_build_instructed_outline (value,
+ &advance);
xfree (value);
+#define LB outline->xmin - outline->origin
+#define RB outline->xmax - outline->origin
+ printf ("instructed advance, lb, rb: %g %g %g\n",
+ sfnt_coerce_fixed (advance),
+ sfnt_coerce_fixed (LB),
+ sfnt_coerce_fixed (RB));
+#undef LB
+#undef RB
+
if (outline)
{
raster
diff --git a/src/sfnt.h b/src/sfnt.h
index 2ae47ad30ce..7baed372212 100644
--- a/src/sfnt.h
+++ b/src/sfnt.h
@@ -2102,7 +2102,7 @@ extern const char *sfnt_interpret_control_value_program
(PROTOTYPE);
#undef PROTOTYPE
-#define PROTOTYPE struct sfnt_instructed_outline *
+#define PROTOTYPE struct sfnt_instructed_outline *, sfnt_fixed *
extern struct sfnt_glyph_outline *sfnt_build_instructed_outline (PROTOTYPE);
diff --git a/src/sfntfont.c b/src/sfntfont.c
index cecdbeafb8d..078fe6083a6 100644
--- a/src/sfntfont.c
+++ b/src/sfntfont.c
@@ -2182,6 +2182,7 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
const char *error;
struct sfnt_glyph_metrics temp;
struct sfnt_metrics_distortion distortion;
+ sfnt_fixed advance;
start = cache->next;
distortion.advance = 0;
@@ -2284,23 +2285,52 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
if (!error)
{
- outline = sfnt_build_instructed_outline (value);
+ /* Now record the advance with that measured from the
+ phantom points within the instructed glyph outline, and
+ subsequently replace it once metrics are scaled. */
+
+ outline = sfnt_build_instructed_outline (value,
+ &advance);
xfree (value);
+
+ if (outline)
+ {
+ /* Save the new advance width. */
+ temp.advance = advance;
+
+ /* Finally, adjust the left side bearing of the glyph
+ metrics by the origin point of the outline, should a
+ transformation have been applied by either
+ instruction code or glyph variation. The left side
+ bearing is the distance from the origin point to the
+ left most point on the X axis. */
+ temp.lbearing = outline->xmin - outline->origin;
+ }
}
}
if (!outline)
- outline = sfnt_build_glyph_outline (glyph, scale,
- &temp,
- sfntfont_get_glyph,
- sfntfont_free_glyph,
- sfntfont_get_metrics,
- &dcontext);
-
- /* 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);
+ {
+ outline = sfnt_build_glyph_outline (glyph, scale,
+ &temp,
+ sfntfont_get_glyph,
+ sfntfont_free_glyph,
+ sfntfont_get_metrics,
+ &dcontext);
+
+ /* 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);
+
+ /* Finally, adjust the left side bearing of the glyph metrics by
+ the origin point of the outline, should a transformation have
+ been applied by either instruction code or glyph variation.
+ The left side bearing is the distance from the origin point
+ to the left most point on the X axis. */
+
+ if (index != -1)
+ temp.lbearing = outline->xmin - outline->origin;
+ }
fail:
@@ -2309,13 +2339,6 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
if (!outline)
return NULL;
- if (index != -1)
- /* Finally, adjust the left side bearing of the glyph metrics by
- the origin point of the outline, should a distortion have been
- applied. The left side bearing is the distance from the origin
- point to the left most point on the X axis. */
- temp.lbearing = outline->xmin - outline->origin;
-
start = xmalloc (sizeof *start);
start->glyph = glyph_code;
start->outline = outline;
@@ -2625,16 +2648,23 @@ sfntfont_lookup_glyph (struct sfnt_font_info
*font_info, int c)
return glyph;
}
+static int sfntfont_measure_pcm (struct sfnt_font_info *, sfnt_glyph,
+ struct font_metrics *);
+
/* Probe and set FONT_INFO->font.average_width,
FONT_INFO->font.space_width, and FONT_INFO->font.min_width
- according to the tables contained therein. */
+ according to the tables contained therein.
+
+ As this function generates outlines for all glyphs, outlines for
+ all ASCII characters will be entered into the outline cache as
+ well. */
static void
sfntfont_probe_widths (struct sfnt_font_info *font_info)
{
int i, num_characters, total_width;
sfnt_glyph glyph;
- struct sfnt_glyph_metrics metrics;
+ struct font_metrics pcm;
num_characters = 0;
total_width = 0;
@@ -2653,29 +2683,27 @@ sfntfont_probe_widths (struct sfnt_font_info *font_info)
if (!glyph)
continue;
- /* Now look up the metrics of this glyph. */
- if (sfnt_lookup_glyph_metrics (glyph, font_info->font.pixel_size,
- &metrics, font_info->hmtx,
- font_info->hhea, font_info->head,
- font_info->maxp))
+ /* Now look up the metrics of this glyph. Data from the metrics
+ table doesn't fit the bill, since variations and instruction
+ code is not applied to it. */
+ if (sfntfont_measure_pcm (font_info, glyph, &pcm))
continue;
/* Increase the number of characters. */
num_characters++;
/* Add the advance to total_width. */
- total_width += SFNT_CEIL_FIXED (metrics.advance) / 65536;
+ total_width += pcm.width;
/* Update min_width if it hasn't been set yet or is wider. */
if (font_info->font.min_width == 1
- || font_info->font.min_width > metrics.advance / 65536)
- font_info->font.min_width = metrics.advance / 65536;
+ || font_info->font.min_width > pcm.width)
+ font_info->font.min_width = pcm.width;
/* If i is the space character, set the space width. Make sure
to round this up. */
if (i == 32)
- font_info->font.space_width
- = SFNT_CEIL_FIXED (metrics.advance) / 65536;
+ font_info->font.space_width = pcm.width;
}
/* Now, if characters were found, set average_width. */
@@ -3263,9 +3291,6 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
- /* Find out the minimum, maximum and average widths. */
- sfntfont_probe_widths (font_info);
-
/* Clear various offsets. */
font_info->font.baseline_offset = 0;
font_info->font.relative_compose = 0;
@@ -3355,6 +3380,10 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
}
cancel_blend:
+
+ /* Find out the minimum, maximum and average widths. */
+ sfntfont_probe_widths (font_info);
+
/* Calculate the xfld name. */
font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil, Qt);
@@ -3468,7 +3497,7 @@ sfntfont_measure_pcm (struct sfnt_font_info *font,
sfnt_glyph glyph,
if (!outline)
return 1;
- /* Round the left side bearing downwards. */
+ /* Round the left side bearing down. */
pcm->lbearing = SFNT_FLOOR_FIXED (metrics.lbearing) / 65536;
pcm->rbearing = SFNT_CEIL_FIXED (outline->xmax) / 65536;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master 9aea075f5fd: Respect glyph metrics modified by instruction code,
Po Lu <=