mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 12:31:25 +00:00
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.
This commit is contained in:
parent
67a325243c
commit
18b34e9ca0
3 changed files with 85 additions and 147 deletions
57
src/sfnt.c
57
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,
|
||||
|
||||
/* 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);
|
||||
PIXEL = UNIT / UPEM * PPEM
|
||||
|
||||
which means:
|
||||
|
||||
PIXEL = UNIT * PPEM / UPEM */
|
||||
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
169
src/sfntfont.c
169
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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue