@cantoo/fontkit 2.0.5 → 2.0.7
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.d.ts +239 -0
- package/dist/browser-module.mjs +4423 -1117
- package/dist/browser-module.mjs.map +1 -1
- package/dist/browser.cjs +4424 -1117
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +239 -0
- package/dist/fontkit.umd.d.ts +239 -0
- package/dist/fontkit.umd.js +22076 -0
- package/dist/fontkit.umd.js.map +7 -0
- package/dist/index.d.ts +239 -0
- package/dist/main.cjs +4424 -1117
- package/dist/main.cjs.map +1 -1
- package/dist/main.d.ts +239 -0
- package/dist/module.d.ts +239 -0
- package/dist/module.mjs +4423 -1117
- package/dist/module.mjs.map +1 -1
- package/package.json +22 -5
- package/src/CmapProcessor.js +59 -20
- package/src/DFont.js +114 -14
- package/src/TTFFont.js +259 -57
- package/src/TrueTypeCollection.js +54 -10
- package/src/WOFF2Font.js +128 -16
- package/src/WOFFFont.js +45 -8
- package/src/aat/AATFeatureMap.js +62 -18
- package/src/aat/AATLayoutEngine.js +33 -1
- package/src/aat/AATLookupTable.js +22 -4
- package/src/aat/AATMorxProcessor.js +189 -52
- package/src/aat/AATStateMachine.js +32 -0
- package/src/base.js +19 -0
- package/src/cff/CFFCharsets.js +3 -0
- package/src/cff/CFFDict.js +79 -9
- package/src/cff/CFFEncodings.js +2 -0
- package/src/cff/CFFFont.js +119 -23
- package/src/cff/CFFIndex.js +62 -5
- package/src/cff/CFFOperand.js +52 -17
- package/src/cff/CFFPointer.js +41 -2
- package/src/cff/CFFPrivateDict.js +14 -4
- package/src/cff/CFFStandardStrings.js +1 -0
- package/src/cff/CFFTop.js +103 -10
- package/src/decorators.js +32 -13
- package/src/encodings.js +22 -5
- package/src/fs.js +10 -0
- package/src/glyph/BBox.js +14 -0
- package/src/glyph/CFFGlyph.js +290 -148
- package/src/glyph/COLRGlyph.js +38 -3
- package/src/glyph/Glyph.js +68 -9
- package/src/glyph/GlyphVariationProcessor.js +135 -34
- package/src/glyph/Path.js +107 -20
- package/src/glyph/SBIXGlyph.js +57 -8
- package/src/glyph/StandardNames.js +1 -0
- package/src/glyph/TTFGlyph.js +176 -29
- package/src/glyph/TTFGlyphEncoder.js +32 -0
- package/src/glyph/WOFF2Glyph.js +23 -4
- package/src/layout/GlyphPosition.js +6 -0
- package/src/layout/GlyphRun.js +25 -7
- package/src/layout/KernProcessor.js +62 -3
- package/src/layout/LayoutEngine.js +86 -12
- package/src/layout/Script.js +27 -1
- package/src/layout/UnicodeLayoutEngine.js +29 -4
- package/src/opentype/GPOSProcessor.js +156 -45
- package/src/opentype/GSUBProcessor.js +92 -33
- package/src/opentype/GlyphInfo.js +52 -4
- package/src/opentype/GlyphIterator.js +51 -2
- package/src/opentype/OTLayoutEngine.js +66 -8
- package/src/opentype/OTProcessor.js +283 -70
- package/src/opentype/ShapingPlan.js +51 -3
- package/src/opentype/shapers/ArabicShaper.js +19 -0
- package/src/opentype/shapers/DefaultShaper.js +51 -7
- package/src/opentype/shapers/HangulShaper.js +85 -7
- package/src/opentype/shapers/HebrewShaper.js +45 -11
- package/src/opentype/shapers/IndicShaper.js +141 -26
- package/src/opentype/shapers/ThaiShaper.js +35 -4
- package/src/opentype/shapers/UniversalShaper.js +83 -17
- package/src/opentype/shapers/index.js +15 -2
- package/src/packages/unicode-properties/data-trie.js +1 -0
- package/src/packages/unicode-properties/data.js +12 -0
- package/src/packages/unicode-properties/dist/index.cjs +22 -9
- package/src/packages/unicode-properties/dist/index.cjs.map +2 -2
- package/src/packages/unicode-properties/dist/index.mjs +21 -9
- package/src/packages/unicode-properties/dist/index.mjs.map +2 -2
- package/src/packages/unicode-properties/index.js +65 -0
- package/src/packages/unicode-properties/package.json +1 -1
- package/src/packages/unicode-trie/builder.js +128 -7
- package/src/packages/unicode-trie/dist/builder.cjs +129 -16
- package/src/packages/unicode-trie/dist/builder.cjs.map +2 -2
- package/src/packages/unicode-trie/dist/builder.mjs +128 -16
- 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 +62 -10
- package/src/packages/unicode-trie/package.json +1 -1
- package/src/packages/unicode-trie/swap.js +13 -0
- package/src/subset/CFFSubset.js +112 -22
- package/src/subset/Subset.js +21 -1
- package/src/subset/TTFSubset.js +79 -36
- package/src/tables/BASE.js +1 -0
- package/src/tables/COLR.js +1 -0
- package/src/tables/CPAL.js +1 -0
- package/src/tables/DSIG.js +1 -0
- package/src/tables/EBDT.js +10 -3
- package/src/tables/EBLC.js +67 -7
- package/src/tables/GDEF.js +1 -0
- package/src/tables/GPOS.js +79 -16
- package/src/tables/GSUB.js +14 -3
- package/src/tables/HVAR.js +51 -5
- package/src/tables/JSTF.js +3 -2
- package/src/tables/LTSH.js +1 -0
- package/src/tables/OS2.js +1 -0
- package/src/tables/PCLT.js +1 -0
- package/src/tables/STAT.js +46 -6
- package/src/tables/VDMX.js +1 -0
- package/src/tables/VORG.js +1 -0
- package/src/tables/WOFF2Directory.js +56 -8
- package/src/tables/WOFFDirectory.js +14 -2
- 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 +26 -6
- package/src/tables/cvt.js +1 -0
- package/src/tables/directory.js +44 -16
- 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 +1 -0
- package/src/tables/glyf.js +1 -0
- package/src/tables/gvar.js +29 -2
- package/src/tables/hdmx.js +12 -1
- package/src/tables/head.js +1 -0
- package/src/tables/hhea.js +1 -0
- package/src/tables/hmtx.js +18 -2
- package/src/tables/index.js +1 -0
- package/src/tables/just.js +15 -4
- package/src/tables/kern.js +43 -6
- package/src/tables/loca.js +21 -8
- package/src/tables/maxp.js +1 -0
- package/src/tables/morx.js +14 -7
- package/src/tables/name.js +104 -23
- package/src/tables/opbd.js +2 -1
- package/src/tables/opentype.js +39 -4
- package/src/tables/post.js +8 -1
- package/src/tables/prep.js +1 -0
- package/src/tables/sbix.js +12 -1
- package/src/tables/variations.js +23 -3
- package/src/tables/vhea.js +1 -0
- package/src/tables/vmtx.js +18 -2
- package/src/utils.js +15 -0
- package/types/assets.d.ts +13 -0
- package/types/deps.d.ts +83 -0
- package/types/fontkit.d.ts +1324 -0
- package/types/index.d.ts +239 -0
- package/types/restructure.d.ts +354 -0
package/src/glyph/CFFGlyph.js
CHANGED
|
@@ -2,20 +2,61 @@ import Glyph from './Glyph';
|
|
|
2
2
|
import Path from './Path';
|
|
3
3
|
import { StandardEncoding } from '../cff/CFFEncodings';
|
|
4
4
|
|
|
5
|
+
/** @typedef {import('../../types/fontkit').CFFCharString} CFFCharString */
|
|
6
|
+
/** @typedef {import('../../types/fontkit').CFFFontLike} CFFFontLike */
|
|
7
|
+
/** @typedef {import('../../types/fontkit').GlyphLike} GlyphLike */
|
|
8
|
+
/** @typedef {import('../../types/fontkit').ItemVariationStore} ItemVariationStore */
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {unknown} value
|
|
12
|
+
* @returns {value is CFFCharString}
|
|
13
|
+
*/
|
|
14
|
+
function isCFFCharString(value) {
|
|
15
|
+
if (typeof value !== 'object' || value === null) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
let offset = Reflect.get(value, 'offset');
|
|
19
|
+
let length = Reflect.get(value, 'length');
|
|
20
|
+
return typeof offset === 'number' && typeof length === 'number';
|
|
21
|
+
}
|
|
22
|
+
|
|
5
23
|
/**
|
|
6
24
|
* Represents an OpenType PostScript glyph, in the Compact Font Format.
|
|
7
25
|
*/
|
|
8
26
|
export default class CFFGlyph extends Glyph {
|
|
9
27
|
type = 'CFF';
|
|
10
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Subroutines used while decoding; set during `_getPath`.
|
|
31
|
+
* @type {Record<number, boolean> | undefined}
|
|
32
|
+
*/
|
|
33
|
+
_usedGsubrs;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Local subroutines used while decoding; set during `_getPath`.
|
|
37
|
+
* @type {Record<number, boolean> | undefined}
|
|
38
|
+
*/
|
|
39
|
+
_usedSubrs;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @returns {string | null | undefined}
|
|
43
|
+
*/
|
|
11
44
|
_getName() {
|
|
12
45
|
if (this._font.CFF2) {
|
|
13
46
|
return super._getName();
|
|
14
47
|
}
|
|
15
48
|
|
|
16
|
-
|
|
49
|
+
let cff = this._font['CFF '];
|
|
50
|
+
if (!cff || typeof cff.getGlyphName !== 'function') {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return cff.getGlyphName(this.id);
|
|
17
54
|
}
|
|
18
55
|
|
|
56
|
+
/**
|
|
57
|
+
* @param {{ length: number }} s
|
|
58
|
+
* @returns {number}
|
|
59
|
+
*/
|
|
19
60
|
bias(s) {
|
|
20
61
|
if (s.length < 1240) {
|
|
21
62
|
return 107;
|
|
@@ -26,45 +67,103 @@ export default class CFFGlyph extends Glyph {
|
|
|
26
67
|
}
|
|
27
68
|
}
|
|
28
69
|
|
|
70
|
+
/**
|
|
71
|
+
* @returns {Path}
|
|
72
|
+
*/
|
|
29
73
|
_getPath() {
|
|
30
74
|
let cff = this._font.CFF2 || this._font['CFF '];
|
|
31
|
-
|
|
32
|
-
|
|
75
|
+
if (!cff) {
|
|
76
|
+
return new Path();
|
|
77
|
+
}
|
|
78
|
+
/** @type {CFFFontLike} */
|
|
79
|
+
let cffFont = cff;
|
|
80
|
+
let { stream } = cffFont;
|
|
81
|
+
let rawStr = cffFont.topDict.CharStrings[this.id];
|
|
82
|
+
if (!isCFFCharString(rawStr)) {
|
|
83
|
+
return new Path();
|
|
84
|
+
}
|
|
85
|
+
let str = rawStr;
|
|
33
86
|
let end = str.offset + str.length;
|
|
34
87
|
stream.pos = str.offset;
|
|
35
88
|
|
|
36
89
|
let path = new Path();
|
|
90
|
+
/** @type {number[]} */
|
|
37
91
|
let stack = [];
|
|
92
|
+
/** @type {number[]} */
|
|
38
93
|
let trans = [];
|
|
39
94
|
|
|
95
|
+
/** @type {number | null} */
|
|
40
96
|
let width = null;
|
|
41
97
|
let nStems = 0;
|
|
42
98
|
let x = 0, y = 0;
|
|
99
|
+
/** @type {Record<number, boolean>} */
|
|
43
100
|
let usedGsubrs;
|
|
101
|
+
/** @type {Record<number, boolean>} */
|
|
44
102
|
let usedSubrs;
|
|
45
103
|
let open = false;
|
|
46
104
|
|
|
47
105
|
this._usedGsubrs = usedGsubrs = {};
|
|
48
106
|
this._usedSubrs = usedSubrs = {};
|
|
49
107
|
|
|
50
|
-
let gsubrs =
|
|
108
|
+
let gsubrs = cffFont.globalSubrIndex || [];
|
|
51
109
|
let gsubrsBias = this.bias(gsubrs);
|
|
52
110
|
|
|
53
|
-
let
|
|
54
|
-
|
|
111
|
+
let fetchedPrivate = cffFont.privateDictForGlyph(this.id);
|
|
112
|
+
/** @type {import('../../types/fontkit').CFFPrivateDict} */
|
|
113
|
+
let privateDict = fetchedPrivate ? fetchedPrivate : {};
|
|
114
|
+
/** @type {CFFCharString[]} */
|
|
115
|
+
let subrs = [];
|
|
116
|
+
if (Array.isArray(privateDict.Subrs)) {
|
|
117
|
+
for (let entry of privateDict.Subrs) {
|
|
118
|
+
if (isCFFCharString(entry)) {
|
|
119
|
+
subrs.push(entry);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
55
123
|
let subrsBias = this.bias(subrs);
|
|
124
|
+
let nominalWidthX = typeof privateDict.nominalWidthX === 'number' ? privateDict.nominalWidthX : 0;
|
|
56
125
|
|
|
57
|
-
|
|
58
|
-
let
|
|
126
|
+
/** @type {ItemVariationStore | undefined} */
|
|
127
|
+
let vstore = (cffFont.topDict.vstore && cffFont.topDict.vstore.itemVariationStore) || undefined;
|
|
128
|
+
/** @type {number} */
|
|
129
|
+
let vsindex = typeof privateDict.vsindex === 'number' ? privateDict.vsindex : 0;
|
|
59
130
|
let variationProcessor = this._font._variationProcessor;
|
|
60
131
|
let font = this._font;
|
|
61
132
|
|
|
133
|
+
/**
|
|
134
|
+
* @returns {number}
|
|
135
|
+
*/
|
|
136
|
+
function shiftStack() {
|
|
137
|
+
let v = stack.shift();
|
|
138
|
+
if (v === undefined) {
|
|
139
|
+
throw new Error('CFF stack underflow');
|
|
140
|
+
}
|
|
141
|
+
return v;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @returns {number}
|
|
146
|
+
*/
|
|
147
|
+
function popStack() {
|
|
148
|
+
let v = stack.pop();
|
|
149
|
+
if (v === undefined) {
|
|
150
|
+
throw new Error('CFF stack underflow');
|
|
151
|
+
}
|
|
152
|
+
return v;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @returns {void}
|
|
157
|
+
*/
|
|
62
158
|
function checkWidth() {
|
|
63
159
|
if (width == null) {
|
|
64
|
-
width =
|
|
160
|
+
width = shiftStack() + nominalWidthX;
|
|
65
161
|
}
|
|
66
162
|
}
|
|
67
163
|
|
|
164
|
+
/**
|
|
165
|
+
* @returns {number}
|
|
166
|
+
*/
|
|
68
167
|
function parseStems() {
|
|
69
168
|
if (stack.length % 2 !== 0) {
|
|
70
169
|
checkWidth();
|
|
@@ -74,33 +173,61 @@ export default class CFFGlyph extends Glyph {
|
|
|
74
173
|
return stack.length = 0;
|
|
75
174
|
}
|
|
76
175
|
|
|
77
|
-
|
|
176
|
+
/**
|
|
177
|
+
* @param {number} mx
|
|
178
|
+
* @param {number} my
|
|
179
|
+
* @returns {void}
|
|
180
|
+
*/
|
|
181
|
+
function moveTo(mx, my) {
|
|
78
182
|
if (open) {
|
|
79
183
|
path.closePath();
|
|
80
184
|
}
|
|
81
185
|
|
|
82
|
-
path.moveTo(
|
|
186
|
+
path.moveTo(mx, my);
|
|
83
187
|
open = true;
|
|
84
188
|
}
|
|
85
189
|
|
|
190
|
+
/**
|
|
191
|
+
* @param {string | null | undefined} name
|
|
192
|
+
* @returns {GlyphLike}
|
|
193
|
+
*/
|
|
86
194
|
function glyphForName(name) {
|
|
87
195
|
if (name) {
|
|
88
196
|
for (let i = 0; i < font.numGlyphs; i++) {
|
|
89
|
-
if (
|
|
90
|
-
|
|
197
|
+
if (typeof cffFont.getGlyphName === 'function' && cffFont.getGlyphName(i) === name) {
|
|
198
|
+
let g = font.getGlyph(i);
|
|
199
|
+
if (!g) {
|
|
200
|
+
throw new Error(`CFF glyph ${i} (name "${name}") is missing; font may be corrupt or incomplete`);
|
|
201
|
+
}
|
|
202
|
+
return g;
|
|
91
203
|
}
|
|
92
204
|
}
|
|
93
205
|
}
|
|
94
|
-
|
|
206
|
+
let fallback = font.getGlyph(0);
|
|
207
|
+
if (!fallback) {
|
|
208
|
+
throw new Error('CFF glyph 0 (.notdef) is missing; font may be corrupt or incomplete');
|
|
209
|
+
}
|
|
210
|
+
return fallback;
|
|
95
211
|
}
|
|
96
212
|
|
|
213
|
+
/**
|
|
214
|
+
* @returns {void}
|
|
215
|
+
*/
|
|
97
216
|
let parse = function () {
|
|
98
217
|
while (stream.pos < end) {
|
|
99
218
|
let op = stream.readUInt8();
|
|
100
219
|
if (op < 32) {
|
|
101
|
-
|
|
220
|
+
/** @type {number} */
|
|
221
|
+
let index;
|
|
222
|
+
/** @type {CFFCharString | undefined} */
|
|
223
|
+
let subr;
|
|
224
|
+
/** @type {boolean} */
|
|
225
|
+
let phase;
|
|
226
|
+
/** @type {number} */
|
|
102
227
|
let c1x, c1y, c2x, c2y, c3x, c3y;
|
|
228
|
+
/** @type {number} */
|
|
103
229
|
let c4x, c4y, c5x, c5y, c6x, c6y;
|
|
230
|
+
/** @type {number[]} */
|
|
104
231
|
let pts;
|
|
105
232
|
|
|
106
233
|
switch (op) {
|
|
@@ -116,14 +243,14 @@ export default class CFFGlyph extends Glyph {
|
|
|
116
243
|
checkWidth();
|
|
117
244
|
}
|
|
118
245
|
|
|
119
|
-
y +=
|
|
246
|
+
y += shiftStack();
|
|
120
247
|
moveTo(x, y);
|
|
121
248
|
break;
|
|
122
249
|
|
|
123
250
|
case 5: // rlineto
|
|
124
251
|
while (stack.length >= 2) {
|
|
125
|
-
x +=
|
|
126
|
-
y +=
|
|
252
|
+
x += shiftStack();
|
|
253
|
+
y += shiftStack();
|
|
127
254
|
path.lineTo(x, y);
|
|
128
255
|
}
|
|
129
256
|
break;
|
|
@@ -133,9 +260,9 @@ export default class CFFGlyph extends Glyph {
|
|
|
133
260
|
phase = op === 6;
|
|
134
261
|
while (stack.length >= 1) {
|
|
135
262
|
if (phase) {
|
|
136
|
-
x +=
|
|
263
|
+
x += shiftStack();
|
|
137
264
|
} else {
|
|
138
|
-
y +=
|
|
265
|
+
y += shiftStack();
|
|
139
266
|
}
|
|
140
267
|
|
|
141
268
|
path.lineTo(x, y);
|
|
@@ -145,18 +272,18 @@ export default class CFFGlyph extends Glyph {
|
|
|
145
272
|
|
|
146
273
|
case 8: // rrcurveto
|
|
147
274
|
while (stack.length > 0) {
|
|
148
|
-
c1x = x +
|
|
149
|
-
c1y = y +
|
|
150
|
-
c2x = c1x +
|
|
151
|
-
c2y = c1y +
|
|
152
|
-
x = c2x +
|
|
153
|
-
y = c2y +
|
|
275
|
+
c1x = x + shiftStack();
|
|
276
|
+
c1y = y + shiftStack();
|
|
277
|
+
c2x = c1x + shiftStack();
|
|
278
|
+
c2y = c1y + shiftStack();
|
|
279
|
+
x = c2x + shiftStack();
|
|
280
|
+
y = c2y + shiftStack();
|
|
154
281
|
path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);
|
|
155
282
|
}
|
|
156
283
|
break;
|
|
157
284
|
|
|
158
285
|
case 10: // callsubr
|
|
159
|
-
index =
|
|
286
|
+
index = popStack() + subrsBias;
|
|
160
287
|
subr = subrs[index];
|
|
161
288
|
if (subr) {
|
|
162
289
|
usedSubrs[index] = true;
|
|
@@ -171,13 +298,13 @@ export default class CFFGlyph extends Glyph {
|
|
|
171
298
|
break;
|
|
172
299
|
|
|
173
300
|
case 11: // return
|
|
174
|
-
if (
|
|
301
|
+
if ((cffFont.version ?? 0) >= 2) {
|
|
175
302
|
break;
|
|
176
303
|
}
|
|
177
304
|
return;
|
|
178
305
|
|
|
179
306
|
case 14: // endchar
|
|
180
|
-
if (
|
|
307
|
+
if ((cffFont.version ?? 0) >= 2) {
|
|
181
308
|
break;
|
|
182
309
|
}
|
|
183
310
|
|
|
@@ -186,10 +313,10 @@ export default class CFFGlyph extends Glyph {
|
|
|
186
313
|
if (stack.length > 4) {
|
|
187
314
|
checkWidth();
|
|
188
315
|
}
|
|
189
|
-
let a = glyphForName(StandardEncoding[
|
|
190
|
-
let b = glyphForName(StandardEncoding[
|
|
191
|
-
let ady =
|
|
192
|
-
let adx =
|
|
316
|
+
let a = glyphForName(StandardEncoding[popStack()]);
|
|
317
|
+
let b = glyphForName(StandardEncoding[popStack()]);
|
|
318
|
+
let ady = popStack();
|
|
319
|
+
let adx = popStack();
|
|
193
320
|
let pos = stream.pos;
|
|
194
321
|
path.commands = b.path.commands.concat(a.path.translate(adx, ady).commands);
|
|
195
322
|
stream.pos = pos;
|
|
@@ -205,16 +332,16 @@ export default class CFFGlyph extends Glyph {
|
|
|
205
332
|
break;
|
|
206
333
|
|
|
207
334
|
case 15: { // vsindex
|
|
208
|
-
if (
|
|
335
|
+
if ((cffFont.version ?? 0) < 2) {
|
|
209
336
|
throw new Error('vsindex operator not supported in CFF v1');
|
|
210
337
|
}
|
|
211
338
|
|
|
212
|
-
vsindex =
|
|
339
|
+
vsindex = popStack();
|
|
213
340
|
break;
|
|
214
341
|
}
|
|
215
342
|
|
|
216
343
|
case 16: { // blend
|
|
217
|
-
if (
|
|
344
|
+
if ((cffFont.version ?? 0) < 2) {
|
|
218
345
|
throw new Error('blend operator not supported in CFF v1');
|
|
219
346
|
}
|
|
220
347
|
|
|
@@ -222,13 +349,20 @@ export default class CFFGlyph extends Glyph {
|
|
|
222
349
|
throw new Error('blend operator in non-variation font');
|
|
223
350
|
}
|
|
224
351
|
|
|
352
|
+
if (!vstore) {
|
|
353
|
+
throw new Error('blend operator without variation store');
|
|
354
|
+
}
|
|
355
|
+
|
|
225
356
|
let blendVector = variationProcessor.getBlendVector(vstore, vsindex);
|
|
226
|
-
let numBlends =
|
|
357
|
+
let numBlends = popStack();
|
|
227
358
|
let numOperands = numBlends * blendVector.length;
|
|
359
|
+
/** @type {number} */
|
|
228
360
|
let delta = stack.length - numOperands;
|
|
361
|
+
/** @type {number} */
|
|
229
362
|
let base = delta - numBlends;
|
|
230
363
|
|
|
231
364
|
for (let i = 0; i < numBlends; i++) {
|
|
365
|
+
/** @type {number} */
|
|
232
366
|
let sum = stack[base + i];
|
|
233
367
|
for (let j = 0; j < blendVector.length; j++) {
|
|
234
368
|
sum += blendVector[j] * stack[delta++];
|
|
@@ -255,8 +389,8 @@ export default class CFFGlyph extends Glyph {
|
|
|
255
389
|
checkWidth();
|
|
256
390
|
}
|
|
257
391
|
|
|
258
|
-
x +=
|
|
259
|
-
y +=
|
|
392
|
+
x += shiftStack();
|
|
393
|
+
y += shiftStack();
|
|
260
394
|
moveTo(x, y);
|
|
261
395
|
break;
|
|
262
396
|
|
|
@@ -265,69 +399,69 @@ export default class CFFGlyph extends Glyph {
|
|
|
265
399
|
checkWidth();
|
|
266
400
|
}
|
|
267
401
|
|
|
268
|
-
x +=
|
|
402
|
+
x += shiftStack();
|
|
269
403
|
moveTo(x, y);
|
|
270
404
|
break;
|
|
271
405
|
|
|
272
406
|
case 24: // rcurveline
|
|
273
407
|
while (stack.length >= 8) {
|
|
274
|
-
c1x = x +
|
|
275
|
-
c1y = y +
|
|
276
|
-
c2x = c1x +
|
|
277
|
-
c2y = c1y +
|
|
278
|
-
x = c2x +
|
|
279
|
-
y = c2y +
|
|
408
|
+
c1x = x + shiftStack();
|
|
409
|
+
c1y = y + shiftStack();
|
|
410
|
+
c2x = c1x + shiftStack();
|
|
411
|
+
c2y = c1y + shiftStack();
|
|
412
|
+
x = c2x + shiftStack();
|
|
413
|
+
y = c2y + shiftStack();
|
|
280
414
|
path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);
|
|
281
415
|
}
|
|
282
416
|
|
|
283
|
-
x +=
|
|
284
|
-
y +=
|
|
417
|
+
x += shiftStack();
|
|
418
|
+
y += shiftStack();
|
|
285
419
|
path.lineTo(x, y);
|
|
286
420
|
break;
|
|
287
421
|
|
|
288
422
|
case 25: // rlinecurve
|
|
289
423
|
while (stack.length >= 8) {
|
|
290
|
-
x +=
|
|
291
|
-
y +=
|
|
424
|
+
x += shiftStack();
|
|
425
|
+
y += shiftStack();
|
|
292
426
|
path.lineTo(x, y);
|
|
293
427
|
}
|
|
294
428
|
|
|
295
|
-
c1x = x +
|
|
296
|
-
c1y = y +
|
|
297
|
-
c2x = c1x +
|
|
298
|
-
c2y = c1y +
|
|
299
|
-
x = c2x +
|
|
300
|
-
y = c2y +
|
|
429
|
+
c1x = x + shiftStack();
|
|
430
|
+
c1y = y + shiftStack();
|
|
431
|
+
c2x = c1x + shiftStack();
|
|
432
|
+
c2y = c1y + shiftStack();
|
|
433
|
+
x = c2x + shiftStack();
|
|
434
|
+
y = c2y + shiftStack();
|
|
301
435
|
path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);
|
|
302
436
|
break;
|
|
303
437
|
|
|
304
438
|
case 26: // vvcurveto
|
|
305
439
|
if (stack.length % 2) {
|
|
306
|
-
x +=
|
|
440
|
+
x += shiftStack();
|
|
307
441
|
}
|
|
308
442
|
|
|
309
443
|
while (stack.length >= 4) {
|
|
310
444
|
c1x = x;
|
|
311
|
-
c1y = y +
|
|
312
|
-
c2x = c1x +
|
|
313
|
-
c2y = c1y +
|
|
445
|
+
c1y = y + shiftStack();
|
|
446
|
+
c2x = c1x + shiftStack();
|
|
447
|
+
c2y = c1y + shiftStack();
|
|
314
448
|
x = c2x;
|
|
315
|
-
y = c2y +
|
|
449
|
+
y = c2y + shiftStack();
|
|
316
450
|
path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);
|
|
317
451
|
}
|
|
318
452
|
break;
|
|
319
453
|
|
|
320
454
|
case 27: // hhcurveto
|
|
321
455
|
if (stack.length % 2) {
|
|
322
|
-
y +=
|
|
456
|
+
y += shiftStack();
|
|
323
457
|
}
|
|
324
458
|
|
|
325
459
|
while (stack.length >= 4) {
|
|
326
|
-
c1x = x +
|
|
460
|
+
c1x = x + shiftStack();
|
|
327
461
|
c1y = y;
|
|
328
|
-
c2x = c1x +
|
|
329
|
-
c2y = c1y +
|
|
330
|
-
x = c2x +
|
|
462
|
+
c2x = c1x + shiftStack();
|
|
463
|
+
c2y = c1y + shiftStack();
|
|
464
|
+
x = c2x + shiftStack();
|
|
331
465
|
y = c2y;
|
|
332
466
|
path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);
|
|
333
467
|
}
|
|
@@ -338,17 +472,20 @@ export default class CFFGlyph extends Glyph {
|
|
|
338
472
|
break;
|
|
339
473
|
|
|
340
474
|
case 29: // callgsubr
|
|
341
|
-
index =
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
475
|
+
index = popStack() + gsubrsBias;
|
|
476
|
+
{
|
|
477
|
+
let candidate = Array.isArray(gsubrs) ? gsubrs[index] : gsubrs[index];
|
|
478
|
+
if (isCFFCharString(candidate)) {
|
|
479
|
+
subr = candidate;
|
|
480
|
+
usedGsubrs[index] = true;
|
|
481
|
+
let p = stream.pos;
|
|
482
|
+
let e = end;
|
|
483
|
+
stream.pos = subr.offset;
|
|
484
|
+
end = subr.offset + subr.length;
|
|
485
|
+
parse();
|
|
486
|
+
stream.pos = p;
|
|
487
|
+
end = e;
|
|
488
|
+
}
|
|
352
489
|
}
|
|
353
490
|
break;
|
|
354
491
|
|
|
@@ -357,19 +494,19 @@ export default class CFFGlyph extends Glyph {
|
|
|
357
494
|
phase = op === 31;
|
|
358
495
|
while (stack.length >= 4) {
|
|
359
496
|
if (phase) {
|
|
360
|
-
c1x = x +
|
|
497
|
+
c1x = x + shiftStack();
|
|
361
498
|
c1y = y;
|
|
362
|
-
c2x = c1x +
|
|
363
|
-
c2y = c1y +
|
|
364
|
-
y = c2y +
|
|
365
|
-
x = c2x + (stack.length === 1 ?
|
|
499
|
+
c2x = c1x + shiftStack();
|
|
500
|
+
c2y = c1y + shiftStack();
|
|
501
|
+
y = c2y + shiftStack();
|
|
502
|
+
x = c2x + (stack.length === 1 ? shiftStack() : 0);
|
|
366
503
|
} else {
|
|
367
504
|
c1x = x;
|
|
368
|
-
c1y = y +
|
|
369
|
-
c2x = c1x +
|
|
370
|
-
c2y = c1y +
|
|
371
|
-
x = c2x +
|
|
372
|
-
y = c2y + (stack.length === 1 ?
|
|
505
|
+
c1y = y + shiftStack();
|
|
506
|
+
c2x = c1x + shiftStack();
|
|
507
|
+
c2y = c1y + shiftStack();
|
|
508
|
+
x = c2x + shiftStack();
|
|
509
|
+
y = c2y + (stack.length === 1 ? shiftStack() : 0);
|
|
373
510
|
}
|
|
374
511
|
|
|
375
512
|
path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);
|
|
@@ -379,79 +516,80 @@ export default class CFFGlyph extends Glyph {
|
|
|
379
516
|
|
|
380
517
|
case 12: {
|
|
381
518
|
op = stream.readUInt8();
|
|
519
|
+
/** @type {number} */
|
|
382
520
|
let a, b, val, idx;
|
|
383
521
|
switch (op) {
|
|
384
522
|
case 3: // and
|
|
385
|
-
a =
|
|
386
|
-
b =
|
|
523
|
+
a = popStack();
|
|
524
|
+
b = popStack();
|
|
387
525
|
stack.push(a && b ? 1 : 0);
|
|
388
526
|
break;
|
|
389
527
|
|
|
390
528
|
case 4: // or
|
|
391
|
-
a =
|
|
392
|
-
b =
|
|
529
|
+
a = popStack();
|
|
530
|
+
b = popStack();
|
|
393
531
|
stack.push(a || b ? 1 : 0);
|
|
394
532
|
break;
|
|
395
533
|
|
|
396
534
|
case 5: // not
|
|
397
|
-
a =
|
|
535
|
+
a = popStack();
|
|
398
536
|
stack.push(a ? 0 : 1);
|
|
399
537
|
break;
|
|
400
538
|
|
|
401
539
|
case 9: // abs
|
|
402
|
-
a =
|
|
540
|
+
a = popStack();
|
|
403
541
|
stack.push(Math.abs(a));
|
|
404
542
|
break;
|
|
405
543
|
|
|
406
544
|
case 10: // add
|
|
407
|
-
a =
|
|
408
|
-
b =
|
|
545
|
+
a = popStack();
|
|
546
|
+
b = popStack();
|
|
409
547
|
stack.push(a + b);
|
|
410
548
|
break;
|
|
411
549
|
|
|
412
550
|
case 11: // sub
|
|
413
|
-
a =
|
|
414
|
-
b =
|
|
551
|
+
a = popStack();
|
|
552
|
+
b = popStack();
|
|
415
553
|
stack.push(a - b);
|
|
416
554
|
break;
|
|
417
555
|
|
|
418
556
|
case 12: // div
|
|
419
|
-
a =
|
|
420
|
-
b =
|
|
557
|
+
a = popStack();
|
|
558
|
+
b = popStack();
|
|
421
559
|
stack.push(a / b);
|
|
422
560
|
break;
|
|
423
561
|
|
|
424
562
|
case 14: // neg
|
|
425
|
-
a =
|
|
563
|
+
a = popStack();
|
|
426
564
|
stack.push(-a);
|
|
427
565
|
break;
|
|
428
566
|
|
|
429
567
|
case 15: // eq
|
|
430
|
-
a =
|
|
431
|
-
b =
|
|
568
|
+
a = popStack();
|
|
569
|
+
b = popStack();
|
|
432
570
|
stack.push(a === b ? 1 : 0);
|
|
433
571
|
break;
|
|
434
572
|
|
|
435
573
|
case 18: // drop
|
|
436
|
-
|
|
574
|
+
popStack();
|
|
437
575
|
break;
|
|
438
576
|
|
|
439
577
|
case 20: // put
|
|
440
|
-
val =
|
|
441
|
-
idx =
|
|
578
|
+
val = popStack();
|
|
579
|
+
idx = popStack();
|
|
442
580
|
trans[idx] = val;
|
|
443
581
|
break;
|
|
444
582
|
|
|
445
583
|
case 21: // get
|
|
446
|
-
idx =
|
|
584
|
+
idx = popStack();
|
|
447
585
|
stack.push(trans[idx] || 0);
|
|
448
586
|
break;
|
|
449
587
|
|
|
450
588
|
case 22: { // ifelse
|
|
451
|
-
let s1 =
|
|
452
|
-
let s2 =
|
|
453
|
-
let v1 =
|
|
454
|
-
let v2 =
|
|
589
|
+
let s1 = popStack();
|
|
590
|
+
let s2 = popStack();
|
|
591
|
+
let v1 = popStack();
|
|
592
|
+
let v2 = popStack();
|
|
455
593
|
stack.push(v1 <= v2 ? s1 : s2);
|
|
456
594
|
break;
|
|
457
595
|
}
|
|
@@ -461,29 +599,29 @@ export default class CFFGlyph extends Glyph {
|
|
|
461
599
|
break;
|
|
462
600
|
|
|
463
601
|
case 24: // mul
|
|
464
|
-
a =
|
|
465
|
-
b =
|
|
602
|
+
a = popStack();
|
|
603
|
+
b = popStack();
|
|
466
604
|
stack.push(a * b);
|
|
467
605
|
break;
|
|
468
606
|
|
|
469
607
|
case 26: // sqrt
|
|
470
|
-
a =
|
|
608
|
+
a = popStack();
|
|
471
609
|
stack.push(Math.sqrt(a));
|
|
472
610
|
break;
|
|
473
611
|
|
|
474
612
|
case 27: // dup
|
|
475
|
-
a =
|
|
613
|
+
a = popStack();
|
|
476
614
|
stack.push(a, a);
|
|
477
615
|
break;
|
|
478
616
|
|
|
479
617
|
case 28: // exch
|
|
480
|
-
a =
|
|
481
|
-
b =
|
|
618
|
+
a = popStack();
|
|
619
|
+
b = popStack();
|
|
482
620
|
stack.push(b, a);
|
|
483
621
|
break;
|
|
484
622
|
|
|
485
623
|
case 29: // index
|
|
486
|
-
idx =
|
|
624
|
+
idx = popStack();
|
|
487
625
|
if (idx < 0) {
|
|
488
626
|
idx = 0;
|
|
489
627
|
} else if (idx > stack.length - 1) {
|
|
@@ -494,13 +632,16 @@ export default class CFFGlyph extends Glyph {
|
|
|
494
632
|
break;
|
|
495
633
|
|
|
496
634
|
case 30: { // roll
|
|
497
|
-
|
|
498
|
-
let
|
|
635
|
+
/** @type {number} */
|
|
636
|
+
let n = popStack();
|
|
637
|
+
/** @type {number} */
|
|
638
|
+
let j = popStack();
|
|
499
639
|
|
|
500
640
|
if (j >= 0) {
|
|
501
641
|
while (j > 0) {
|
|
642
|
+
/** @type {number} */
|
|
502
643
|
let t = stack[n - 1];
|
|
503
|
-
for (let i = n - 2; i >= 0; i--) {
|
|
644
|
+
for (/** @type {number} */ let i = n - 2; i >= 0; i--) {
|
|
504
645
|
stack[i + 1] = stack[i];
|
|
505
646
|
}
|
|
506
647
|
|
|
@@ -509,8 +650,9 @@ export default class CFFGlyph extends Glyph {
|
|
|
509
650
|
}
|
|
510
651
|
} else {
|
|
511
652
|
while (j < 0) {
|
|
653
|
+
/** @type {number} */
|
|
512
654
|
let t = stack[0];
|
|
513
|
-
for (let i = 0; i <= n; i++) {
|
|
655
|
+
for (/** @type {number} */ let i = 0; i <= n; i++) {
|
|
514
656
|
stack[i] = stack[i + 1];
|
|
515
657
|
}
|
|
516
658
|
|
|
@@ -522,17 +664,17 @@ export default class CFFGlyph extends Glyph {
|
|
|
522
664
|
}
|
|
523
665
|
|
|
524
666
|
case 34: // hflex
|
|
525
|
-
c1x = x +
|
|
667
|
+
c1x = x + shiftStack();
|
|
526
668
|
c1y = y;
|
|
527
|
-
c2x = c1x +
|
|
528
|
-
c2y = c1y +
|
|
529
|
-
c3x = c2x +
|
|
669
|
+
c2x = c1x + shiftStack();
|
|
670
|
+
c2y = c1y + shiftStack();
|
|
671
|
+
c3x = c2x + shiftStack();
|
|
530
672
|
c3y = c2y;
|
|
531
|
-
c4x = c3x +
|
|
673
|
+
c4x = c3x + shiftStack();
|
|
532
674
|
c4y = c3y;
|
|
533
|
-
c5x = c4x +
|
|
675
|
+
c5x = c4x + shiftStack();
|
|
534
676
|
c5y = c4y;
|
|
535
|
-
c6x = c5x +
|
|
677
|
+
c6x = c5x + shiftStack();
|
|
536
678
|
c6y = c5y;
|
|
537
679
|
x = c6x;
|
|
538
680
|
y = c6y;
|
|
@@ -545,28 +687,28 @@ export default class CFFGlyph extends Glyph {
|
|
|
545
687
|
pts = [];
|
|
546
688
|
|
|
547
689
|
for (let i = 0; i <= 5; i++) {
|
|
548
|
-
x +=
|
|
549
|
-
y +=
|
|
690
|
+
x += shiftStack();
|
|
691
|
+
y += shiftStack();
|
|
550
692
|
pts.push(x, y);
|
|
551
693
|
}
|
|
552
694
|
|
|
553
|
-
path.bezierCurveTo(
|
|
554
|
-
path.bezierCurveTo(
|
|
555
|
-
|
|
695
|
+
path.bezierCurveTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
|
|
696
|
+
path.bezierCurveTo(pts[6], pts[7], pts[8], pts[9], pts[10], pts[11]);
|
|
697
|
+
shiftStack(); // fd
|
|
556
698
|
break;
|
|
557
699
|
|
|
558
700
|
case 36: // hflex1
|
|
559
|
-
c1x = x +
|
|
560
|
-
c1y = y +
|
|
561
|
-
c2x = c1x +
|
|
562
|
-
c2y = c1y +
|
|
563
|
-
c3x = c2x +
|
|
701
|
+
c1x = x + shiftStack();
|
|
702
|
+
c1y = y + shiftStack();
|
|
703
|
+
c2x = c1x + shiftStack();
|
|
704
|
+
c2y = c1y + shiftStack();
|
|
705
|
+
c3x = c2x + shiftStack();
|
|
564
706
|
c3y = c2y;
|
|
565
|
-
c4x = c3x +
|
|
707
|
+
c4x = c3x + shiftStack();
|
|
566
708
|
c4y = c3y;
|
|
567
|
-
c5x = c4x +
|
|
568
|
-
c5y = c4y +
|
|
569
|
-
c6x = c5x +
|
|
709
|
+
c5x = c4x + shiftStack();
|
|
710
|
+
c5y = c4y + shiftStack();
|
|
711
|
+
c6x = c5x + shiftStack();
|
|
570
712
|
c6y = c5y;
|
|
571
713
|
x = c6x;
|
|
572
714
|
y = c6y;
|
|
@@ -581,22 +723,22 @@ export default class CFFGlyph extends Glyph {
|
|
|
581
723
|
|
|
582
724
|
pts = [];
|
|
583
725
|
for (let i = 0; i <= 4; i++) {
|
|
584
|
-
x +=
|
|
585
|
-
y +=
|
|
726
|
+
x += shiftStack();
|
|
727
|
+
y += shiftStack();
|
|
586
728
|
pts.push(x, y);
|
|
587
729
|
}
|
|
588
730
|
|
|
589
731
|
if (Math.abs(x - startx) > Math.abs(y - starty)) { // horizontal
|
|
590
|
-
x +=
|
|
732
|
+
x += shiftStack();
|
|
591
733
|
y = starty;
|
|
592
734
|
} else {
|
|
593
735
|
x = startx;
|
|
594
|
-
y +=
|
|
736
|
+
y += shiftStack();
|
|
595
737
|
}
|
|
596
738
|
|
|
597
739
|
pts.push(x, y);
|
|
598
|
-
path.bezierCurveTo(
|
|
599
|
-
path.bezierCurveTo(
|
|
740
|
+
path.bezierCurveTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
|
|
741
|
+
path.bezierCurveTo(pts[6], pts[7], pts[8], pts[9], pts[10], pts[11]);
|
|
600
742
|
break;
|
|
601
743
|
}
|
|
602
744
|
|