@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/TTFFont.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cache } from './decorators';
|
|
2
2
|
import * as fontkit from './base';
|
|
3
|
+
import * as r from 'restructure';
|
|
3
4
|
import Directory from './tables/directory';
|
|
4
5
|
import tables from './tables';
|
|
5
6
|
import CmapProcessor from './CmapProcessor';
|
|
@@ -15,18 +16,114 @@ import CFFSubset from './subset/CFFSubset';
|
|
|
15
16
|
import BBox from './glyph/BBox';
|
|
16
17
|
import { asciiDecoder } from './utils';
|
|
17
18
|
|
|
19
|
+
/** @typedef {import('restructure').DecodeStream} DecodeStream */
|
|
20
|
+
/** @typedef {import('restructure').BinaryBuffer} BinaryBuffer */
|
|
21
|
+
/** @typedef {import('../types/fontkit').FontDirectory} FontDirectory */
|
|
22
|
+
/** @typedef {import('../types/fontkit').FontLike} FontLike */
|
|
23
|
+
/** @typedef {import('../types/fontkit').FontMetrics} FontMetrics */
|
|
24
|
+
/** @typedef {import('../types/fontkit').TableEntry} TableEntry */
|
|
25
|
+
/** @typedef {import('../types/fontkit').TableCodec} TableCodec */
|
|
26
|
+
/** @typedef {import('../types/fontkit').VariationCoords} VariationCoords */
|
|
27
|
+
/** @typedef {import('../types/fontkit').NameString} NameString */
|
|
28
|
+
/** @typedef {import('../types/fontkit').HeadTable} HeadTable */
|
|
29
|
+
/** @typedef {import('../types/fontkit').HheaTable} HheaTable */
|
|
30
|
+
/** @typedef {import('../types/fontkit').MaxpTable} MaxpTable */
|
|
31
|
+
/** @typedef {import('../types/fontkit').OS2Table} OS2Table */
|
|
32
|
+
/** @typedef {import('../types/fontkit').NameTable} NameTable */
|
|
33
|
+
/** @typedef {import('../types/fontkit').PostTable} PostTable */
|
|
34
|
+
/** @typedef {import('../types/fontkit').CmapTable} CmapTable */
|
|
35
|
+
/** @typedef {import('../types/fontkit').MetricsTable} MetricsTable */
|
|
36
|
+
/** @typedef {import('../types/fontkit').FvarTable} FvarTable */
|
|
37
|
+
/** @typedef {import('../types/fontkit').FvarAxis} FvarAxis */
|
|
38
|
+
/** @typedef {import('../types/fontkit').CFFFontLike} CFFFontLike */
|
|
39
|
+
/** @typedef {import('../types/fontkit').FeatureInput} FeatureInput */
|
|
40
|
+
/** @typedef {import('../types/fontkit').ScriptTag} ScriptTag */
|
|
41
|
+
/** @typedef {import('../types/fontkit').LanguageTag} LanguageTag */
|
|
42
|
+
/** @typedef {import('../types/fontkit').TextDirection} TextDirection */
|
|
43
|
+
/** @typedef {import('./glyph/Glyph').default} Glyph */
|
|
44
|
+
/** @typedef {import('./layout/GlyphRun').default} GlyphRun */
|
|
45
|
+
/** @typedef {import('./subset/Subset').default} Subset */
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Axis description from {@link TTFFont#variationAxes}.
|
|
49
|
+
* @typedef {{ name: NameString | undefined, min: number, default: number, max: number }} VariationAxisInfo
|
|
50
|
+
*/
|
|
51
|
+
|
|
18
52
|
/**
|
|
19
53
|
* This is the base class for all SFNT-based font formats in fontkit.
|
|
20
54
|
* It supports TrueType, and PostScript glyphs, and several color glyph formats.
|
|
55
|
+
*
|
|
56
|
+
* Dynamic SFNT table accessors (`cmap`, `head`, `hhea`, …) are installed by
|
|
57
|
+
* `_installTableGetters` and typed here so call sites see real table shapes.
|
|
58
|
+
*
|
|
59
|
+
* @implements {FontLike}
|
|
21
60
|
*/
|
|
22
61
|
export default class TTFFont {
|
|
62
|
+
/** @type {string} */
|
|
23
63
|
type = 'TTF';
|
|
24
64
|
|
|
65
|
+
/** @type {DecodeStream} */
|
|
66
|
+
stream = new r.DecodeStream(new Uint8Array(0));
|
|
67
|
+
/** @type {FontDirectory} */
|
|
68
|
+
directory = /** @type {FontDirectory} */ ({ tables: {} });
|
|
69
|
+
/** @type {string | null} */
|
|
70
|
+
defaultLanguage = null;
|
|
71
|
+
/** @type {number[] | null} */
|
|
72
|
+
variationCoords = null;
|
|
73
|
+
/** @type {number} */
|
|
74
|
+
_directoryPos = 0;
|
|
75
|
+
/** @type {Record<string, unknown>} */
|
|
76
|
+
_tables = {};
|
|
77
|
+
/** @type {Record<number, Glyph | undefined>} */
|
|
78
|
+
_glyphs = {};
|
|
79
|
+
/** @type {FontMetrics | undefined} */
|
|
80
|
+
_metrics;
|
|
81
|
+
|
|
82
|
+
// SFNT tables installed as configurable getters by `_installTableGetters`.
|
|
83
|
+
/** @type {CmapTable | undefined} */
|
|
84
|
+
cmap;
|
|
85
|
+
/** @type {HeadTable} */
|
|
86
|
+
head = /** @type {HeadTable} */ ({ unitsPerEm: 0, xMin: 0, yMin: 0, xMax: 0, yMax: 0 });
|
|
87
|
+
/** @type {HheaTable | undefined} */
|
|
88
|
+
hhea;
|
|
89
|
+
/** @type {MetricsTable} */
|
|
90
|
+
hmtx = /** @type {MetricsTable} */ ({
|
|
91
|
+
metrics: { length: 0, get() { return undefined; } },
|
|
92
|
+
bearings: { length: 0, get() { return undefined; } }
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
/** @type {MaxpTable} */
|
|
96
|
+
maxp = { numGlyphs: 0 };
|
|
97
|
+
/** @type {NameTable | undefined} */
|
|
98
|
+
name;
|
|
99
|
+
/** @type {OS2Table | undefined} */
|
|
100
|
+
'OS/2';
|
|
101
|
+
/** @type {PostTable} */
|
|
102
|
+
post = { version: 0, italicAngle: 0, underlinePosition: 0, underlineThickness: 0 };
|
|
103
|
+
/** @type {FvarTable | undefined} */
|
|
104
|
+
fvar;
|
|
105
|
+
/** @type {CFFFontLike | undefined} */
|
|
106
|
+
CFF2;
|
|
107
|
+
/** @type {CFFFontLike | undefined} */
|
|
108
|
+
'CFF ';
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @param {ArrayBufferView} buffer
|
|
112
|
+
* @returns {boolean}
|
|
113
|
+
*/
|
|
25
114
|
static probe(buffer) {
|
|
26
|
-
let
|
|
115
|
+
let bytes
|
|
116
|
+
= buffer instanceof Uint8Array
|
|
117
|
+
? buffer
|
|
118
|
+
: new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
119
|
+
let format = asciiDecoder.decode(bytes.subarray(0, 4));
|
|
27
120
|
return format === 'true' || format === 'OTTO' || format === String.fromCharCode(0, 1, 0, 0);
|
|
28
121
|
}
|
|
29
122
|
|
|
123
|
+
/**
|
|
124
|
+
* @param {DecodeStream} stream
|
|
125
|
+
* @param {number[] | null} [variationCoords]
|
|
126
|
+
*/
|
|
30
127
|
constructor(stream, variationCoords = null) {
|
|
31
128
|
this.defaultLanguage = null;
|
|
32
129
|
this.stream = stream;
|
|
@@ -35,14 +132,28 @@ export default class TTFFont {
|
|
|
35
132
|
this._directoryPos = this.stream.pos;
|
|
36
133
|
this._tables = {};
|
|
37
134
|
this._glyphs = {};
|
|
135
|
+
this._metrics = undefined;
|
|
136
|
+
this.directory = /** @type {FontDirectory} */ ({ tables: {} });
|
|
137
|
+
|
|
38
138
|
this._decodeDirectory();
|
|
39
139
|
this._installTableGetters();
|
|
40
140
|
}
|
|
41
141
|
|
|
142
|
+
/**
|
|
143
|
+
* @param {DecodeStream} stream
|
|
144
|
+
* @returns {void}
|
|
145
|
+
*/
|
|
146
|
+
_setStream(stream) {
|
|
147
|
+
this.stream = stream;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** @returns {void} */
|
|
42
151
|
_installTableGetters() {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
152
|
+
let tableMap = this.directory.tables;
|
|
153
|
+
for (let tag in tableMap) {
|
|
154
|
+
let table = tableMap[tag];
|
|
155
|
+
let codec = tables[tag];
|
|
156
|
+
if (codec && table && table.length > 0) {
|
|
46
157
|
Object.defineProperty(this, tag, {
|
|
47
158
|
get: this._getTable.bind(this, table),
|
|
48
159
|
configurable: true
|
|
@@ -51,10 +162,18 @@ export default class TTFFont {
|
|
|
51
162
|
}
|
|
52
163
|
}
|
|
53
164
|
|
|
165
|
+
/**
|
|
166
|
+
* @param {string | null} [lang]
|
|
167
|
+
* @returns {void}
|
|
168
|
+
*/
|
|
54
169
|
setDefaultLanguage(lang = null) {
|
|
55
170
|
this.defaultLanguage = lang;
|
|
56
171
|
}
|
|
57
172
|
|
|
173
|
+
/**
|
|
174
|
+
* @param {TableEntry} table
|
|
175
|
+
* @returns {unknown}
|
|
176
|
+
*/
|
|
58
177
|
_getTable(table) {
|
|
59
178
|
if (!(table.tag in this._tables)) {
|
|
60
179
|
try {
|
|
@@ -62,7 +181,8 @@ export default class TTFFont {
|
|
|
62
181
|
} catch (e) {
|
|
63
182
|
if (fontkit.logErrors) {
|
|
64
183
|
console.error(`Error decoding table ${table.tag}`);
|
|
65
|
-
|
|
184
|
+
let err = /** @type {{ stack?: string }} */ (e);
|
|
185
|
+
console.error(err.stack);
|
|
66
186
|
}
|
|
67
187
|
}
|
|
68
188
|
}
|
|
@@ -70,6 +190,10 @@ export default class TTFFont {
|
|
|
70
190
|
return this._tables[table.tag];
|
|
71
191
|
}
|
|
72
192
|
|
|
193
|
+
/**
|
|
194
|
+
* @param {string} tag
|
|
195
|
+
* @returns {DecodeStream | null}
|
|
196
|
+
*/
|
|
73
197
|
_getTableStream(tag) {
|
|
74
198
|
let table = this.directory.tables[tag];
|
|
75
199
|
if (table) {
|
|
@@ -80,20 +204,36 @@ export default class TTFFont {
|
|
|
80
204
|
return null;
|
|
81
205
|
}
|
|
82
206
|
|
|
207
|
+
/** @returns {void} */
|
|
83
208
|
_decodeDirectory() {
|
|
84
|
-
|
|
209
|
+
this.directory = /** @type {FontDirectory} */ (
|
|
210
|
+
/** @type {unknown} */ (Directory.decode(this.stream, { _startOffset: 0 }))
|
|
211
|
+
);
|
|
85
212
|
}
|
|
86
213
|
|
|
214
|
+
/**
|
|
215
|
+
* @param {TableEntry} table
|
|
216
|
+
* @returns {unknown}
|
|
217
|
+
*/
|
|
87
218
|
_decodeTable(table) {
|
|
88
219
|
let pos = this.stream.pos;
|
|
89
220
|
|
|
90
221
|
let stream = this._getTableStream(table.tag);
|
|
91
|
-
let
|
|
222
|
+
let codec = /** @type {TableCodec | undefined} */ (tables[table.tag]);
|
|
223
|
+
if (!stream || !codec || !codec.decode) {
|
|
224
|
+
this.stream.pos = pos;
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
let result = codec.decode(stream, this, table.length);
|
|
92
229
|
|
|
93
230
|
this.stream.pos = pos;
|
|
94
231
|
return result;
|
|
95
232
|
}
|
|
96
233
|
|
|
234
|
+
/**
|
|
235
|
+
* @returns {FontMetrics}
|
|
236
|
+
*/
|
|
97
237
|
_getMetrics() {
|
|
98
238
|
if (this._metrics) {
|
|
99
239
|
return this._metrics;
|
|
@@ -103,21 +243,34 @@ export default class TTFFont {
|
|
|
103
243
|
// https://gitlab.freedesktop.org/freetype/freetype/-/blob/master/src/sfnt/sfobjs.c
|
|
104
244
|
// typo*/win* fields exist only in OS/2 version >= 1
|
|
105
245
|
let os2 = this['OS/2'];
|
|
106
|
-
let hasTypo = os2 && os2.version > 0;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
246
|
+
let hasTypo = !!(os2 && os2.version > 0);
|
|
247
|
+
/** @type {number} */
|
|
248
|
+
let ascent;
|
|
249
|
+
/** @type {number} */
|
|
250
|
+
let descent;
|
|
251
|
+
/** @type {number} */
|
|
252
|
+
let lineGap;
|
|
253
|
+
|
|
254
|
+
if (hasTypo && os2 && os2.fsSelection.useTypoMetrics) {
|
|
255
|
+
ascent = /** @type {number} */ (os2.typoAscender);
|
|
256
|
+
descent = /** @type {number} */ (os2.typoDescender);
|
|
257
|
+
lineGap = /** @type {number} */ (os2.typoLineGap);
|
|
111
258
|
} else {
|
|
112
|
-
|
|
259
|
+
let hhea = this.hhea;
|
|
260
|
+
if (!hhea) {
|
|
261
|
+
throw new Error('Missing hhea table');
|
|
262
|
+
}
|
|
263
|
+
({ ascent, descent, lineGap } = hhea);
|
|
113
264
|
|
|
114
265
|
// Only when both hhea values are zero — FreeType uses !(ascender || descender)
|
|
115
|
-
if (!(ascent || descent) && hasTypo) {
|
|
266
|
+
if (!(ascent || descent) && hasTypo && os2) {
|
|
116
267
|
if (os2.typoAscender || os2.typoDescender) {
|
|
117
|
-
|
|
268
|
+
ascent = /** @type {number} */ (os2.typoAscender);
|
|
269
|
+
descent = /** @type {number} */ (os2.typoDescender);
|
|
270
|
+
lineGap = /** @type {number} */ (os2.typoLineGap);
|
|
118
271
|
} else {
|
|
119
|
-
ascent = os2.winAscent;
|
|
120
|
-
descent = -os2.winDescent;
|
|
272
|
+
ascent = /** @type {number} */ (os2.winAscent);
|
|
273
|
+
descent = -(/** @type {number} */ (os2.winDescent));
|
|
121
274
|
lineGap = 0;
|
|
122
275
|
}
|
|
123
276
|
}
|
|
@@ -134,18 +287,22 @@ export default class TTFFont {
|
|
|
134
287
|
/**
|
|
135
288
|
* Gets a string from the font's `name` table
|
|
136
289
|
* `lang` is a BCP-47 language code.
|
|
137
|
-
* @
|
|
290
|
+
* @param {string} key
|
|
291
|
+
* @param {string | null} [lang]
|
|
292
|
+
* @returns {NameString | null}
|
|
138
293
|
*/
|
|
139
294
|
getName(key, lang = this.defaultLanguage || fontkit.defaultLanguage) {
|
|
140
295
|
let record = this.name && this.name.records[key];
|
|
141
|
-
if (record) {
|
|
296
|
+
if (record && typeof record === 'object') {
|
|
142
297
|
// Attempt to retrieve the entry, depending on which translation is available:
|
|
298
|
+
/** @type {import('../types/fontkit').NameLocaleMap} */
|
|
299
|
+
let locales = /** @type {import('../types/fontkit').NameLocaleMap} */ (record);
|
|
143
300
|
return (
|
|
144
|
-
|
|
145
|
-
||
|
|
146
|
-
||
|
|
147
|
-
||
|
|
148
|
-
||
|
|
301
|
+
(lang ? locales[lang] : undefined)
|
|
302
|
+
|| (this.defaultLanguage ? locales[this.defaultLanguage] : undefined)
|
|
303
|
+
|| locales[fontkit.defaultLanguage]
|
|
304
|
+
|| locales['en']
|
|
305
|
+
|| locales[Object.keys(locales)[0]] // Seriously, ANY language would be fine
|
|
149
306
|
|| null
|
|
150
307
|
);
|
|
151
308
|
}
|
|
@@ -155,7 +312,7 @@ export default class TTFFont {
|
|
|
155
312
|
|
|
156
313
|
/**
|
|
157
314
|
* The unique PostScript name for this font, e.g. "Helvetica-Bold"
|
|
158
|
-
* @type {
|
|
315
|
+
* @type {NameString | null}
|
|
159
316
|
*/
|
|
160
317
|
get postscriptName() {
|
|
161
318
|
return this.getName('postscriptName');
|
|
@@ -163,7 +320,7 @@ export default class TTFFont {
|
|
|
163
320
|
|
|
164
321
|
/**
|
|
165
322
|
* The font's full name, e.g. "Helvetica Bold"
|
|
166
|
-
* @type {
|
|
323
|
+
* @type {NameString | null}
|
|
167
324
|
*/
|
|
168
325
|
get fullName() {
|
|
169
326
|
return this.getName('fullName');
|
|
@@ -171,7 +328,7 @@ export default class TTFFont {
|
|
|
171
328
|
|
|
172
329
|
/**
|
|
173
330
|
* The font's family name, e.g. "Helvetica"
|
|
174
|
-
* @type {
|
|
331
|
+
* @type {NameString | null}
|
|
175
332
|
*/
|
|
176
333
|
get familyName() {
|
|
177
334
|
return this.getName('fontFamily');
|
|
@@ -179,7 +336,7 @@ export default class TTFFont {
|
|
|
179
336
|
|
|
180
337
|
/**
|
|
181
338
|
* The font's sub-family, e.g. "Bold".
|
|
182
|
-
* @type {
|
|
339
|
+
* @type {NameString | null}
|
|
183
340
|
*/
|
|
184
341
|
get subfamilyName() {
|
|
185
342
|
return this.getName('fontSubfamily');
|
|
@@ -187,7 +344,7 @@ export default class TTFFont {
|
|
|
187
344
|
|
|
188
345
|
/**
|
|
189
346
|
* The font's copyright information
|
|
190
|
-
* @type {
|
|
347
|
+
* @type {NameString | null}
|
|
191
348
|
*/
|
|
192
349
|
get copyright() {
|
|
193
350
|
return this.getName('copyright');
|
|
@@ -195,7 +352,7 @@ export default class TTFFont {
|
|
|
195
352
|
|
|
196
353
|
/**
|
|
197
354
|
* The font's version number
|
|
198
|
-
* @type {
|
|
355
|
+
* @type {NameString | null}
|
|
199
356
|
*/
|
|
200
357
|
get version() {
|
|
201
358
|
return this.getName('version');
|
|
@@ -265,7 +422,7 @@ export default class TTFFont {
|
|
|
265
422
|
*/
|
|
266
423
|
get capHeight() {
|
|
267
424
|
let os2 = this['OS/2'];
|
|
268
|
-
return os2 ? os2.capHeight : this.ascent;
|
|
425
|
+
return os2 && os2.capHeight != null ? os2.capHeight : this.ascent;
|
|
269
426
|
}
|
|
270
427
|
|
|
271
428
|
/**
|
|
@@ -275,7 +432,7 @@ export default class TTFFont {
|
|
|
275
432
|
*/
|
|
276
433
|
get xHeight() {
|
|
277
434
|
let os2 = this['OS/2'];
|
|
278
|
-
return os2 ? os2.xHeight : 0;
|
|
435
|
+
return os2 && os2.xHeight != null ? os2.xHeight : 0;
|
|
279
436
|
}
|
|
280
437
|
|
|
281
438
|
/**
|
|
@@ -303,9 +460,12 @@ export default class TTFFont {
|
|
|
303
460
|
return Object.freeze(new BBox(this.head.xMin, this.head.yMin, this.head.xMax, this.head.yMax));
|
|
304
461
|
}
|
|
305
462
|
|
|
463
|
+
/**
|
|
464
|
+
* @type {CmapProcessor}
|
|
465
|
+
*/
|
|
306
466
|
@cache
|
|
307
467
|
get _cmapProcessor() {
|
|
308
|
-
return new CmapProcessor(this.cmap);
|
|
468
|
+
return new CmapProcessor(/** @type {CmapTable} */ (this.cmap));
|
|
309
469
|
}
|
|
310
470
|
|
|
311
471
|
/**
|
|
@@ -332,7 +492,7 @@ export default class TTFFont {
|
|
|
332
492
|
* Does not perform any advanced substitutions (there is no context to do so).
|
|
333
493
|
*
|
|
334
494
|
* @param {number} codePoint
|
|
335
|
-
* @return {Glyph}
|
|
495
|
+
* @return {Glyph | null}
|
|
336
496
|
*/
|
|
337
497
|
glyphForCodePoint(codePoint) {
|
|
338
498
|
return this.getGlyph(this._cmapProcessor.lookup(codePoint), [codePoint]);
|
|
@@ -348,6 +508,7 @@ export default class TTFFont {
|
|
|
348
508
|
* @return {Glyph[]}
|
|
349
509
|
*/
|
|
350
510
|
glyphsForString(string) {
|
|
511
|
+
/** @type {Glyph[]} */
|
|
351
512
|
let glyphs = [];
|
|
352
513
|
let len = string.length;
|
|
353
514
|
let idx = 0;
|
|
@@ -377,10 +538,16 @@ export default class TTFFont {
|
|
|
377
538
|
|
|
378
539
|
if (state === 0 && nextState === 1) {
|
|
379
540
|
// Variation selector following normal codepoint.
|
|
380
|
-
|
|
541
|
+
let g = this.getGlyph(this._cmapProcessor.lookup(last, code), [last, code]);
|
|
542
|
+
if (g) {
|
|
543
|
+
glyphs.push(g);
|
|
544
|
+
}
|
|
381
545
|
} else if (state === 0 && nextState === 0) {
|
|
382
546
|
// Normal codepoint following normal codepoint.
|
|
383
|
-
|
|
547
|
+
let g = this.glyphForCodePoint(last);
|
|
548
|
+
if (g) {
|
|
549
|
+
glyphs.push(g);
|
|
550
|
+
}
|
|
384
551
|
}
|
|
385
552
|
|
|
386
553
|
last = code;
|
|
@@ -390,6 +557,9 @@ export default class TTFFont {
|
|
|
390
557
|
return glyphs;
|
|
391
558
|
}
|
|
392
559
|
|
|
560
|
+
/**
|
|
561
|
+
* @type {LayoutEngine}
|
|
562
|
+
*/
|
|
393
563
|
@cache
|
|
394
564
|
get _layoutEngine() {
|
|
395
565
|
return new LayoutEngine(this);
|
|
@@ -399,10 +569,10 @@ export default class TTFFont {
|
|
|
399
569
|
* Returns a GlyphRun object, which includes an array of Glyphs and GlyphPositions for the given string.
|
|
400
570
|
*
|
|
401
571
|
* @param {string} string
|
|
402
|
-
* @param {
|
|
403
|
-
* @param {
|
|
404
|
-
* @param {
|
|
405
|
-
* @param {
|
|
572
|
+
* @param {FeatureInput} [userFeatures]
|
|
573
|
+
* @param {ScriptTag} [script]
|
|
574
|
+
* @param {LanguageTag} [language]
|
|
575
|
+
* @param {TextDirection} [direction]
|
|
406
576
|
* @return {GlyphRun}
|
|
407
577
|
*/
|
|
408
578
|
layout(string, userFeatures, script, language, direction) {
|
|
@@ -412,6 +582,7 @@ export default class TTFFont {
|
|
|
412
582
|
/**
|
|
413
583
|
* Returns an array of strings that map to the given glyph id.
|
|
414
584
|
* @param {number} gid - glyph id
|
|
585
|
+
* @returns {string[]}
|
|
415
586
|
*/
|
|
416
587
|
stringsForGlyph(gid) {
|
|
417
588
|
return this._layoutEngine.stringsForGlyph(gid);
|
|
@@ -429,16 +600,27 @@ export default class TTFFont {
|
|
|
429
600
|
return this._layoutEngine.getAvailableFeatures();
|
|
430
601
|
}
|
|
431
602
|
|
|
603
|
+
/**
|
|
604
|
+
* @param {ScriptTag} [script]
|
|
605
|
+
* @param {LanguageTag} [language]
|
|
606
|
+
* @returns {string[]}
|
|
607
|
+
*/
|
|
432
608
|
getAvailableFeatures(script, language) {
|
|
433
609
|
return this._layoutEngine.getAvailableFeatures(script, language);
|
|
434
610
|
}
|
|
435
611
|
|
|
612
|
+
/**
|
|
613
|
+
* @param {number} glyph
|
|
614
|
+
* @param {number[]} [characters]
|
|
615
|
+
* @returns {Glyph | null | undefined}
|
|
616
|
+
*/
|
|
436
617
|
_getBaseGlyph(glyph, characters = []) {
|
|
437
618
|
let cached = this._glyphs[glyph];
|
|
438
|
-
if (cached
|
|
619
|
+
if (cached && typeof (/** @type {{ _getContours?: unknown }} */ (cached))._getContours === 'function') {
|
|
439
620
|
return cached;
|
|
440
621
|
}
|
|
441
622
|
|
|
623
|
+
/** @type {Glyph | null} */
|
|
442
624
|
let outline = null;
|
|
443
625
|
if (this.directory.tables.glyf) {
|
|
444
626
|
outline = new TTFGlyph(glyph, characters, this);
|
|
@@ -459,8 +641,8 @@ export default class TTFFont {
|
|
|
459
641
|
* your use later, and it will be stored in the glyph object.
|
|
460
642
|
*
|
|
461
643
|
* @param {number} glyph
|
|
462
|
-
* @param {number[]} characters
|
|
463
|
-
* @return {Glyph}
|
|
644
|
+
* @param {number[]} [characters]
|
|
645
|
+
* @return {Glyph | null}
|
|
464
646
|
*/
|
|
465
647
|
getGlyph(glyph, characters = []) {
|
|
466
648
|
if (!this._glyphs[glyph]) {
|
|
@@ -495,10 +677,11 @@ export default class TTFFont {
|
|
|
495
677
|
* that this font supports. Keys are setting tags, and values
|
|
496
678
|
* contain the axis name, range, and default value.
|
|
497
679
|
*
|
|
498
|
-
* @type {
|
|
680
|
+
* @type {Record<string, VariationAxisInfo>}
|
|
499
681
|
*/
|
|
500
682
|
@cache
|
|
501
683
|
get variationAxes() {
|
|
684
|
+
/** @type {Record<string, VariationAxisInfo>} */
|
|
502
685
|
let res = {};
|
|
503
686
|
if (!this.fvar) {
|
|
504
687
|
return res;
|
|
@@ -506,7 +689,7 @@ export default class TTFFont {
|
|
|
506
689
|
|
|
507
690
|
for (let axis of this.fvar.axis) {
|
|
508
691
|
res[axis.axisTag.trim()] = {
|
|
509
|
-
name: axis.name.en,
|
|
692
|
+
name: axis.name && axis.name.en,
|
|
510
693
|
min: axis.minValue,
|
|
511
694
|
default: axis.defaultValue,
|
|
512
695
|
max: axis.maxValue
|
|
@@ -521,23 +704,28 @@ export default class TTFFont {
|
|
|
521
704
|
* that the font designer has specified. Keys are variation names
|
|
522
705
|
* and values are the variation settings for this instance.
|
|
523
706
|
*
|
|
524
|
-
* @type {
|
|
707
|
+
* @type {Record<string, Record<string, number>>}
|
|
525
708
|
*/
|
|
526
709
|
@cache
|
|
527
710
|
get namedVariations() {
|
|
711
|
+
/** @type {Record<string, Record<string, number>>} */
|
|
528
712
|
let res = {};
|
|
529
713
|
if (!this.fvar) {
|
|
530
714
|
return res;
|
|
531
715
|
}
|
|
532
716
|
|
|
533
717
|
for (let instance of this.fvar.instance) {
|
|
718
|
+
/** @type {Record<string, number>} */
|
|
534
719
|
let settings = {};
|
|
535
720
|
for (let i = 0; i < this.fvar.axis.length; i++) {
|
|
536
721
|
let axis = this.fvar.axis[i];
|
|
537
722
|
settings[axis.axisTag.trim()] = instance.coord[i];
|
|
538
723
|
}
|
|
539
724
|
|
|
540
|
-
|
|
725
|
+
let key = instance.name && instance.name.en;
|
|
726
|
+
if (typeof key === 'string') {
|
|
727
|
+
res[key] = settings;
|
|
728
|
+
}
|
|
541
729
|
}
|
|
542
730
|
|
|
543
731
|
return res;
|
|
@@ -548,7 +736,7 @@ export default class TTFFont {
|
|
|
548
736
|
* Settings can either be an instance name, or an object containing
|
|
549
737
|
* variation tags as specified by the `variationAxes` property.
|
|
550
738
|
*
|
|
551
|
-
* @param {
|
|
739
|
+
* @param {string | Record<string, number>} settings
|
|
552
740
|
* @return {TTFFont}
|
|
553
741
|
*/
|
|
554
742
|
getVariation(settings) {
|
|
@@ -556,27 +744,34 @@ export default class TTFFont {
|
|
|
556
744
|
throw new Error('Variations require a font with the fvar, gvar and glyf, or CFF2 tables.');
|
|
557
745
|
}
|
|
558
746
|
|
|
747
|
+
/** @type {Record<string, number> | undefined} */
|
|
748
|
+
let resolved;
|
|
559
749
|
if (typeof settings === 'string') {
|
|
560
|
-
|
|
750
|
+
resolved = this.namedVariations[settings];
|
|
751
|
+
} else {
|
|
752
|
+
resolved = settings;
|
|
561
753
|
}
|
|
562
754
|
|
|
563
|
-
if (typeof
|
|
755
|
+
if (typeof resolved !== 'object' || resolved == null) {
|
|
564
756
|
throw new Error('Variation settings must be either a variation name or settings object.');
|
|
565
757
|
}
|
|
566
758
|
|
|
759
|
+
let fvar = /** @type {FvarTable} */ (this.fvar);
|
|
760
|
+
|
|
567
761
|
// normalize the coordinates
|
|
568
|
-
let coords =
|
|
762
|
+
let coords = fvar.axis.map((/** @type {FvarAxis} */ axis) => {
|
|
569
763
|
let axisTag = axis.axisTag.trim();
|
|
570
|
-
if (axisTag in
|
|
571
|
-
return Math.max(axis.minValue, Math.min(axis.maxValue,
|
|
764
|
+
if (axisTag in resolved) {
|
|
765
|
+
return Math.max(axis.minValue, Math.min(axis.maxValue, resolved[axisTag]));
|
|
572
766
|
} else {
|
|
573
767
|
return axis.defaultValue;
|
|
574
768
|
}
|
|
575
769
|
});
|
|
576
770
|
|
|
577
771
|
// Decompress WOFF/WOFF2 on the source once so the clone shares resolved tables.
|
|
578
|
-
|
|
579
|
-
|
|
772
|
+
let maybeDecompress = /** @type {{ _decompress?: () => void }} */ (this)._decompress;
|
|
773
|
+
if (typeof maybeDecompress === 'function') {
|
|
774
|
+
maybeDecompress.call(this);
|
|
580
775
|
}
|
|
581
776
|
|
|
582
777
|
// Preserve subclass (WOFF/WOFF2) and share decoded state. @cache values and
|
|
@@ -590,6 +785,9 @@ export default class TTFFont {
|
|
|
590
785
|
return font;
|
|
591
786
|
}
|
|
592
787
|
|
|
788
|
+
/**
|
|
789
|
+
* @type {GlyphVariationProcessor | null}
|
|
790
|
+
*/
|
|
593
791
|
@cache
|
|
594
792
|
get _variationProcessor() {
|
|
595
793
|
if (!this.fvar) {
|
|
@@ -604,14 +802,18 @@ export default class TTFFont {
|
|
|
604
802
|
}
|
|
605
803
|
|
|
606
804
|
if (!variationCoords) {
|
|
607
|
-
variationCoords = this.fvar.axis.map(axis => axis.defaultValue);
|
|
805
|
+
variationCoords = this.fvar.axis.map((/** @type {FvarAxis} */ axis) => axis.defaultValue);
|
|
608
806
|
}
|
|
609
807
|
|
|
610
808
|
return new GlyphVariationProcessor(this, variationCoords);
|
|
611
809
|
}
|
|
612
810
|
|
|
613
811
|
// Standardized format plugin API
|
|
812
|
+
/**
|
|
813
|
+
* @param {string | Uint8Array | Record<string, number>} name
|
|
814
|
+
* @returns {TTFFont}
|
|
815
|
+
*/
|
|
614
816
|
getFont(name) {
|
|
615
|
-
return this.getVariation(name);
|
|
817
|
+
return this.getVariation(/** @type {string | Record<string, number>} */ (name));
|
|
616
818
|
}
|
|
617
819
|
}
|