@cantoo/fontkit 2.0.4 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-module.mjs +4448 -1142
- package/dist/browser-module.mjs.map +1 -1
- package/dist/browser.cjs +4449 -1142
- package/dist/browser.cjs.map +1 -1
- package/dist/main.cjs +4449 -1142
- package/dist/main.cjs.map +1 -1
- package/dist/module.mjs +4448 -1142
- package/dist/module.mjs.map +1 -1
- package/package.json +4 -1
- package/src/CmapProcessor.js +60 -21
- package/src/DFont.js +114 -14
- package/src/TTFFont.js +260 -62
- package/src/TrueTypeCollection.js +59 -15
- package/src/WOFF2Font.js +128 -22
- package/src/WOFFFont.js +45 -8
- package/src/aat/AATFeatureMap.js +83 -40
- package/src/aat/AATLayoutEngine.js +34 -2
- package/src/aat/AATLookupTable.js +24 -6
- package/src/aat/AATMorxProcessor.js +202 -65
- package/src/aat/AATStateMachine.js +35 -3
- package/src/base.js +20 -1
- package/src/cff/CFFCharsets.js +3 -0
- package/src/cff/CFFDict.js +81 -11
- package/src/cff/CFFEncodings.js +2 -0
- package/src/cff/CFFFont.js +120 -24
- package/src/cff/CFFIndex.js +66 -9
- package/src/cff/CFFOperand.js +53 -28
- package/src/cff/CFFPointer.js +41 -2
- package/src/cff/CFFPrivateDict.js +34 -24
- package/src/cff/CFFStandardStrings.js +68 -67
- package/src/cff/CFFTop.js +161 -68
- package/src/decorators.js +34 -15
- package/src/encodings.js +133 -116
- package/src/fs.js +10 -0
- package/src/glyph/BBox.js +14 -0
- package/src/glyph/CFFGlyph.js +293 -152
- package/src/glyph/COLRGlyph.js +40 -5
- package/src/glyph/Glyph.js +72 -13
- package/src/glyph/GlyphVariationProcessor.js +158 -62
- package/src/glyph/Path.js +119 -32
- package/src/glyph/SBIXGlyph.js +57 -8
- package/src/glyph/StandardNames.js +1 -0
- package/src/glyph/TTFGlyph.js +203 -63
- package/src/glyph/TTFGlyphEncoder.js +58 -26
- package/src/glyph/WOFF2Glyph.js +25 -6
- package/src/layout/GlyphPosition.js +6 -0
- package/src/layout/GlyphRun.js +28 -10
- package/src/layout/KernProcessor.js +63 -4
- package/src/layout/LayoutEngine.js +99 -26
- package/src/layout/Script.js +52 -26
- package/src/layout/UnicodeLayoutEngine.js +34 -10
- package/src/opentype/GPOSProcessor.js +156 -45
- package/src/opentype/GSUBProcessor.js +92 -33
- package/src/opentype/GlyphInfo.js +53 -5
- package/src/opentype/GlyphIterator.js +51 -2
- package/src/opentype/OTLayoutEngine.js +66 -8
- package/src/opentype/OTProcessor.js +284 -71
- package/src/opentype/ShapingPlan.js +52 -5
- package/src/opentype/shapers/ArabicShaper.js +27 -8
- package/src/opentype/shapers/DefaultShaper.js +54 -10
- package/src/opentype/shapers/HangulShaper.js +120 -42
- package/src/opentype/shapers/HebrewShaper.js +50 -16
- package/src/opentype/shapers/IndicShaper.js +159 -44
- package/src/opentype/shapers/ThaiShaper.js +50 -19
- package/src/opentype/shapers/UniversalShaper.js +83 -17
- package/src/opentype/shapers/index.js +48 -35
- package/src/opentype/shapers/indic-data.js +2 -2
- package/src/packages/unicode-properties/data-trie.js +2 -1
- package/src/packages/unicode-properties/data.js +13 -1
- package/src/packages/unicode-properties/dist/index.cjs +23 -10
- package/src/packages/unicode-properties/dist/index.cjs.map +2 -2
- package/src/packages/unicode-properties/dist/index.mjs +22 -10
- package/src/packages/unicode-properties/dist/index.mjs.map +2 -2
- package/src/packages/unicode-properties/generate.js +3 -4
- package/src/packages/unicode-properties/index.js +95 -30
- package/src/packages/unicode-properties/package.json +1 -1
- package/src/packages/unicode-trie/builder.js +146 -29
- package/src/packages/unicode-trie/dist/builder.cjs +135 -25
- package/src/packages/unicode-trie/dist/builder.cjs.map +2 -2
- package/src/packages/unicode-trie/dist/builder.mjs +134 -25
- package/src/packages/unicode-trie/dist/builder.mjs.map +2 -2
- package/src/packages/unicode-trie/dist/index.cjs +22 -9
- package/src/packages/unicode-trie/dist/index.cjs.map +2 -2
- package/src/packages/unicode-trie/dist/index.mjs +21 -9
- package/src/packages/unicode-trie/dist/index.mjs.map +2 -2
- package/src/packages/unicode-trie/index.js +63 -12
- package/src/packages/unicode-trie/package.json +1 -1
- package/src/packages/unicode-trie/swap.js +15 -2
- package/src/subset/CFFSubset.js +112 -22
- package/src/subset/Subset.js +23 -3
- package/src/subset/TTFSubset.js +84 -41
- package/src/tables/BASE.js +28 -27
- package/src/tables/COLR.js +10 -9
- package/src/tables/CPAL.js +2 -1
- package/src/tables/DSIG.js +8 -7
- package/src/tables/EBDT.js +10 -4
- package/src/tables/EBLC.js +70 -10
- package/src/tables/GDEF.js +18 -17
- package/src/tables/GPOS.js +153 -90
- package/src/tables/GSUB.js +50 -39
- package/src/tables/HVAR.js +51 -5
- package/src/tables/JSTF.js +17 -16
- package/src/tables/LTSH.js +4 -3
- package/src/tables/OS2.js +50 -49
- package/src/tables/PCLT.js +16 -15
- package/src/tables/STAT.js +46 -6
- package/src/tables/VDMX.js +18 -17
- package/src/tables/VORG.js +8 -7
- package/src/tables/WOFF2Directory.js +57 -9
- package/src/tables/WOFFDirectory.js +32 -20
- package/src/tables/aat.js +160 -35
- package/src/tables/avar.js +1 -0
- package/src/tables/bsln.js +3 -2
- package/src/tables/cmap.js +83 -63
- package/src/tables/cvt.js +1 -0
- package/src/tables/directory.js +56 -28
- package/src/tables/feat.js +24 -2
- package/src/tables/fpgm.js +1 -0
- package/src/tables/fvar.js +32 -4
- package/src/tables/gasp.js +6 -5
- package/src/tables/glyf.js +2 -1
- package/src/tables/gvar.js +29 -2
- package/src/tables/hdmx.js +18 -7
- package/src/tables/head.js +17 -16
- package/src/tables/hhea.js +15 -14
- package/src/tables/hmtx.js +18 -2
- package/src/tables/index.js +1 -5
- package/src/tables/just.js +15 -4
- package/src/tables/kern.js +84 -47
- package/src/tables/loca.js +23 -10
- package/src/tables/maxp.js +16 -15
- package/src/tables/morx.js +27 -20
- package/src/tables/name.js +120 -39
- package/src/tables/opbd.js +2 -1
- package/src/tables/opentype.js +126 -91
- package/src/tables/post.js +18 -11
- package/src/tables/prep.js +1 -0
- package/src/tables/sbix.js +12 -1
- package/src/tables/variations.js +29 -9
- package/src/tables/vhea.js +15 -14
- package/src/tables/vmtx.js +20 -4
- package/src/utils.js +15 -0
|
@@ -1,14 +1,20 @@
|
|
|
1
|
+
/** @typedef {import('../../types/fontkit').FontLike} FontLike */
|
|
2
|
+
/** @typedef {import('../../types/fontkit').GlyphPoint} GlyphPoint */
|
|
3
|
+
/** @typedef {import('../../types/fontkit').HVARTable} HVARTable */
|
|
4
|
+
/** @typedef {import('../../types/fontkit').ItemVariationStore} ItemVariationStore */
|
|
5
|
+
/** @typedef {import('../../types/fontkit').ItemVariationData} ItemVariationData */
|
|
6
|
+
|
|
1
7
|
const TUPLES_SHARE_POINT_NUMBERS = 0x8000;
|
|
2
|
-
const TUPLE_COUNT_MASK
|
|
3
|
-
const EMBEDDED_TUPLE_COORD
|
|
4
|
-
const INTERMEDIATE_TUPLE
|
|
5
|
-
const PRIVATE_POINT_NUMBERS
|
|
6
|
-
const TUPLE_INDEX_MASK
|
|
7
|
-
const POINTS_ARE_WORDS
|
|
8
|
-
const POINT_RUN_COUNT_MASK
|
|
9
|
-
const DELTAS_ARE_ZERO
|
|
10
|
-
const DELTAS_ARE_WORDS
|
|
11
|
-
const DELTA_RUN_COUNT_MASK
|
|
8
|
+
const TUPLE_COUNT_MASK = 0x0fff;
|
|
9
|
+
const EMBEDDED_TUPLE_COORD = 0x8000;
|
|
10
|
+
const INTERMEDIATE_TUPLE = 0x4000;
|
|
11
|
+
const PRIVATE_POINT_NUMBERS = 0x2000;
|
|
12
|
+
const TUPLE_INDEX_MASK = 0x0fff;
|
|
13
|
+
const POINTS_ARE_WORDS = 0x80;
|
|
14
|
+
const POINT_RUN_COUNT_MASK = 0x7f;
|
|
15
|
+
const DELTAS_ARE_ZERO = 0x80;
|
|
16
|
+
const DELTAS_ARE_WORDS = 0x40;
|
|
17
|
+
const DELTA_RUN_COUNT_MASK = 0x3f;
|
|
12
18
|
|
|
13
19
|
/**
|
|
14
20
|
* This class is transforms TrueType glyphs according to the data from
|
|
@@ -22,18 +28,35 @@ const DELTA_RUN_COUNT_MASK = 0x3f;
|
|
|
22
28
|
* @private
|
|
23
29
|
*/
|
|
24
30
|
export default class GlyphVariationProcessor {
|
|
31
|
+
/**
|
|
32
|
+
* @param {FontLike} font
|
|
33
|
+
* @param {number[]} coords
|
|
34
|
+
*/
|
|
25
35
|
constructor(font, coords) {
|
|
36
|
+
/** @type {FontLike} */
|
|
26
37
|
this.font = font;
|
|
38
|
+
/** @type {number[]} */
|
|
27
39
|
this.normalizedCoords = this.normalizeCoords(coords);
|
|
28
|
-
|
|
40
|
+
/** @type {Map<ItemVariationData, number[]>} */
|
|
41
|
+
this.blendVectors = new Map();
|
|
29
42
|
}
|
|
30
43
|
|
|
44
|
+
/**
|
|
45
|
+
* @param {number[]} coords
|
|
46
|
+
* @returns {number[]}
|
|
47
|
+
*/
|
|
31
48
|
normalizeCoords(coords) {
|
|
32
49
|
// the default mapping is linear along each axis, in two segments:
|
|
33
50
|
// from the minValue to defaultValue, and from defaultValue to maxValue.
|
|
51
|
+
/** @type {number[]} */
|
|
34
52
|
let normalized = [];
|
|
35
|
-
|
|
36
|
-
|
|
53
|
+
let fvar = this.font.fvar;
|
|
54
|
+
if (!fvar) {
|
|
55
|
+
return normalized;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (let i = 0; i < fvar.axis.length; i++) {
|
|
59
|
+
let axis = fvar.axis[i];
|
|
37
60
|
if (coords[i] < axis.defaultValue) {
|
|
38
61
|
normalized.push((coords[i] - axis.defaultValue + Number.EPSILON) / (axis.defaultValue - axis.minValue + Number.EPSILON));
|
|
39
62
|
} else {
|
|
@@ -50,9 +73,9 @@ export default class GlyphVariationProcessor {
|
|
|
50
73
|
let pair = segment.correspondence[j];
|
|
51
74
|
if (j >= 1 && normalized[i] < pair.fromCoord) {
|
|
52
75
|
let prev = segment.correspondence[j - 1];
|
|
53
|
-
normalized[i] = ((normalized[i] - prev.fromCoord) * (pair.toCoord - prev.toCoord) + Number.EPSILON)
|
|
54
|
-
(pair.fromCoord - prev.fromCoord + Number.EPSILON)
|
|
55
|
-
prev.toCoord;
|
|
76
|
+
normalized[i] = ((normalized[i] - prev.fromCoord) * (pair.toCoord - prev.toCoord) + Number.EPSILON)
|
|
77
|
+
/ (pair.fromCoord - prev.fromCoord + Number.EPSILON)
|
|
78
|
+
+ prev.toCoord;
|
|
56
79
|
|
|
57
80
|
break;
|
|
58
81
|
}
|
|
@@ -63,6 +86,11 @@ export default class GlyphVariationProcessor {
|
|
|
63
86
|
return normalized;
|
|
64
87
|
}
|
|
65
88
|
|
|
89
|
+
/**
|
|
90
|
+
* @param {number} gid
|
|
91
|
+
* @param {GlyphPoint[]} glyphPoints
|
|
92
|
+
* @returns {void}
|
|
93
|
+
*/
|
|
66
94
|
transformPoints(gid, glyphPoints) {
|
|
67
95
|
if (!this.font.fvar || !this.font.gvar) { return; }
|
|
68
96
|
|
|
@@ -82,10 +110,12 @@ export default class GlyphVariationProcessor {
|
|
|
82
110
|
let tupleCount = stream.readUInt16BE();
|
|
83
111
|
let offsetToData = offset + stream.readUInt16BE();
|
|
84
112
|
|
|
113
|
+
/** @type {Uint16Array} */
|
|
114
|
+
let sharedPoints = new Uint16Array(0);
|
|
85
115
|
if (tupleCount & TUPLES_SHARE_POINT_NUMBERS) {
|
|
86
116
|
let here = stream.pos;
|
|
87
117
|
stream.pos = offsetToData;
|
|
88
|
-
|
|
118
|
+
sharedPoints = this.decodePoints();
|
|
89
119
|
offsetToData = stream.pos;
|
|
90
120
|
stream.pos = here;
|
|
91
121
|
}
|
|
@@ -97,13 +127,13 @@ export default class GlyphVariationProcessor {
|
|
|
97
127
|
let tupleDataSize = stream.readUInt16BE();
|
|
98
128
|
let tupleIndex = stream.readUInt16BE();
|
|
99
129
|
|
|
130
|
+
/** @type {number[]} */
|
|
100
131
|
let tupleCoords;
|
|
101
132
|
if (tupleIndex & EMBEDDED_TUPLE_COORD) {
|
|
102
133
|
tupleCoords = [];
|
|
103
134
|
for (let a = 0; a < gvar.axisCount; a++) {
|
|
104
135
|
tupleCoords.push(stream.readInt16BE() / 16384);
|
|
105
136
|
}
|
|
106
|
-
|
|
107
137
|
} else {
|
|
108
138
|
if ((tupleIndex & TUPLE_INDEX_MASK) >= gvar.globalCoordCount) {
|
|
109
139
|
throw new Error('Invalid gvar table');
|
|
@@ -112,13 +142,17 @@ export default class GlyphVariationProcessor {
|
|
|
112
142
|
tupleCoords = gvar.globalCoords[tupleIndex & TUPLE_INDEX_MASK];
|
|
113
143
|
}
|
|
114
144
|
|
|
145
|
+
/** @type {number[] | undefined} */
|
|
146
|
+
let startCoords;
|
|
147
|
+
/** @type {number[] | undefined} */
|
|
148
|
+
let endCoords;
|
|
115
149
|
if (tupleIndex & INTERMEDIATE_TUPLE) {
|
|
116
|
-
|
|
150
|
+
startCoords = [];
|
|
117
151
|
for (let a = 0; a < gvar.axisCount; a++) {
|
|
118
152
|
startCoords.push(stream.readInt16BE() / 16384);
|
|
119
153
|
}
|
|
120
154
|
|
|
121
|
-
|
|
155
|
+
endCoords = [];
|
|
122
156
|
for (let a = 0; a < gvar.axisCount; a++) {
|
|
123
157
|
endCoords.push(stream.readInt16BE() / 16384);
|
|
124
158
|
}
|
|
@@ -134,6 +168,7 @@ export default class GlyphVariationProcessor {
|
|
|
134
168
|
let here = stream.pos;
|
|
135
169
|
stream.pos = offsetToData;
|
|
136
170
|
|
|
171
|
+
/** @type {Uint16Array} */
|
|
137
172
|
let points;
|
|
138
173
|
if (tupleIndex & PRIVATE_POINT_NUMBERS) {
|
|
139
174
|
points = this.decodePoints();
|
|
@@ -147,34 +182,34 @@ export default class GlyphVariationProcessor {
|
|
|
147
182
|
let yDeltas = this.decodeDeltas(nPoints);
|
|
148
183
|
|
|
149
184
|
if (points.length === 0) { // all points
|
|
150
|
-
for (let
|
|
151
|
-
|
|
152
|
-
point.x += Math.round(xDeltas[
|
|
153
|
-
point.y += Math.round(yDeltas[
|
|
185
|
+
for (let pi = 0; pi < glyphPoints.length; pi++) {
|
|
186
|
+
let point = glyphPoints[pi];
|
|
187
|
+
point.x += Math.round(xDeltas[pi] * factor);
|
|
188
|
+
point.y += Math.round(yDeltas[pi] * factor);
|
|
154
189
|
}
|
|
155
190
|
} else {
|
|
156
191
|
let outPoints = origPoints.map(pt => pt.copy());
|
|
157
192
|
let hasDelta = glyphPoints.map(() => false);
|
|
158
193
|
|
|
159
|
-
for (let
|
|
160
|
-
let idx = points[
|
|
194
|
+
for (let pi = 0; pi < points.length; pi++) {
|
|
195
|
+
let idx = points[pi];
|
|
161
196
|
if (idx < glyphPoints.length) {
|
|
162
197
|
let point = outPoints[idx];
|
|
163
198
|
hasDelta[idx] = true;
|
|
164
199
|
|
|
165
|
-
point.x += xDeltas[
|
|
166
|
-
point.y += yDeltas[
|
|
200
|
+
point.x += xDeltas[pi] * factor;
|
|
201
|
+
point.y += yDeltas[pi] * factor;
|
|
167
202
|
}
|
|
168
203
|
}
|
|
169
204
|
|
|
170
205
|
this.interpolateMissingDeltas(outPoints, origPoints, hasDelta);
|
|
171
206
|
|
|
172
|
-
for (let
|
|
173
|
-
let deltaX = outPoints[
|
|
174
|
-
let deltaY = outPoints[
|
|
207
|
+
for (let pi = 0; pi < glyphPoints.length; pi++) {
|
|
208
|
+
let deltaX = outPoints[pi].x - origPoints[pi].x;
|
|
209
|
+
let deltaY = outPoints[pi].y - origPoints[pi].y;
|
|
175
210
|
|
|
176
|
-
glyphPoints[
|
|
177
|
-
glyphPoints[
|
|
211
|
+
glyphPoints[pi].x = Math.round(glyphPoints[pi].x + deltaX);
|
|
212
|
+
glyphPoints[pi].y = Math.round(glyphPoints[pi].y + deltaY);
|
|
178
213
|
}
|
|
179
214
|
}
|
|
180
215
|
|
|
@@ -183,6 +218,9 @@ export default class GlyphVariationProcessor {
|
|
|
183
218
|
}
|
|
184
219
|
}
|
|
185
220
|
|
|
221
|
+
/**
|
|
222
|
+
* @returns {Uint16Array}
|
|
223
|
+
*/
|
|
186
224
|
decodePoints() {
|
|
187
225
|
let stream = this.font.stream;
|
|
188
226
|
let count = stream.readUInt8();
|
|
@@ -197,7 +235,8 @@ export default class GlyphVariationProcessor {
|
|
|
197
235
|
while (i < count) {
|
|
198
236
|
let run = stream.readUInt8();
|
|
199
237
|
let runCount = (run & POINT_RUN_COUNT_MASK) + 1;
|
|
200
|
-
|
|
238
|
+
// gvar point numbers are big-endian (OpenType); was incorrectly readUInt16.
|
|
239
|
+
let fn = run & POINTS_ARE_WORDS ? stream.readUInt16BE : stream.readUInt8;
|
|
201
240
|
|
|
202
241
|
for (let j = 0; j < runCount && i < count; j++) {
|
|
203
242
|
point += fn.call(stream);
|
|
@@ -208,6 +247,10 @@ export default class GlyphVariationProcessor {
|
|
|
208
247
|
return points;
|
|
209
248
|
}
|
|
210
249
|
|
|
250
|
+
/**
|
|
251
|
+
* @param {number} count
|
|
252
|
+
* @returns {Int16Array}
|
|
253
|
+
*/
|
|
211
254
|
decodeDeltas(count) {
|
|
212
255
|
let stream = this.font.stream;
|
|
213
256
|
let i = 0;
|
|
@@ -219,7 +262,6 @@ export default class GlyphVariationProcessor {
|
|
|
219
262
|
|
|
220
263
|
if (run & DELTAS_ARE_ZERO) {
|
|
221
264
|
i += runCount;
|
|
222
|
-
|
|
223
265
|
} else {
|
|
224
266
|
let fn = run & DELTAS_ARE_WORDS ? stream.readInt16BE : stream.readInt8;
|
|
225
267
|
for (let j = 0; j < runCount && i < count; j++) {
|
|
@@ -231,9 +273,19 @@ export default class GlyphVariationProcessor {
|
|
|
231
273
|
return deltas;
|
|
232
274
|
}
|
|
233
275
|
|
|
276
|
+
/**
|
|
277
|
+
* @param {number} tupleIndex
|
|
278
|
+
* @param {number[]} tupleCoords
|
|
279
|
+
* @param {number[] | undefined} startCoords
|
|
280
|
+
* @param {number[] | undefined} endCoords
|
|
281
|
+
* @returns {number}
|
|
282
|
+
*/
|
|
234
283
|
tupleFactor(tupleIndex, tupleCoords, startCoords, endCoords) {
|
|
235
284
|
let normalized = this.normalizedCoords;
|
|
236
285
|
let { gvar } = this.font;
|
|
286
|
+
if (!gvar) {
|
|
287
|
+
return 0;
|
|
288
|
+
}
|
|
237
289
|
let factor = 1;
|
|
238
290
|
|
|
239
291
|
for (let i = 0; i < gvar.axisCount; i++) {
|
|
@@ -246,20 +298,21 @@ export default class GlyphVariationProcessor {
|
|
|
246
298
|
}
|
|
247
299
|
|
|
248
300
|
if ((tupleIndex & INTERMEDIATE_TUPLE) === 0) {
|
|
249
|
-
if ((normalized[i] < Math.min(0, tupleCoords[i]))
|
|
250
|
-
|
|
301
|
+
if ((normalized[i] < Math.min(0, tupleCoords[i]))
|
|
302
|
+
|| (normalized[i] > Math.max(0, tupleCoords[i]))) {
|
|
251
303
|
return 0;
|
|
252
304
|
}
|
|
253
305
|
|
|
254
306
|
factor = (factor * normalized[i] + Number.EPSILON) / (tupleCoords[i] + Number.EPSILON);
|
|
255
307
|
} else {
|
|
256
|
-
if (
|
|
257
|
-
|
|
308
|
+
if (!startCoords || !endCoords) {
|
|
309
|
+
return 0;
|
|
310
|
+
}
|
|
311
|
+
if ((normalized[i] < startCoords[i])
|
|
312
|
+
|| (normalized[i] > endCoords[i])) {
|
|
258
313
|
return 0;
|
|
259
|
-
|
|
260
314
|
} else if (normalized[i] < tupleCoords[i]) {
|
|
261
315
|
factor = factor * (normalized[i] - startCoords[i] + Number.EPSILON) / (tupleCoords[i] - startCoords[i] + Number.EPSILON);
|
|
262
|
-
|
|
263
316
|
} else {
|
|
264
317
|
factor = factor * (endCoords[i] - normalized[i] + Number.EPSILON) / (endCoords[i] - tupleCoords[i] + Number.EPSILON);
|
|
265
318
|
}
|
|
@@ -269,9 +322,15 @@ export default class GlyphVariationProcessor {
|
|
|
269
322
|
return factor;
|
|
270
323
|
}
|
|
271
324
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
325
|
+
/**
|
|
326
|
+
* Interpolates points without delta values.
|
|
327
|
+
* Needed for the Ø and Q glyphs in Skia.
|
|
328
|
+
* Algorithm from Freetype.
|
|
329
|
+
* @param {GlyphPoint[]} points
|
|
330
|
+
* @param {GlyphPoint[]} inPoints
|
|
331
|
+
* @param {boolean[]} hasDelta
|
|
332
|
+
* @returns {void}
|
|
333
|
+
*/
|
|
275
334
|
interpolateMissingDeltas(points, inPoints, hasDelta) {
|
|
276
335
|
if (points.length === 0) {
|
|
277
336
|
return;
|
|
@@ -327,24 +386,36 @@ export default class GlyphVariationProcessor {
|
|
|
327
386
|
}
|
|
328
387
|
}
|
|
329
388
|
|
|
389
|
+
/**
|
|
390
|
+
* @param {number} p1
|
|
391
|
+
* @param {number} p2
|
|
392
|
+
* @param {number} ref1
|
|
393
|
+
* @param {number} ref2
|
|
394
|
+
* @param {GlyphPoint[]} inPoints
|
|
395
|
+
* @param {GlyphPoint[]} outPoints
|
|
396
|
+
* @returns {void}
|
|
397
|
+
*/
|
|
330
398
|
deltaInterpolate(p1, p2, ref1, ref2, inPoints, outPoints) {
|
|
331
399
|
if (p1 > p2) {
|
|
332
400
|
return;
|
|
333
401
|
}
|
|
334
402
|
|
|
403
|
+
/** @type {Array<'x' | 'y'>} */
|
|
335
404
|
let iterable = ['x', 'y'];
|
|
336
405
|
for (let i = 0; i < iterable.length; i++) {
|
|
337
406
|
let k = iterable[i];
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
407
|
+
let r1 = ref1;
|
|
408
|
+
let r2 = ref2;
|
|
409
|
+
if (inPoints[r1][k] > inPoints[r2][k]) {
|
|
410
|
+
let p = r1;
|
|
411
|
+
r1 = r2;
|
|
412
|
+
r2 = p;
|
|
342
413
|
}
|
|
343
414
|
|
|
344
|
-
let in1 = inPoints[
|
|
345
|
-
let in2 = inPoints[
|
|
346
|
-
let out1 = outPoints[
|
|
347
|
-
let out2 = outPoints[
|
|
415
|
+
let in1 = inPoints[r1][k];
|
|
416
|
+
let in2 = inPoints[r2][k];
|
|
417
|
+
let out1 = outPoints[r1][k];
|
|
418
|
+
let out2 = outPoints[r2][k];
|
|
348
419
|
|
|
349
420
|
// If the reference points have the same coordinate but different
|
|
350
421
|
// delta, inferred delta is zero. Otherwise interpolate.
|
|
@@ -368,6 +439,14 @@ export default class GlyphVariationProcessor {
|
|
|
368
439
|
}
|
|
369
440
|
}
|
|
370
441
|
|
|
442
|
+
/**
|
|
443
|
+
* @param {number} p1
|
|
444
|
+
* @param {number} p2
|
|
445
|
+
* @param {number} ref
|
|
446
|
+
* @param {GlyphPoint[]} inPoints
|
|
447
|
+
* @param {GlyphPoint[]} outPoints
|
|
448
|
+
* @returns {void}
|
|
449
|
+
*/
|
|
371
450
|
deltaShift(p1, p2, ref, inPoints, outPoints) {
|
|
372
451
|
let deltaX = outPoints[ref].x - inPoints[ref].x;
|
|
373
452
|
let deltaY = outPoints[ref].y - inPoints[ref].y;
|
|
@@ -384,6 +463,11 @@ export default class GlyphVariationProcessor {
|
|
|
384
463
|
}
|
|
385
464
|
}
|
|
386
465
|
|
|
466
|
+
/**
|
|
467
|
+
* @param {number} gid
|
|
468
|
+
* @param {HVARTable} table
|
|
469
|
+
* @returns {number}
|
|
470
|
+
*/
|
|
387
471
|
getAdvanceAdjustment(gid, table) {
|
|
388
472
|
let outerIndex, innerIndex;
|
|
389
473
|
|
|
@@ -393,7 +477,7 @@ export default class GlyphVariationProcessor {
|
|
|
393
477
|
idx = table.advanceWidthMapping.mapCount - 1;
|
|
394
478
|
}
|
|
395
479
|
|
|
396
|
-
({outerIndex, innerIndex} = table.advanceWidthMapping.mapData[idx]);
|
|
480
|
+
({ outerIndex, innerIndex } = table.advanceWidthMapping.mapData[idx]);
|
|
397
481
|
} else {
|
|
398
482
|
outerIndex = 0;
|
|
399
483
|
innerIndex = gid;
|
|
@@ -402,8 +486,14 @@ export default class GlyphVariationProcessor {
|
|
|
402
486
|
return this.getDelta(table.itemVariationStore, outerIndex, innerIndex);
|
|
403
487
|
}
|
|
404
488
|
|
|
405
|
-
|
|
406
|
-
|
|
489
|
+
/**
|
|
490
|
+
* See pseudo code from `Font Variations Overview'
|
|
491
|
+
* in the OpenType specification.
|
|
492
|
+
* @param {ItemVariationStore} itemStore
|
|
493
|
+
* @param {number} outerIndex
|
|
494
|
+
* @param {number} innerIndex
|
|
495
|
+
* @returns {number}
|
|
496
|
+
*/
|
|
407
497
|
getDelta(itemStore, outerIndex, innerIndex) {
|
|
408
498
|
if (outerIndex >= itemStore.itemVariationData.length) {
|
|
409
499
|
return 0;
|
|
@@ -425,13 +515,20 @@ export default class GlyphVariationProcessor {
|
|
|
425
515
|
return netAdjustment;
|
|
426
516
|
}
|
|
427
517
|
|
|
518
|
+
/**
|
|
519
|
+
* @param {ItemVariationStore} itemStore
|
|
520
|
+
* @param {number} outerIndex
|
|
521
|
+
* @returns {number[]}
|
|
522
|
+
*/
|
|
428
523
|
getBlendVector(itemStore, outerIndex) {
|
|
429
524
|
let varData = itemStore.itemVariationData[outerIndex];
|
|
430
|
-
|
|
431
|
-
|
|
525
|
+
let cached = this.blendVectors.get(varData);
|
|
526
|
+
if (cached) {
|
|
527
|
+
return cached;
|
|
432
528
|
}
|
|
433
529
|
|
|
434
530
|
let normalizedCoords = this.normalizedCoords;
|
|
531
|
+
/** @type {number[]} */
|
|
435
532
|
let blendVector = [];
|
|
436
533
|
|
|
437
534
|
// outer loop steps through master designs to be blended
|
|
@@ -449,7 +546,6 @@ export default class GlyphVariationProcessor {
|
|
|
449
546
|
// ignore invalid ranges
|
|
450
547
|
if (axis.startCoord > axis.peakCoord || axis.peakCoord > axis.endCoord) {
|
|
451
548
|
axisScalar = 1;
|
|
452
|
-
|
|
453
549
|
} else if (axis.startCoord < 0 && axis.endCoord > 0 && axis.peakCoord !== 0) {
|
|
454
550
|
axisScalar = 1;
|
|
455
551
|
|
|
@@ -466,11 +562,11 @@ export default class GlyphVariationProcessor {
|
|
|
466
562
|
if (normalizedCoords[j] === axis.peakCoord) {
|
|
467
563
|
axisScalar = 1;
|
|
468
564
|
} else if (normalizedCoords[j] < axis.peakCoord) {
|
|
469
|
-
axisScalar = (normalizedCoords[j] - axis.startCoord + Number.EPSILON)
|
|
470
|
-
(axis.peakCoord - axis.startCoord + Number.EPSILON);
|
|
565
|
+
axisScalar = (normalizedCoords[j] - axis.startCoord + Number.EPSILON)
|
|
566
|
+
/ (axis.peakCoord - axis.startCoord + Number.EPSILON);
|
|
471
567
|
} else {
|
|
472
|
-
axisScalar = (axis.endCoord - normalizedCoords[j] + Number.EPSILON)
|
|
473
|
-
(axis.endCoord - axis.peakCoord + Number.EPSILON);
|
|
568
|
+
axisScalar = (axis.endCoord - normalizedCoords[j] + Number.EPSILON)
|
|
569
|
+
/ (axis.endCoord - axis.peakCoord + Number.EPSILON);
|
|
474
570
|
}
|
|
475
571
|
}
|
|
476
572
|
|