1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#ifndef VEGA_SHAPE_H
#define VEGA_SHAPE_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/* Shaping (docs/design/004-text.md): a run of characters (one script, one
* direction) to glyphs and their positions, as HarfBuzz 10 shapes it with
* its default, Arabic and Hebrew shapers, glyph for glyph and unit for unit.
*
* What a font's shaping needs travels in a symbol file (its shaping
* section), written by the build tool:
* - plans, compiled from the font: per script and direction, which
* lookups run, in what order, on which glyphs (the feature masks);
* - the font's character map and advances;
* - its OpenType layout tables (GDEF, GSUB, GPOS) as they are: they are
* read in place, every read checked against the table's end, so a
* damaged table shapes wrong but never reads outside it.
* Positions are in the font's units (VegaShaping.upem to an em).
*
* The section, little-endian:
* "VSHP", u32 size, u16 upem, u16 glyph_count,
* u32 cmap_count, u32 cmap_offset (u32 code, u32 glyph; by code),
* u32 advances_offset (glyph_count u16),
* u32 offset, u32 size of GDEF, of GSUB and of GPOS (0 0 when absent),
* u32 plan_count, u32 plans_offset (VEGA_PLAN_BYTES each),
* u32 step_count, u32 steps_offset (8 bytes each),
* u32 offset, u32 size of the kern table (0 0 when absent),
* u32 extents_offset (glyph_count of i16 x_bearing,
* y_bearing, width, height; 0 when
* no plan positions marks without
* GPOS; x_bearing INT16_MIN: none),
* u32 0
* Offsets are from the section's start. A plan:
* u32 script (ISO 15924 as a tag: 'Latn'), u8 direction, u8 native
* direction (of its script; 0 when it has none), u8 shaper, u8 flags,
* u32 global mask, u32 kern mask, u32 masks[VEGA_PLAN_MASKS], u32 first
* GSUB step, u32 GSUB steps, u32 first GPOS step, u32 GPOS steps.
* A step, a lookup to run: u16 lookup index, u8 flags, u8 0, u32 mask. */
enum { VEGA_SHAPING_HEADER = 80, VEGA_PLAN_BYTES = 88, VEGA_STEP_BYTES = 8, VEGA_PLAN_MASKS = 14 };
enum { VEGA_SHAPE_LTR = 1, VEGA_SHAPE_RTL = 2 };
enum { VEGA_SHAPER_DEFAULT, VEGA_SHAPER_ARABIC, VEGA_SHAPER_HEBREW, VEGA_SHAPER_HANGUL };
/* Plan flags: GPOS runs; mark advances are zeroed after it (by GDEF); glyph
* classes come from Unicode (the font has none); the font positions marks
* (a 'mark' feature); automatic fractions; the kern table kerns; marks are
* placed around their base without GPOS, and zeroing a mark's advance keeps
* it where it was. */
enum { VEGA_PLAN_GPOS = 1, VEGA_PLAN_ZERO_MARKS = 2, VEGA_PLAN_GUESS_CLASSES = 4, VEGA_PLAN_GPOS_MARK = 8,
VEGA_PLAN_FRACTIONS = 16, VEGA_PLAN_KERN = 32, VEGA_PLAN_FALLBACK_MARKS = 64, VEGA_PLAN_ADJUST_ZEROING = 128 };
/* The masks a plan names, for the features set glyph by glyph. */
enum { VEGA_MASK_ISOL, VEGA_MASK_FINA, VEGA_MASK_FIN2, VEGA_MASK_FIN3, VEGA_MASK_MEDI, VEGA_MASK_MED2,
VEGA_MASK_INIT, VEGA_MASK_RTLM, VEGA_MASK_FRAC, VEGA_MASK_NUMR, VEGA_MASK_DNOM, VEGA_MASK_LJMO, VEGA_MASK_VJMO,
VEGA_MASK_TJMO };
/* Step flags. */
enum { VEGA_STEP_AUTO_ZWNJ = 1, VEGA_STEP_AUTO_ZWJ = 2, VEGA_STEP_RANDOM = 4, VEGA_STEP_PER_SYLLABLE = 8 };
typedef struct { const unsigned char *p; uint32_t size; } VegaTable;
/* Which glyphs may be in a set, as three 64-bit patterns of glyph bits
* (HarfBuzz's set digest): a glyph whose bits are not all there is not. */
typedef struct { uint64_t mask[3]; } VegaDigest;
typedef struct {
uint16_t type; /* with extensions resolved */
uint32_t at;
VegaDigest digest; /* the glyphs it starts from */
} VegaSubtable;
typedef struct {
uint16_t type, flags;
uint32_t props; /* flags, and the mark filtering set in the high half */
uint32_t first, count; /* subtables */
bool reverse;
VegaDigest digest; /* the glyphs its subtables start from */
} VegaLookup;
typedef struct {
const unsigned char *bytes;
size_t size;
uint16_t upem, glyph_count;
uint32_t cmap_count, plan_count;
const unsigned char *cmap, *advances, *plans, *steps, *extents;
VegaTable gdef, gsub, gpos, kern;
uint32_t glyph_classes, attach_classes, mark_sets; /* in GDEF; 0 when absent */
VegaLookup *lookups[2]; /* GSUB, GPOS */
uint32_t lookup_count[2];
VegaSubtable *subtables;
uint16_t *bmp[256]; /* the character map's glyphs below U+10000, by page */
} VegaShaping;
/* Open a shaping section (kept, not copied); false with why. */
bool vega_shaping_open(VegaShaping *, const unsigned char *bytes, size_t size, char *error, size_t error_size);
void vega_shaping_close(VegaShaping *);
/* The font's glyph for a character, or 0. */
uint32_t vega_shaping_glyph(const VegaShaping *, uint32_t code);
/* A shaped glyph, as HarfBuzz gives it: in visual order (left to right),
* cluster the index of the first character it came from; each glyph is
* drawn at the pen plus its offset, then the pen moves by its advance. */
typedef struct {
uint32_t glyph, cluster;
int32_t x_advance, y_advance, x_offset, y_offset;
} VegaShaped;
/* The buffers shaping works in, kept from one run to the next. */
typedef struct VegaShaper VegaShaper;
VegaShaper *vega_shaper_new(void);
void vega_shaper_free(VegaShaper *);
/* Shape a run of count characters of script (an ISO 15924 tag, as
* vega_script_code gives it) in direction (VEGA_SHAPE_LTR or _RTL) by the
* plan compiled for them (or for Common, 'Zyyy', when there is none). The
* glyphs (as many as returned) are the shaper's until its next run; -1
* when there is no plan or no memory. */
long vega_shape(VegaShaper *, const VegaShaping *, const uint32_t *codes, size_t count, uint32_t script, int direction,
const VegaShaped **out);
#endif
|