Improve text display on Android port

* src/sfnt.c (sfnt_build_glyph_outline): Clear
build_outline_context.
(sfnt_poly_coverage): Extend coverage map.
(sfnt_prepare_raster): Always floor coordinates, since the
increase in coverage makes this hack unnecessary.
(sfnt_build_outline_edges): Likewise.
(sfnt_compare_edges): Remove function.
(sfnt_edge_sort): New function.  Since edges are already
partially sorted, and there are not many, insertion sort
suffices.
(sfnt_poly_edges): Use sfnt_edge_sort.
(sfnt_fill_span): Stop rounding x0 and x1 to the grid, and make
coverage computation static.
(sfnt_lookup_glyph_metrics): Fix return code for unscaled
metrics.
(sfnt_scale_metrics): New function.
(SFNT_ENABLE_HINTING): Remove define.
(struct sfnt_cvt_table, struct sfnt_fpgm_table)
(struct sfnt_prep_table): Move to sfnt.h.
(sfnt_read_cvt_table):
(sfnt_read_fpgm_table, sfnt_read_prep_table): Make TEST_STATIC.
(struct sfnt_unit_vector, struct sfnt_interpreter_definition)
(struct sfnt_interpreter_zone, struct sfnt_graphics_state):
(struct sfnt_interpreter): Move to sfnt.h.
(sfnt_make_interpreter): Make TEST_STATIC.
(POP, PUSH, DELTAP1, DELTAP2, DELTAP3): When TEST, define to
regular push and pop.
(sfnt_deltac):
(sfnt_deltap): Fix order of arguments.
(IUP_SINGLE_PAIR): Fix interpolation loop wraparound.
(sfnt_interpret_font_program):
(sfnt_interpret_control_value_program): Make TEST_STATIC.
(struct sfnt_instructed_outline): Move to sfnt.h.
(sfnt_build_instructed_outline): Make TEST_STATIC.
(sfnt_interpret_simple_glyph):
(sfnt_x_raster):
(sfnt_test_raster):
(all_tests):
(sfnt_verbose):
(main): Improve test code.

* src/sfnt.h (SFNT_ENABLE_HINTING, struct sfnt_cvt_table)
(struct sfnt_fpgm_table, struct sfnt_prep_table)
(struct sfnt_unit_vector, struct sfnt_interpreter_definition)
(struct sfnt_interpreter_zone, struct sfnt_graphics_state)
(struct sfnt_interpreter, struct sfnt_instructed_outline)
(PROTOTYPE): New definitions.
* src/sfntfont-android.c (sfntfont_android_put_glyphs): Make
coordinate generation more straightforward.
* src/sfntfont.c (sfntfont_get_glyph_outline): New arguments
INTERPRETER and METRICS.
(struct sfnt_font_info): New tables.
(sfntfont_setup_interpreter): New function.
(sfntfont_open): Avoid memory leak.  Set up interpreter.
(sfntfont_measure_instructed_pcm): New function.
(sfntfont_measure_pcm): Delegate to measure_instructed_pcm where
appropriate.
(sfntfont_close): Free new tables.
(sfntfont_draw): Scale metrics properly.
This commit is contained in:
Po Lu 2023-02-08 16:34:29 +08:00
parent bd55cca4b8
commit 1a70941c8e
4 changed files with 1076 additions and 558 deletions

File diff suppressed because it is too large Load diff

View file

@ -23,6 +23,11 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <stdint.h>
#include <stddef.h>
#include <setjmp.h>
#if defined emacs || defined TEST
#define SFNT_ENABLE_HINTING
#endif
@ -719,7 +724,7 @@ struct sfnt_edge
enum
{
SFNT_POLY_SHIFT = 2,
SFNT_POLY_SHIFT = 3,
SFNT_POLY_SAMPLE = (1 << SFNT_POLY_SHIFT),
SFNT_POLY_MASK = (SFNT_POLY_SAMPLE - 1),
SFNT_POLY_STEP = (0x10000 >> SFNT_POLY_SHIFT),
@ -984,6 +989,9 @@ extern int sfnt_lookup_glyph_metrics (sfnt_glyph, int,
struct sfnt_head_table *,
struct sfnt_maxp_table *);
extern void sfnt_scale_metrics (struct sfnt_glyph_metrics *,
sfnt_fixed);
#define PROTOTYPE int, struct sfnt_offset_subtable *
extern struct sfnt_name_table *sfnt_read_name_table (PROTOTYPE);
#undef PROTOTYPE
@ -1003,4 +1011,477 @@ extern char *sfnt_find_metadata (struct sfnt_meta_table *,
extern struct sfnt_ttc_header *sfnt_read_ttc_header (int);
#endif /* TEST */
/* TrueType hinting support. */
#ifdef SFNT_ENABLE_HINTING
/* Structure definitions for tables used by the TrueType
interpreter. */
struct sfnt_cvt_table
{
/* Number of elements in the control value table. */
size_t num_elements;
/* Pointer to elements in the control value table. */
sfnt_fword *values;
};
struct sfnt_fpgm_table
{
/* Number of instructions in the font program table. */
size_t num_instructions;
/* Pointer to elements in the font program table. */
unsigned char *instructions;
};
struct sfnt_prep_table
{
/* Number of instructions in the control value program (pre-program)
table. */
size_t num_instructions;
/* Pointer to elements in the preprogram table. */
unsigned char *instructions;
};
/* Fixed point types used by the TrueType interpreter. */
/* 26.6 fixed point type used within the interpreter. */
typedef int32_t sfnt_f26dot6;
/* 2.14 fixed point type used to represent versors of unit
vectors. */
typedef int16_t sfnt_f2dot14;
/* 18.14 fixed point type used to calculate rounding details. */
typedef int32_t sfnt_f18dot14;
/* Interpreter execution environment. */
struct sfnt_unit_vector
{
/* X and Y versors of the 2d unit vector. */
sfnt_f2dot14 x, y;
};
struct sfnt_interpreter_definition
{
/* The opcode of this instruction or function. */
uint16_t opcode;
/* The number of instructions. */
uint16_t instruction_count;
/* Pointer to instructions belonging to the definition. This
pointer points directly into the control value or font program.
Make sure both programs are kept around as long as the
interpreter continues to exist. */
unsigned char *instructions;
};
/* This structure represents a ``struct sfnt_glyph'' that has been
scaled to a given pixel size.
It can either contain a simple glyph, or a decomposed compound
glyph; instructions are interpreted for both simple glyphs, simple
glyph components inside a compound glyph, and compound glyphs as a
whole.
In addition to the glyph data itself, it also records various
information for the instruction interpretation process:
- ``current'' point coordinates, which have been modified
by the instructing process.
- two phantom points at the origin and the advance of the
glyph. */
struct sfnt_interpreter_zone
{
/* The number of points in this zone, including the two phantom
points at the end. */
size_t num_points;
/* The number of contours in this zone. */
size_t num_contours;
/* The end points of each contour. */
size_t *contour_end_points;
/* Pointer to the X axis point data. */
sfnt_f26dot6 *restrict x_points;
/* Pointer to the X axis current point data. */
sfnt_f26dot6 *restrict x_current;
/* Pointer to the Y axis point data. */
sfnt_f26dot6 *restrict y_points;
/* Pointer to the Y axis current point data. */
sfnt_f26dot6 *restrict y_current;
/* Pointer to the flags associated with this data. */
unsigned char *flags;
};
enum
{
/* Bits 7 and 6 of a glyph point's flags is reserved. This scaler
uses it to mean that the point has been touched in one axis or
another. */
SFNT_POINT_TOUCHED_X = (1 << 7),
SFNT_POINT_TOUCHED_Y = (1 << 6),
SFNT_POINT_TOUCHED_BOTH = (SFNT_POINT_TOUCHED_X
| SFNT_POINT_TOUCHED_Y),
};
/* This is needed because `round' below needs an interpreter
argument. */
struct sfnt_interpreter;
struct sfnt_graphics_state
{
/* Pointer to the function used for rounding. This function is
asymmetric, so -0.5 rounds up to 0, not -1. It is up to the
caller to handle negative values.
Value is undefined unless sfnt_validate_gs has been called, and
the second argument may be used to provide detailed rounding
information (``super rounding state''.) */
sfnt_f26dot6 (*round) (sfnt_f26dot6, struct sfnt_interpreter *);
/* Pointer to the function used to project euclidean vectors onto
the projection vector. Value is the magnitude of the projected
vector. */
sfnt_f26dot6 (*project) (sfnt_f26dot6, sfnt_f26dot6,
struct sfnt_interpreter *);
/* Pointer to the function used to project euclidean vectors onto
the dual projection vector. Value is the magnitude of the
projected vector. */
sfnt_f26dot6 (*dual_project) (sfnt_f26dot6, sfnt_f26dot6,
struct sfnt_interpreter *);
/* Pointer to the function used to move specified points
along the freedom vector by a distance specified in terms
of the projection vector. */
void (*move) (sfnt_f26dot6 *restrict,
sfnt_f26dot6 *restrict, size_t,
struct sfnt_interpreter *,
sfnt_f26dot6, unsigned char *);
/* Dot product between the freedom and the projection vectors. */
sfnt_f2dot14 vector_dot_product;
/* Controls whether the sign of control value table entries will be
changed to match the sign of the actual distance measurement with
which it is compared. Setting auto flip to TRUE makes it
possible to control distances measured with or against the
projection vector with a single control value table entry. When
auto flip is set to FALSE, distances must be measured with the
projection vector. */
bool auto_flip;
/* Limits the regularizing effects of control value table entries to
cases where the difference between the table value and the
measurement taken from the original outline is sufficiently
small. */
sfnt_f26dot6 cvt_cut_in;
/* Establishes the base value used to calculate the range of point
sizes to which a given DELTAC[] or DELTAP[] instruction will
apply. The formulas given below are used to calculate the range
of the various DELTA instructions.
DELTAC1 DELTAP1 (delta_base) through (delta_base + 15)
DELTAC2 DELTAP2 (delta_base + 16) through (delta_base + 31)
DELTAC3 DELTAP3 (delta_base + 32) through (delta_base + 47)
Please keep this documentation in sync with the TrueType
reference manual. */
unsigned short delta_base;
/* Determines the range of movement and smallest magnitude of
movement (the step) in a DELTAC[] or DELTAP[] instruction.
Changing the value of the delta shift makes it possible to trade
off fine control of point movement for range of movement. A low
delta shift favors range of movement over fine control. A high
delta shift favors fine control over range of movement. The step
has the value 1/2 to the power delta shift. The range of
movement is calculated by taking the number of steps allowed (16)
and multiplying it by the step.
The legal range for delta shift is zero through six. Negative
values are illegal. */
unsigned short delta_shift;
/* A second projection vector set to a line defined by the original
outline location of two points. The dual projection vector is
used when it is necessary to measure distances from the scaled
outline before any instructions were executed. */
struct sfnt_unit_vector dual_projection_vector;
/* A unit vector that establishes an axis along which points can
move. */
struct sfnt_unit_vector freedom_vector;
/* Makes it possible to turn off instructions under some
circumstances. When flag 1 is set, changes to the graphics state
made in the control value program will be ignored. When flag is
1, grid fitting instructions will be ignored. */
unsigned char instruct_control;
/* Makes it possible to repeat certain instructions a designated
number of times. The default value of one assures that unless
the value of loop is altered, these instructions will execute one
time. */
unsigned short loop;
/* Establishes the smallest possible value to which a distance will
be rounded. */
sfnt_f26dot6 minimum_distance;
/* A unit vector whose direction establishes an axis along which
distances are measured. */
struct sfnt_unit_vector projection_vector;
/* Determines the manner in which values are rounded. Can be set to
a number of predefined states or to a customized state with the
SROUND or S45ROUND instructions. */
int round_state;
/* Reference points. These reference point numbers, which together
with a zone designation, specify a point in either the glyph zone
or the twilight zone. */
uint16_t rp0, rp1, rp2;
/* Flags which determine whether the interpreter will activate
dropout control for the current glyph. */
int scan_control;
/* The distance difference below which the interpreter will replace
a CVT distance or an actual distance in favor of the single width
value. */
sfnt_f26dot6 sw_cut_in;
/* The value used in place of the control value table distance or
the actual distance value when the difference between that
distance and the single width value is less than the single width
cut-in. */
sfnt_f26dot6 single_width_value;
/* Zone pointers, which reference a zone. */
int zp0, zp1, zp2;
};
struct sfnt_interpreter
{
/* The number of elements in the stack. */
uint16_t max_stack_elements;
/* The number of instructions in INSTRUCTIONS. */
uint16_t num_instructions;
/* Size of the storage area. */
uint16_t storage_size;
/* Size of the function definition area. */
uint16_t function_defs_size;
/* Size of the instruction definition area. */
uint16_t instruction_defs_size;
/* Size of the twilight zone. */
uint16_t twilight_zone_size;
/* The instruction pointer. This points to the instruction
currently being executed. */
int IP;
/* The current scale. */
sfnt_fixed scale;
/* The current ppem and point size. */
int ppem, point_size;
/* The execution stack. This has at most max_stack_elements
elements. */
uint32_t *stack;
/* Pointer past the top of the stack. */
uint32_t *SP;
/* The size of the control value table. */
size_t cvt_size;
/* Pointer to instructions currently being executed. */
unsigned char *restrict instructions;
/* The twilight zone. May not be NULL. */
sfnt_f26dot6 *restrict twilight_x, *restrict twilight_y;
/* The original X positions of points in the twilight zone. */
sfnt_f26dot6 *restrict twilight_original_x;
/* The original Y positions of points in the twilight zone.
Apple does not directly say whether or not points in the twilight
zone can have their original positions changed. But this is
implied by ``create points in the twilight zone''. */
sfnt_f26dot6 *restrict twilight_original_y;
/* The scaled outlines being manipulated. May be NULL. */
struct sfnt_interpreter_zone *glyph_zone;
/* The glyph advance width. Value is undefined unless GLYPH_ZONE is
set. */
sfnt_f26dot6 advance_width;
/* The storage area. */
uint32_t *storage;
/* Control value table values. */
sfnt_f26dot6 *cvt;
/* Function definitions. */
struct sfnt_interpreter_definition *function_defs;
/* Instruction definitions. */
struct sfnt_interpreter_definition *instruction_defs;
/* Interpreter registers. */
struct sfnt_graphics_state state;
/* Detailed rounding state used when state.round_state indicates
that fine grained rounding should be used.
PERIOD says how often a round value occurs, for numbers
increasing from PHASE to infinity.
THRESHOLD says when to round a value between two increasing
periods towards the larger period. */
sfnt_f26dot6 period, phase, threshold;
/* The depth of any ongoing calls. */
int call_depth;
/* Jump buffer for traps. */
jmp_buf trap;
/* What was the trap. */
const char *trap_reason;
#ifdef TEST
/* If non-NULL, function called before each instruction is
executed. */
void (*run_hook) (struct sfnt_interpreter *);
/* If non-NULL, function called before each stack element is
pushed. */
void (*push_hook) (struct sfnt_interpreter *, uint32_t);
/* If non-NULL, function called before each stack element is
popped. */
void (*pop_hook) (struct sfnt_interpreter *, uint32_t);
#endif
};
/* Glyph hinting. */
/* Structure describing a single scaled and fitted outline. */
struct sfnt_instructed_outline
{
/* The number of points in this contour, including the two phantom
points at the end. */
size_t num_points;
/* The number of contours in this outline. */
size_t num_contours;
/* The end points of each contour. */
size_t *contour_end_points;
/* The points of each contour, with two additional phantom points at
the end. */
sfnt_f26dot6 *restrict x_points, *restrict y_points;
/* The flags of each point. */
unsigned char *flags;
};
/* Functions used to read tables used by the TrueType interpreter. */
#ifndef TEST
#define PROTOTYPE int, struct sfnt_offset_subtable *
extern struct sfnt_cvt_table *sfnt_read_cvt_table (PROTOTYPE);
extern struct sfnt_fpgm_table *sfnt_read_fpgm_table (PROTOTYPE);
extern struct sfnt_prep_table *sfnt_read_prep_table (PROTOTYPE);
#undef PROTOTYPE
#define PROTOTYPE \
struct sfnt_maxp_table *, \
struct sfnt_cvt_table *, \
struct sfnt_head_table *, \
int, int
extern struct sfnt_interpreter *sfnt_make_interpreter (PROTOTYPE);
#undef PROTOTYPE
#define PROTOTYPE \
struct sfnt_interpreter *, \
struct sfnt_fpgm_table *
extern const char *sfnt_interpret_font_program (PROTOTYPE);
#undef PROTOTYPE
#define PROTOTYPE \
struct sfnt_interpreter *, \
struct sfnt_prep_table *, \
struct sfnt_graphics_state *
extern const char *sfnt_interpret_control_value_program (PROTOTYPE);
#undef PROTOTYPE
#define PROTOTYPE struct sfnt_instructed_outline *
extern struct sfnt_glyph_outline *sfnt_build_instructed_outline (PROTOTYPE);
#undef PROTOTYPE
#define PROTOTYPE \
struct sfnt_glyph *, \
struct sfnt_interpreter *, \
struct sfnt_glyph_metrics *, \
struct sfnt_instructed_outline **
extern const char *sfnt_interpret_simple_glyph (PROTOTYPE);
#undef PROTOTYPE
#endif /* TEST */
#endif /* SFNT_ENABLE_HINTING */
#endif /* _SFNT_H_ */

View file

@ -454,7 +454,7 @@ sfntfont_android_put_glyphs (struct glyph_string *s, int from,
{
text.x1 = x_coords[0] + rasters[0]->offx;
text.x2 = text.x1 + rasters[0]->width;
text.y1 = y - (rasters[0]->height + rasters[0]->offy);
text.y1 = y - rasters[0]->height - rasters[0]->offy;
text.y2 = y - rasters[0]->offy;
}
else
@ -469,7 +469,7 @@ sfntfont_android_put_glyphs (struct glyph_string *s, int from,
character.x1 = x_coords[i] + rasters[i]->offx;
character.x2 = character.x1 + rasters[i]->width;
character.y1 = y - (rasters[i]->height + rasters[i]->offy);
character.y1 = y - rasters[i]->height - rasters[i]->offy;
character.y2 = y - rasters[i]->offy;
sfntfont_android_union_boxes (text, character, &text);

View file

@ -1456,6 +1456,9 @@ sfntfont_dereference_outline (struct sfnt_glyph_outline *outline)
Use the offset information in the long or short loca tables
LOCA_LONG and LOCA_SHORT, whichever is set.
If INTERPRETER is non-NULL, then possibly use the unscaled glyph
metrics in METRICS when instructing the glyph.
Return the outline with an incremented reference count and enter
the generated outline into CACHE upon success, possibly discarding
any older outlines, or NULL on failure. */
@ -1467,12 +1470,16 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
struct sfnt_glyf_table *glyf,
struct sfnt_head_table *head,
struct sfnt_loca_table_short *loca_short,
struct sfnt_loca_table_long *loca_long)
struct sfnt_loca_table_long *loca_long,
struct sfnt_interpreter *interpreter,
struct sfnt_glyph_metrics *metrics)
{
struct sfnt_outline_cache *start;
struct sfnt_glyph_outline *outline;
struct sfnt_glyph *glyph;
struct sfntfont_get_glyph_outline_dcontext dcontext;
struct sfnt_instructed_outline *value;
const char *error;
start = cache->next;
@ -1504,14 +1511,32 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
if (!glyph)
return NULL;
/* Try to instruct the glyph if INTERPRETER is specified.
TODO: support compound glyphs. */
outline = NULL;
if (interpreter && glyph->simple)
{
error = sfnt_interpret_simple_glyph (glyph, interpreter,
metrics, &value);
if (!error)
{
outline = sfnt_build_instructed_outline (value);
xfree (value);
}
}
dcontext.loca_long = loca_long;
dcontext.loca_short = loca_short;
dcontext.glyf = glyf;
outline = sfnt_build_glyph_outline (glyph, head, pixel_size,
sfntfont_get_glyph,
sfntfont_free_glyph,
&dcontext);
if (!outline)
outline = sfnt_build_glyph_outline (glyph, head, pixel_size,
sfntfont_get_glyph,
sfntfont_free_glyph,
&dcontext);
xfree (glyph);
if (!outline)
@ -1709,6 +1734,9 @@ struct sfnt_font_info
struct sfnt_glyf_table *glyf;
struct sfnt_loca_table_short *loca_short;
struct sfnt_loca_table_long *loca_long;
struct sfnt_prep_table *prep;
struct sfnt_fpgm_table *fpgm;
struct sfnt_cvt_table *cvt;
/* The selected character map. */
struct sfnt_cmap_encoding_subtable_data *cmap_data;
@ -1727,6 +1755,13 @@ struct sfnt_font_info
/* Number of elements in the raster cache. */
int raster_cache_size;
/* Interpreter for grid fitting (if enabled). */
struct sfnt_interpreter *interpreter;
/* Graphics state after the execution of the font and control value
programs. */
struct sfnt_graphics_state state;
};
/* Look up the glyph corresponding to the character C in FONT. Return
@ -1813,6 +1848,106 @@ sfntfont_probe_widths (struct sfnt_font_info *font_info)
font_info->font.average_width = total_width / num_characters;
}
/* Initialize the instruction interpreter for INFO, whose file and
offset subtable should be respectively FD and SUBTABLE. Load the
font and preprogram for the pixel size in INFO and its
corresponding point size POINT_SIZE.
The font tables in INFO must already have been initialized.
Set INFO->interpreter, INFO->cvt, INFO->prep, INFO->fpgm and
INFO->state upon success, and leave those fields intact
otherwise. */
static void
sfntfont_setup_interpreter (int fd, struct sfnt_font_info *info,
struct sfnt_offset_subtable *subtable,
int point_size)
{
struct sfnt_cvt_table *cvt;
struct sfnt_fpgm_table *fpgm;
struct sfnt_prep_table *prep;
struct sfnt_interpreter *interpreter;
const char *error;
struct sfnt_graphics_state state;
/* Try to read the control value program, cvt, and font program
tables. */
cvt = sfnt_read_cvt_table (fd, subtable);
fpgm = sfnt_read_fpgm_table (fd, subtable);
prep = sfnt_read_prep_table (fd, subtable);
/* If both fpgm and prep are NULL, this font likely has no
instructions, so don't bother setting up the interpreter. */
if (!fpgm && !prep)
goto bail;
/* Now, create the interpreter using the limits in info->maxp and
info->head. CVT can be NULL. */
interpreter = sfnt_make_interpreter (info->maxp, cvt, info->head,
info->font.pixel_size,
point_size);
/* Bail if the interpreter couldn't be created. */
if (!interpreter)
goto bail;
if (fpgm)
{
/* Otherwise, evaluate the font and cvt programs.
FIXME: make sure infinite loops inside these programs
cannot lock up Emacs. */
error = sfnt_interpret_font_program (interpreter, fpgm);
if (error)
{
/* If an error occurs, log it to the *Messages* buffer. */
message_with_string ("While interpreting font program: %s",
build_string (error), true);
goto bail1;
}
/* Save the graphics state. */
state = interpreter->state;
}
if (prep)
{
/* This will overwrite state if the instruction control is set
appropriately. */
error = sfnt_interpret_control_value_program (interpreter, prep,
&state);
if (error)
{
/* If an error occurs, log it to the *Messages* buffer. */
message_with_string ("While interpreting preprogram: %s",
build_string (error), true);
goto bail1;
}
}
/* The interpreter has been properly set up. */
info->fpgm = fpgm;
info->prep = prep;
info->cvt = cvt;
info->state = state;
info->interpreter = interpreter;
return;
bail1:
xfree (interpreter);
bail:
xfree (cvt);
xfree (fpgm);
xfree (prep);
}
/* Open the font corresponding to the font-entity FONT_ENTITY. Return
nil upon failure, else the opened font-object. */
@ -1829,6 +1964,8 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
struct sfnt_cmap_encoding_subtable *subtables;
struct sfnt_cmap_encoding_subtable_data **data;
struct charset *charset;
int point_size;
Display_Info *dpyinfo;
if (XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) != 0)
pixel_size = XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX));
@ -1868,6 +2005,9 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
font_info->loca_short = NULL;
font_info->loca_long = NULL;
font_info->cmap_data = NULL;
font_info->prep = NULL;
font_info->fpgm = NULL;
font_info->cvt = NULL;
font_info->outline_cache.next = &font_info->outline_cache;
font_info->outline_cache.last = &font_info->outline_cache;
@ -1875,6 +2015,7 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
font_info->raster_cache.next = &font_info->raster_cache;
font_info->raster_cache.last = &font_info->raster_cache;
font_info->raster_cache_size = 0;
font_info->interpreter = NULL;
/* Open the font. */
fd = emacs_open (desc->path, O_RDONLY, 0);
@ -2027,9 +2168,20 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
/* Calculate the xfld name. */
font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
/* Now try to set up grid fitting for this font. */
dpyinfo = FRAME_DISPLAY_INFO (f);
point_size = PIXEL_TO_POINT (pixel_size, (dpyinfo->resx
* dpyinfo->resy
/ 2));
sfntfont_setup_interpreter (fd, font_info, subtable,
point_size);
/* Close the font file descriptor. */
emacs_close (fd);
/* Free the offset subtable. */
xfree (subtable);
/* All done. */
unblock_input ();
return font_object;
@ -2090,6 +2242,54 @@ sfntfont_encode_char (struct font *font, int c)
return glyph;
}
/* Measure the single glyph GLYPH in the font FONT and return its
metrics in *PCM.
Instruct the glyph if possible.
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)
{
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->outline_cache_size,
font->glyf, font->head,
font->loca_short,
font->loca_long,
font->interpreter, &metrics);
if (!outline)
return 1;
/* Scale the metrics by the interpreter's scale. */
sfnt_scale_metrics (&metrics, font->interpreter->scale);
/* How to round lbearing and rbearing? */
pcm->lbearing = metrics.lbearing >> 16;
pcm->rbearing = 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. */
@ -2100,6 +2300,10 @@ sfntfont_measure_pcm (struct sfnt_font_info *font, sfnt_glyph glyph,
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,
@ -2113,7 +2317,7 @@ sfntfont_measure_pcm (struct sfnt_font_info *font, sfnt_glyph glyph,
&font->outline_cache_size,
font->glyf, font->head,
font->loca_short,
font->loca_long);
font->loca_long, NULL, NULL);
if (!outline)
return 1;
@ -2192,6 +2396,10 @@ sfntfont_close (struct font *font)
xfree (info->loca_short);
xfree (info->loca_long);
xfree (info->cmap_data);
xfree (info->prep);
xfree (info->fpgm);
xfree (info->cvt);
xfree (info->interpreter);
sfntfont_free_outline_cache (&info->outline_cache);
sfntfont_free_raster_cache (&info->raster_cache);
@ -2221,10 +2429,15 @@ 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);
@ -2233,8 +2446,9 @@ 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. */
if (sfnt_lookup_glyph_metrics (s->char2b[i], font->pixel_size,
/* 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))
{
@ -2250,7 +2464,9 @@ sfntfont_draw (struct glyph_string *s, int from, int to,
&info->outline_cache_size,
info->glyf, info->head,
info->loca_short,
info->loca_long);
info->loca_long,
info->interpreter,
&metrics);
x_coords[i - from] = 0;
if (!outline)
@ -2259,6 +2475,10 @@ 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,