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:
parent
bd55cca4b8
commit
1a70941c8e
4 changed files with 1076 additions and 558 deletions
909
src/sfnt.c
909
src/sfnt.c
File diff suppressed because it is too large
Load diff
483
src/sfnt.h
483
src/sfnt.h
|
@ -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_ */
|
||||
|
|
|
@ -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);
|
||||
|
|
238
src/sfntfont.c
238
src/sfntfont.c
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue