@cantoo/fontkit 2.0.5 → 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 +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/main.cjs +4424 -1117
- package/dist/main.cjs.map +1 -1
- package/dist/module.mjs +4423 -1117
- package/dist/module.mjs.map +1 -1
- package/package.json +3 -1
- 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/src/cff/CFFOperand.js
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
/** @typedef {import('restructure').DecodeStream} DecodeStream */
|
|
2
|
+
/** @typedef {import('restructure').EncodeStream} EncodeStream */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Operand value that may force a 32-bit encoding (e.g. CFF pointer placeholders).
|
|
6
|
+
* @typedef {number | { forceLarge?: boolean, valueOf(): number }} CFFOperandValue
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
const FLOAT_EOF = 0xf;
|
|
2
10
|
const FLOAT_LOOKUP = [
|
|
3
11
|
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
4
12
|
'8', '9', '.', 'E', 'E-', null, '-'
|
|
5
13
|
];
|
|
6
14
|
|
|
15
|
+
/** @type {Record<string, number>} */
|
|
7
16
|
const FLOAT_ENCODE_LOOKUP = {
|
|
8
17
|
'.': 10,
|
|
9
18
|
E: 11,
|
|
@@ -12,6 +21,11 @@ const FLOAT_ENCODE_LOOKUP = {
|
|
|
12
21
|
};
|
|
13
22
|
|
|
14
23
|
export default class CFFOperand {
|
|
24
|
+
/**
|
|
25
|
+
* @param {DecodeStream} stream
|
|
26
|
+
* @param {number} value
|
|
27
|
+
* @returns {number | null}
|
|
28
|
+
*/
|
|
15
29
|
static decode(stream, value) {
|
|
16
30
|
if (32 <= value && value <= 246) {
|
|
17
31
|
return value - 139;
|
|
@@ -53,73 +67,94 @@ export default class CFFOperand {
|
|
|
53
67
|
return null;
|
|
54
68
|
}
|
|
55
69
|
|
|
70
|
+
/**
|
|
71
|
+
* @param {CFFOperandValue} value
|
|
72
|
+
* @returns {number}
|
|
73
|
+
*/
|
|
56
74
|
static size(value) {
|
|
57
75
|
// if the value needs to be forced to the largest size (32 bit)
|
|
58
76
|
// e.g. for unknown pointers, set to 32768
|
|
59
|
-
|
|
60
|
-
|
|
77
|
+
/** @type {number} */
|
|
78
|
+
let n;
|
|
79
|
+
if (value && typeof value === 'object' && value.forceLarge) {
|
|
80
|
+
n = 32768;
|
|
81
|
+
} else {
|
|
82
|
+
n = Number(value);
|
|
61
83
|
}
|
|
62
84
|
|
|
63
|
-
if ((
|
|
64
|
-
let str = '' +
|
|
85
|
+
if ((n | 0) !== n) { // floating point
|
|
86
|
+
let str = '' + n;
|
|
65
87
|
return 1 + Math.ceil((str.length + 1) / 2);
|
|
66
|
-
} else if (-107 <=
|
|
88
|
+
} else if (-107 <= n && n <= 107) {
|
|
67
89
|
return 1;
|
|
68
|
-
} else if (108 <=
|
|
90
|
+
} else if (108 <= n && n <= 1131 || -1131 <= n && n <= -108) {
|
|
69
91
|
return 2;
|
|
70
|
-
} else if (-32768 <=
|
|
92
|
+
} else if (-32768 <= n && n <= 32767) {
|
|
71
93
|
return 3;
|
|
72
94
|
} else {
|
|
73
95
|
return 5;
|
|
74
96
|
}
|
|
75
97
|
}
|
|
76
98
|
|
|
99
|
+
/**
|
|
100
|
+
* @param {EncodeStream} stream
|
|
101
|
+
* @param {CFFOperandValue} value
|
|
102
|
+
* @returns {void}
|
|
103
|
+
*/
|
|
77
104
|
static encode(stream, value) {
|
|
78
105
|
// if the value needs to be forced to the largest size (32 bit)
|
|
79
106
|
// e.g. for unknown pointers, save the old value and set to 32768
|
|
80
107
|
let val = Number(value);
|
|
81
108
|
|
|
82
|
-
if (value.forceLarge) {
|
|
109
|
+
if (value && typeof value === 'object' && value.forceLarge) {
|
|
83
110
|
stream.writeUInt8(29);
|
|
84
|
-
|
|
111
|
+
stream.writeInt32BE(val);
|
|
112
|
+
return;
|
|
85
113
|
} else if ((val | 0) !== val) { // floating point
|
|
86
114
|
stream.writeUInt8(30);
|
|
87
115
|
|
|
88
116
|
let str = '' + val;
|
|
117
|
+
/** @type {number | undefined} */
|
|
89
118
|
let n2;
|
|
90
119
|
for (let i = 0; i < str.length; i += 2) {
|
|
91
120
|
let c1 = str[i];
|
|
92
|
-
let n1 = FLOAT_ENCODE_LOOKUP[c1]
|
|
121
|
+
let n1 = FLOAT_ENCODE_LOOKUP[c1] ?? (+c1);
|
|
93
122
|
|
|
94
123
|
if (i === str.length - 1) {
|
|
95
124
|
n2 = FLOAT_EOF;
|
|
96
125
|
} else {
|
|
97
126
|
let c2 = str[i + 1];
|
|
98
|
-
n2 = FLOAT_ENCODE_LOOKUP[c2]
|
|
127
|
+
n2 = FLOAT_ENCODE_LOOKUP[c2] ?? (+c2);
|
|
99
128
|
}
|
|
100
129
|
|
|
101
130
|
stream.writeUInt8((n1 << 4) | (n2 & 15));
|
|
102
131
|
}
|
|
103
132
|
|
|
104
133
|
if (n2 !== FLOAT_EOF) {
|
|
105
|
-
|
|
134
|
+
stream.writeUInt8((FLOAT_EOF << 4));
|
|
106
135
|
}
|
|
136
|
+
return;
|
|
107
137
|
} else if (-107 <= val && val <= 107) {
|
|
108
|
-
|
|
138
|
+
stream.writeUInt8(val + 139);
|
|
139
|
+
return;
|
|
109
140
|
} else if (108 <= val && val <= 1131) {
|
|
110
141
|
val -= 108;
|
|
111
142
|
stream.writeUInt8((val >> 8) + 247);
|
|
112
|
-
|
|
143
|
+
stream.writeUInt8(val & 0xff);
|
|
144
|
+
return;
|
|
113
145
|
} else if (-1131 <= val && val <= -108) {
|
|
114
146
|
val = -val - 108;
|
|
115
147
|
stream.writeUInt8((val >> 8) + 251);
|
|
116
|
-
|
|
148
|
+
stream.writeUInt8(val & 0xff);
|
|
149
|
+
return;
|
|
117
150
|
} else if (-32768 <= val && val <= 32767) {
|
|
118
151
|
stream.writeUInt8(28);
|
|
119
|
-
|
|
152
|
+
stream.writeInt16BE(val);
|
|
153
|
+
return;
|
|
120
154
|
} else {
|
|
121
155
|
stream.writeUInt8(29);
|
|
122
|
-
|
|
156
|
+
stream.writeInt32BE(val);
|
|
157
|
+
return;
|
|
123
158
|
}
|
|
124
159
|
}
|
|
125
160
|
}
|
package/src/cff/CFFPointer.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import * as r from 'restructure';
|
|
2
2
|
|
|
3
|
+
/** @typedef {import('restructure').BaseType} BaseType */
|
|
4
|
+
/** @typedef {import('restructure').DecodeStream} DecodeStream */
|
|
5
|
+
/** @typedef {import('restructure').EncodeStream} EncodeStream */
|
|
6
|
+
/** @typedef {import('restructure').PointerOptions} PointerOptions */
|
|
7
|
+
/** @typedef {import('restructure').StructValue} StructValue */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* CFF dict pointer: offset comes from a prior operand rather than the stream.
|
|
11
|
+
* Temporary offsetType stubs only implement the method needed for that phase.
|
|
12
|
+
*/
|
|
3
13
|
export default class CFFPointer extends r.Pointer {
|
|
14
|
+
/**
|
|
15
|
+
* @param {BaseType | null} type
|
|
16
|
+
* @param {PointerOptions} [options]
|
|
17
|
+
*/
|
|
4
18
|
constructor(type, options = {}) {
|
|
5
19
|
if (options.type == null) {
|
|
6
20
|
options.type = 'global';
|
|
@@ -9,6 +23,12 @@ export default class CFFPointer extends r.Pointer {
|
|
|
9
23
|
super(null, type, options);
|
|
10
24
|
}
|
|
11
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @param {DecodeStream} stream
|
|
28
|
+
* @param {StructValue | null | undefined} parent
|
|
29
|
+
* @param {number[]} operands
|
|
30
|
+
* @returns {unknown}
|
|
31
|
+
*/
|
|
12
32
|
decode(stream, parent, operands) {
|
|
13
33
|
this.offsetType = {
|
|
14
34
|
decode: () => operands[0]
|
|
@@ -17,6 +37,12 @@ export default class CFFPointer extends r.Pointer {
|
|
|
17
37
|
return super.decode(stream, parent, operands);
|
|
18
38
|
}
|
|
19
39
|
|
|
40
|
+
/**
|
|
41
|
+
* @param {EncodeStream | null} stream
|
|
42
|
+
* @param {unknown} value
|
|
43
|
+
* @param {StructValue | null | undefined} ctx
|
|
44
|
+
* @returns {Ptr[]}
|
|
45
|
+
*/
|
|
20
46
|
encode(stream, value, ctx) {
|
|
21
47
|
if (!stream) {
|
|
22
48
|
// compute the size (so ctx.pointerSize is correct)
|
|
@@ -28,22 +54,35 @@ export default class CFFPointer extends r.Pointer {
|
|
|
28
54
|
return [new Ptr(0)];
|
|
29
55
|
}
|
|
30
56
|
|
|
57
|
+
/** @type {number | null} */
|
|
31
58
|
let ptr = null;
|
|
32
59
|
this.offsetType = {
|
|
33
|
-
|
|
60
|
+
/**
|
|
61
|
+
* @param {EncodeStream} _stream
|
|
62
|
+
* @param {number} val
|
|
63
|
+
*/
|
|
64
|
+
encode: (_stream, val) => { ptr = val; }
|
|
34
65
|
};
|
|
35
66
|
|
|
36
67
|
super.encode(stream, value, ctx);
|
|
37
|
-
return [new Ptr(ptr)];
|
|
68
|
+
return [new Ptr(ptr ?? 0)];
|
|
38
69
|
}
|
|
39
70
|
}
|
|
40
71
|
|
|
41
72
|
class Ptr {
|
|
73
|
+
/**
|
|
74
|
+
* @param {number} val
|
|
75
|
+
*/
|
|
42
76
|
constructor(val) {
|
|
77
|
+
/** @type {number} */
|
|
43
78
|
this.val = val;
|
|
79
|
+
/** @type {boolean} */
|
|
44
80
|
this.forceLarge = true;
|
|
45
81
|
}
|
|
46
82
|
|
|
83
|
+
/**
|
|
84
|
+
* @returns {number}
|
|
85
|
+
*/
|
|
47
86
|
valueOf() {
|
|
48
87
|
return this.val;
|
|
49
88
|
}
|
|
@@ -2,17 +2,27 @@ import CFFDict from './CFFDict';
|
|
|
2
2
|
import CFFIndex from './CFFIndex';
|
|
3
3
|
import CFFPointer from './CFFPointer';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/** @typedef {import('restructure').DecodeStream} DecodeStream */
|
|
6
|
+
/** @typedef {import('restructure').StructValue} StructValue */
|
|
7
|
+
|
|
8
|
+
/** @type {import('../../types/fontkit').CFFOperandType} */
|
|
9
|
+
const CFFBlendOp = {
|
|
10
|
+
/**
|
|
11
|
+
* @param {DecodeStream} _stream
|
|
12
|
+
* @param {StructValue} _parent
|
|
13
|
+
* @param {number[]} operands
|
|
14
|
+
* @returns {void}
|
|
15
|
+
*/
|
|
16
|
+
decode(_stream, _parent, operands) {
|
|
7
17
|
let numBlends = operands.pop();
|
|
8
18
|
|
|
9
19
|
// TODO: actually blend. For now just consume the deltas
|
|
10
20
|
// since we don't use any of the values anyway.
|
|
11
|
-
while (operands.length > numBlends) {
|
|
21
|
+
while (operands.length > /** @type {number} */ (numBlends)) {
|
|
12
22
|
operands.pop();
|
|
13
23
|
}
|
|
14
24
|
}
|
|
15
|
-
}
|
|
25
|
+
};
|
|
16
26
|
|
|
17
27
|
export default new CFFDict([
|
|
18
28
|
// key name type default
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Automatically generated from Appendix A of the CFF specification; do
|
|
2
2
|
// not edit. Length should be 391.
|
|
3
|
+
/** @type {string[]} */
|
|
3
4
|
export default [
|
|
4
5
|
'.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar',
|
|
5
6
|
'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright',
|
package/src/cff/CFFTop.js
CHANGED
|
@@ -8,33 +8,89 @@ import { StandardEncoding, ExpertEncoding } from './CFFEncodings';
|
|
|
8
8
|
import { ISOAdobeCharset, ExpertCharset, ExpertSubsetCharset } from './CFFCharsets';
|
|
9
9
|
import { ItemVariationStore } from '../tables/variations';
|
|
10
10
|
|
|
11
|
+
/** @typedef {import('restructure').BaseType} BaseType */
|
|
12
|
+
/** @typedef {import('restructure').DecodeStream} DecodeStream */
|
|
13
|
+
/** @typedef {import('restructure').EncodeStream} EncodeStream */
|
|
14
|
+
/** @typedef {import('restructure').StructValue} StructValue */
|
|
15
|
+
/** @typedef {import('../../types/fontkit').CFFEncodeContext} CFFEncodeContext */
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {StructValue} t
|
|
19
|
+
* @returns {number}
|
|
20
|
+
*/
|
|
21
|
+
function charStringsCount(t) {
|
|
22
|
+
let parent = t.parent;
|
|
23
|
+
if (!parent) {
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
let cs = parent.CharStrings;
|
|
27
|
+
if (cs && typeof cs === 'object' && 'length' in cs && typeof /** @type {{ length: unknown }} */ (cs).length === 'number') {
|
|
28
|
+
return /** @type {{ length: number }} */ (cs).length;
|
|
29
|
+
}
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
11
33
|
// Checks if an operand is an index of a predefined value,
|
|
12
34
|
// otherwise delegates to the provided type.
|
|
13
35
|
class PredefinedOp {
|
|
36
|
+
/**
|
|
37
|
+
* @param {unknown[]} predefinedOps
|
|
38
|
+
* @param {BaseType} type
|
|
39
|
+
*/
|
|
14
40
|
constructor(predefinedOps, type) {
|
|
41
|
+
/** @type {unknown[]} */
|
|
15
42
|
this.predefinedOps = predefinedOps;
|
|
43
|
+
/** @type {BaseType} */
|
|
16
44
|
this.type = type;
|
|
17
45
|
}
|
|
18
46
|
|
|
47
|
+
/**
|
|
48
|
+
* @param {DecodeStream} stream
|
|
49
|
+
* @param {StructValue} parent
|
|
50
|
+
* @param {number[]} operands
|
|
51
|
+
* @returns {unknown}
|
|
52
|
+
*/
|
|
19
53
|
decode(stream, parent, operands) {
|
|
20
|
-
if (this.predefinedOps[operands[0]]) {
|
|
54
|
+
if (this.predefinedOps[operands[0]] != null) {
|
|
21
55
|
return this.predefinedOps[operands[0]];
|
|
22
56
|
}
|
|
23
57
|
|
|
58
|
+
if (!this.type.decode) {
|
|
59
|
+
throw new Error('PredefinedOp type must implement decode()');
|
|
60
|
+
}
|
|
24
61
|
return this.type.decode(stream, parent, operands);
|
|
25
62
|
}
|
|
26
63
|
|
|
64
|
+
/**
|
|
65
|
+
* @param {unknown} value
|
|
66
|
+
* @param {StructValue | null | undefined} ctx
|
|
67
|
+
* @returns {unknown}
|
|
68
|
+
*/
|
|
27
69
|
size(value, ctx) {
|
|
70
|
+
if (!this.type.size) {
|
|
71
|
+
throw new Error('PredefinedOp type must implement size()');
|
|
72
|
+
}
|
|
28
73
|
return this.type.size(value, ctx);
|
|
29
74
|
}
|
|
30
75
|
|
|
76
|
+
/**
|
|
77
|
+
* @param {EncodeStream | null} stream
|
|
78
|
+
* @param {unknown} value
|
|
79
|
+
* @param {StructValue | null | undefined} ctx
|
|
80
|
+
* @returns {unknown[]}
|
|
81
|
+
*/
|
|
31
82
|
encode(stream, value, ctx) {
|
|
32
83
|
let index = this.predefinedOps.indexOf(value);
|
|
33
84
|
if (index !== -1) {
|
|
34
|
-
|
|
85
|
+
// Must be an operand list — CFFDict iterates with for-of.
|
|
86
|
+
return [index];
|
|
35
87
|
}
|
|
36
88
|
|
|
37
|
-
|
|
89
|
+
if (!this.type.encode) {
|
|
90
|
+
throw new Error('PredefinedOp type must implement encode()');
|
|
91
|
+
}
|
|
92
|
+
let encoded = this.type.encode(stream, value, ctx);
|
|
93
|
+
return Array.isArray(encoded) ? encoded : [encoded];
|
|
38
94
|
}
|
|
39
95
|
}
|
|
40
96
|
|
|
@@ -43,6 +99,10 @@ class CFFEncodingVersion extends r.Number {
|
|
|
43
99
|
super('UInt8');
|
|
44
100
|
}
|
|
45
101
|
|
|
102
|
+
/**
|
|
103
|
+
* @param {DecodeStream} stream
|
|
104
|
+
* @returns {number}
|
|
105
|
+
*/
|
|
46
106
|
decode(stream) {
|
|
47
107
|
return r.uint8.decode(stream) & 0x7f;
|
|
48
108
|
}
|
|
@@ -77,15 +137,29 @@ let CFFEncoding = new PredefinedOp([StandardEncoding, ExpertEncoding], new CFFPo
|
|
|
77
137
|
// Decodes an array of ranges until the total
|
|
78
138
|
// length is equal to the provided length.
|
|
79
139
|
class RangeArray extends r.Array {
|
|
140
|
+
/**
|
|
141
|
+
* @param {DecodeStream} stream
|
|
142
|
+
* @param {StructValue} parent
|
|
143
|
+
* @returns {Array<StructValue & { nLeft: number, offset: number }>}
|
|
144
|
+
*/
|
|
80
145
|
decode(stream, parent) {
|
|
146
|
+
if (this.length == null) {
|
|
147
|
+
throw new Error('RangeArray requires a length');
|
|
148
|
+
}
|
|
81
149
|
let length = resolveLength(this.length, stream, parent);
|
|
82
150
|
let count = 0;
|
|
151
|
+
/** @type {Array<StructValue & { nLeft: number, offset: number }>} */
|
|
83
152
|
let res = [];
|
|
84
153
|
while (count < length) {
|
|
85
|
-
|
|
154
|
+
if (!this.type.decode) {
|
|
155
|
+
throw new Error('RangeArray element type must implement decode()');
|
|
156
|
+
}
|
|
157
|
+
let range = /** @type {StructValue & { nLeft: number, offset?: number }} */ (
|
|
158
|
+
this.type.decode(stream, parent)
|
|
159
|
+
);
|
|
86
160
|
range.offset = count;
|
|
87
161
|
count += range.nLeft + 1;
|
|
88
|
-
res.push(range);
|
|
162
|
+
res.push(/** @type {StructValue & { nLeft: number, offset: number }} */ (range));
|
|
89
163
|
}
|
|
90
164
|
|
|
91
165
|
return res;
|
|
@@ -94,15 +168,15 @@ class RangeArray extends r.Array {
|
|
|
94
168
|
|
|
95
169
|
let CFFCustomCharset = new r.VersionedStruct(r.uint8, {
|
|
96
170
|
0: {
|
|
97
|
-
glyphs: new r.Array(r.uint16, t => t
|
|
171
|
+
glyphs: new r.Array(r.uint16, t => charStringsCount(t) - 1)
|
|
98
172
|
},
|
|
99
173
|
|
|
100
174
|
1: {
|
|
101
|
-
ranges: new RangeArray(Range1, t => t
|
|
175
|
+
ranges: new RangeArray(Range1, t => charStringsCount(t) - 1)
|
|
102
176
|
},
|
|
103
177
|
|
|
104
178
|
2: {
|
|
105
|
-
ranges: new RangeArray(Range2, t => t
|
|
179
|
+
ranges: new RangeArray(Range2, t => charStringsCount(t) - 1)
|
|
106
180
|
}
|
|
107
181
|
});
|
|
108
182
|
|
|
@@ -120,7 +194,7 @@ let FDRange4 = new r.Struct({
|
|
|
120
194
|
|
|
121
195
|
let FDSelect = new r.VersionedStruct(r.uint8, {
|
|
122
196
|
0: {
|
|
123
|
-
fds: new r.Array(r.uint8, t => t
|
|
197
|
+
fds: new r.Array(r.uint8, t => charStringsCount(t))
|
|
124
198
|
},
|
|
125
199
|
|
|
126
200
|
3: {
|
|
@@ -138,15 +212,34 @@ let FDSelect = new r.VersionedStruct(r.uint8, {
|
|
|
138
212
|
|
|
139
213
|
let ptr = new CFFPointer(CFFPrivateDict);
|
|
140
214
|
class CFFPrivateOp {
|
|
215
|
+
/**
|
|
216
|
+
* @param {DecodeStream} stream
|
|
217
|
+
* @param {StructValue} parent
|
|
218
|
+
* @param {number[]} operands
|
|
219
|
+
* @returns {unknown}
|
|
220
|
+
*/
|
|
141
221
|
decode(stream, parent, operands) {
|
|
142
222
|
parent.length = operands[0];
|
|
143
223
|
return ptr.decode(stream, parent, [operands[1]]);
|
|
144
224
|
}
|
|
145
225
|
|
|
226
|
+
/**
|
|
227
|
+
* Size operands match encode(null, …): [privateDictByteLength, pointerOperand].
|
|
228
|
+
* @param {StructValue} dict
|
|
229
|
+
* @param {CFFEncodeContext | StructValue} ctx
|
|
230
|
+
* @returns {unknown[]}
|
|
231
|
+
*/
|
|
146
232
|
size(dict, ctx) {
|
|
147
|
-
|
|
233
|
+
// Delegate to encode(null) so pointerSize is updated and operands match.
|
|
234
|
+
return this.encode(null, dict, ctx);
|
|
148
235
|
}
|
|
149
236
|
|
|
237
|
+
/**
|
|
238
|
+
* @param {EncodeStream | null} stream
|
|
239
|
+
* @param {StructValue} dict
|
|
240
|
+
* @param {CFFEncodeContext | StructValue} ctx
|
|
241
|
+
* @returns {unknown[]}
|
|
242
|
+
*/
|
|
150
243
|
encode(stream, dict, ctx) {
|
|
151
244
|
return [CFFPrivateDict.size(dict, ctx, false), ptr.encode(stream, dict, ctx)[0]];
|
|
152
245
|
}
|
package/src/decorators.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Cache decorator for getters/methods.
|
|
3
|
+
* Results are lazily computed once, then cached on the instance.
|
|
4
|
+
*
|
|
5
|
+
* @template T
|
|
6
|
+
* @param {object} target
|
|
7
|
+
* @param {string} key
|
|
8
|
+
* @param {TypedPropertyDescriptor<T>} descriptor
|
|
9
|
+
* @returns {TypedPropertyDescriptor<T> | void}
|
|
5
10
|
*/
|
|
6
11
|
export function cache(target, key, descriptor) {
|
|
7
12
|
if (descriptor.get) {
|
|
@@ -11,26 +16,40 @@ export function cache(target, key, descriptor) {
|
|
|
11
16
|
Object.defineProperty(this, key, { value });
|
|
12
17
|
return value;
|
|
13
18
|
};
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (typeof descriptor.value === 'function') {
|
|
23
|
+
let fn = /** @type {(...args: unknown[]) => T} */ (descriptor.value);
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
/** @type {TypedPropertyDescriptor<T>} */
|
|
26
|
+
let replacement = {
|
|
27
|
+
configurable: true,
|
|
28
|
+
enumerable: false,
|
|
18
29
|
get() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
/** @type {Map<unknown, T>} */
|
|
31
|
+
let cacheMap = new Map();
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {...unknown} args
|
|
35
|
+
* @returns {T}
|
|
36
|
+
*/
|
|
37
|
+
let memoized = (...args) => {
|
|
38
|
+
let cacheKey = args.length > 0 ? args[0] : 'value';
|
|
39
|
+
if (cacheMap.has(cacheKey)) {
|
|
40
|
+
return /** @type {T} */ (cacheMap.get(cacheKey));
|
|
24
41
|
}
|
|
25
42
|
|
|
26
43
|
let result = fn.apply(this, args);
|
|
27
|
-
|
|
44
|
+
cacheMap.set(cacheKey, result);
|
|
28
45
|
return result;
|
|
29
46
|
};
|
|
30
47
|
|
|
31
48
|
Object.defineProperty(this, key, { value: memoized });
|
|
32
|
-
return memoized;
|
|
49
|
+
return /** @type {T} */ (/** @type {unknown} */ (memoized));
|
|
33
50
|
}
|
|
34
51
|
};
|
|
52
|
+
|
|
53
|
+
return replacement;
|
|
35
54
|
}
|
|
36
55
|
}
|
package/src/encodings.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Gets an encoding name from platform, encoding, and language ids.
|
|
3
3
|
* Returned encoding names can be used in iconv-lite to decode text.
|
|
4
|
+
* @param {number} platformID
|
|
5
|
+
* @param {number} encodingID
|
|
6
|
+
* @param {number} [languageID]
|
|
7
|
+
* @returns {string | null | undefined}
|
|
4
8
|
*/
|
|
5
9
|
export function getEncoding(platformID, encodingID, languageID = 0) {
|
|
6
10
|
if (platformID === 1 && MAC_LANGUAGE_ENCODINGS[languageID]) {
|
|
@@ -10,7 +14,10 @@ export function getEncoding(platformID, encodingID, languageID = 0) {
|
|
|
10
14
|
return ENCODINGS[platformID][encodingID];
|
|
11
15
|
}
|
|
12
16
|
|
|
17
|
+
/** @type {Set<string>} */
|
|
13
18
|
const SINGLE_BYTE_ENCODINGS = new Set(['x-mac-roman', 'x-mac-cyrillic', 'iso-8859-6', 'iso-8859-8']);
|
|
19
|
+
|
|
20
|
+
/** @type {Record<string, string>} */
|
|
14
21
|
const MAC_ENCODINGS = {
|
|
15
22
|
'x-mac-croatian': 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø¿¡¬√ƒ≈ƫȅ ÀÃÕŒœĐ—“”‘’÷◊©⁄€‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ',
|
|
16
23
|
'x-mac-gaelic': 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØḂ±≤≥ḃĊċḊḋḞḟĠġṀæøṁṖṗɼƒſṠ«»… ÀÃÕŒœ–—“”‘’ṡẛÿŸṪ€‹›Ŷŷṫ·Ỳỳ⁊ÂÊÁËÈÍÎÏÌÓÔ♣ÒÚÛÙıÝýŴŵẄẅẀẁẂẃ',
|
|
@@ -22,8 +29,13 @@ const MAC_ENCODINGS = {
|
|
|
22
29
|
'x-mac-turkish': 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙˆ˜¯˘˙˚¸˝˛ˇ'
|
|
23
30
|
};
|
|
24
31
|
|
|
32
|
+
/** @type {Map<string, Map<number, number>>} */
|
|
25
33
|
const encodingCache = new Map();
|
|
26
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @param {string} encoding
|
|
37
|
+
* @returns {Map<number, number> | undefined}
|
|
38
|
+
*/
|
|
27
39
|
export function getEncodingMapping(encoding) {
|
|
28
40
|
let cached = encodingCache.get(encoding);
|
|
29
41
|
if (cached) {
|
|
@@ -47,13 +59,13 @@ export function getEncodingMapping(encoding) {
|
|
|
47
59
|
// TextEncoder only supports utf8, whereas TextDecoder supports legacy encodings.
|
|
48
60
|
// Use this to create a mapping of code points.
|
|
49
61
|
let decoder = new TextDecoder(encoding);
|
|
50
|
-
let
|
|
62
|
+
let bytes = new Uint8Array(0x80);
|
|
51
63
|
for (let i = 0; i < 0x80; i++) {
|
|
52
|
-
|
|
64
|
+
bytes[i] = 0x80 + i;
|
|
53
65
|
}
|
|
54
66
|
|
|
55
67
|
let res = new Map();
|
|
56
|
-
let s = decoder.decode(
|
|
68
|
+
let s = decoder.decode(bytes);
|
|
57
69
|
for (let i = 0; i < 0x80; i++) {
|
|
58
70
|
res.set(s.charCodeAt(i), 0x80 + i);
|
|
59
71
|
}
|
|
@@ -61,9 +73,12 @@ export function getEncodingMapping(encoding) {
|
|
|
61
73
|
encodingCache.set(encoding, res);
|
|
62
74
|
return res;
|
|
63
75
|
}
|
|
76
|
+
|
|
77
|
+
return undefined;
|
|
64
78
|
}
|
|
65
79
|
|
|
66
80
|
// Map of platform ids to encoding ids.
|
|
81
|
+
/** @type {(string | null)[][]} */
|
|
67
82
|
export const ENCODINGS = [
|
|
68
83
|
// unicode
|
|
69
84
|
['utf-16be', 'utf-16be', 'utf-16be', 'utf-16be', 'utf-16be', 'utf-16be', 'utf-16be'],
|
|
@@ -103,6 +118,7 @@ export const ENCODINGS = [
|
|
|
103
118
|
|
|
104
119
|
// Overrides for Mac scripts by language id.
|
|
105
120
|
// See http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt
|
|
121
|
+
/** @type {Record<number, string>} */
|
|
106
122
|
export const MAC_LANGUAGE_ENCODINGS = {
|
|
107
123
|
15: 'x-mac-icelandic',
|
|
108
124
|
17: 'x-mac-turkish',
|
|
@@ -122,9 +138,10 @@ export const MAC_LANGUAGE_ENCODINGS = {
|
|
|
122
138
|
};
|
|
123
139
|
|
|
124
140
|
// Map of platform ids to BCP-47 language codes.
|
|
141
|
+
/** @type {Array<Record<number, string>>} */
|
|
125
142
|
export const LANGUAGES = [
|
|
126
143
|
// unicode
|
|
127
|
-
|
|
144
|
+
{},
|
|
128
145
|
|
|
129
146
|
{ // macintosh
|
|
130
147
|
0: 'en', 30: 'fo', 60: 'ks', 90: 'rw',
|
|
@@ -160,7 +177,7 @@ export const LANGUAGES = [
|
|
|
160
177
|
},
|
|
161
178
|
|
|
162
179
|
// ISO (deprecated)
|
|
163
|
-
|
|
180
|
+
{},
|
|
164
181
|
|
|
165
182
|
{ // windows
|
|
166
183
|
0x0436: 'af', 0x4009: 'en-IN', 0x0487: 'rw', 0x0432: 'tn',
|
package/src/fs.js
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { create } from './base';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @param {string | import('fs').PathLike} filename
|
|
6
|
+
* @param {string | Uint8Array} [postscriptName]
|
|
7
|
+
* @returns {import('../types/fontkit').OpenedFont | null | undefined}
|
|
8
|
+
*/
|
|
4
9
|
export function openSync(filename, postscriptName) {
|
|
5
10
|
let buffer = fs.readFileSync(filename);
|
|
6
11
|
return create(buffer, postscriptName);
|
|
7
12
|
}
|
|
8
13
|
|
|
14
|
+
/**
|
|
15
|
+
* @param {string | import('fs').PathLike} filename
|
|
16
|
+
* @param {string | Uint8Array} [postscriptName]
|
|
17
|
+
* @returns {Promise<import('../types/fontkit').OpenedFont | null | undefined>}
|
|
18
|
+
*/
|
|
9
19
|
export async function open(filename, postscriptName) {
|
|
10
20
|
let buffer = await fs.promises.readFile(filename);
|
|
11
21
|
return create(buffer, postscriptName);
|
package/src/glyph/BBox.js
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
* Represents a glyph bounding box
|
|
3
3
|
*/
|
|
4
4
|
export default class BBox {
|
|
5
|
+
/**
|
|
6
|
+
* @param {number} [minX]
|
|
7
|
+
* @param {number} [minY]
|
|
8
|
+
* @param {number} [maxX]
|
|
9
|
+
* @param {number} [maxY]
|
|
10
|
+
*/
|
|
5
11
|
constructor(minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity) {
|
|
6
12
|
/**
|
|
7
13
|
* The minimum X position in the bounding box
|
|
@@ -44,6 +50,11 @@ export default class BBox {
|
|
|
44
50
|
return this.maxY - this.minY;
|
|
45
51
|
}
|
|
46
52
|
|
|
53
|
+
/**
|
|
54
|
+
* @param {number} x
|
|
55
|
+
* @param {number} y
|
|
56
|
+
* @returns {void}
|
|
57
|
+
*/
|
|
47
58
|
addPoint(x, y) {
|
|
48
59
|
if (Math.abs(x) !== Infinity) {
|
|
49
60
|
if (x < this.minX) {
|
|
@@ -66,6 +77,9 @@ export default class BBox {
|
|
|
66
77
|
}
|
|
67
78
|
}
|
|
68
79
|
|
|
80
|
+
/**
|
|
81
|
+
* @returns {BBox}
|
|
82
|
+
*/
|
|
69
83
|
copy() {
|
|
70
84
|
return new BBox(this.minX, this.minY, this.maxX, this.maxY);
|
|
71
85
|
}
|