Commit 9aea075f authored by Po Lu's avatar Po Lu
Browse files

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.
parent e84493ea
Pipeline #27592 failed with stages
in 46 minutes and 8 seconds
......@@ -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
......
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment