@cantoo/fontkit 2.0.4
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/LICENSE +21 -0
- package/README.md +274 -0
- package/dist/browser-module.mjs +13660 -0
- package/dist/browser-module.mjs.map +1 -0
- package/dist/browser.cjs +13689 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/main.cjs +13712 -0
- package/dist/main.cjs.map +1 -0
- package/dist/module.mjs +13673 -0
- package/dist/module.mjs.map +1 -0
- package/package.json +99 -0
- package/src/CmapProcessor.js +285 -0
- package/src/DFont.js +113 -0
- package/src/TTFFont.js +621 -0
- package/src/TrueTypeCollection.js +65 -0
- package/src/WOFF2Font.js +222 -0
- package/src/WOFFFont.js +56 -0
- package/src/aat/AATFeatureMap.js +545 -0
- package/src/aat/AATLayoutEngine.js +48 -0
- package/src/aat/AATLookupTable.js +125 -0
- package/src/aat/AATMorxProcessor.js +429 -0
- package/src/aat/AATStateMachine.js +96 -0
- package/src/base.js +29 -0
- package/src/cff/CFFCharsets.js +99 -0
- package/src/cff/CFFDict.js +166 -0
- package/src/cff/CFFEncodings.js +48 -0
- package/src/cff/CFFFont.js +158 -0
- package/src/cff/CFFIndex.js +150 -0
- package/src/cff/CFFOperand.js +135 -0
- package/src/cff/CFFPointer.js +50 -0
- package/src/cff/CFFPrivateDict.js +39 -0
- package/src/cff/CFFStandardStrings.js +71 -0
- package/src/cff/CFFTop.js +236 -0
- package/src/decorators.js +36 -0
- package/src/encodings.js +219 -0
- package/src/fs.js +12 -0
- package/src/glyph/BBox.js +72 -0
- package/src/glyph/CBDTGlyph.js +9 -0
- package/src/glyph/CFFGlyph.js +635 -0
- package/src/glyph/COLRGlyph.js +108 -0
- package/src/glyph/Glyph.js +270 -0
- package/src/glyph/GlyphVariationProcessor.js +487 -0
- package/src/glyph/Path.js +257 -0
- package/src/glyph/SBIXGlyph.js +54 -0
- package/src/glyph/StandardNames.js +27 -0
- package/src/glyph/TTFGlyph.js +408 -0
- package/src/glyph/TTFGlyphEncoder.js +158 -0
- package/src/glyph/WOFF2Glyph.js +70 -0
- package/src/index.js +15 -0
- package/src/layout/GlyphPosition.js +30 -0
- package/src/layout/GlyphRun.js +108 -0
- package/src/layout/KernProcessor.js +97 -0
- package/src/layout/LayoutEngine.js +190 -0
- package/src/layout/Script.js +231 -0
- package/src/layout/UnicodeLayoutEngine.js +250 -0
- package/src/node.js +16 -0
- package/src/opentype/GPOSProcessor.js +311 -0
- package/src/opentype/GSUBProcessor.js +208 -0
- package/src/opentype/GlyphInfo.js +57 -0
- package/src/opentype/GlyphIterator.js +82 -0
- package/src/opentype/OTLayoutEngine.js +117 -0
- package/src/opentype/OTProcessor.js +472 -0
- package/src/opentype/ShapingPlan.js +121 -0
- package/src/opentype/shapers/ArabicShaper.js +124 -0
- package/src/opentype/shapers/DefaultShaper.js +116 -0
- package/src/opentype/shapers/HangulShaper.js +285 -0
- package/src/opentype/shapers/HebrewShaper.js +105 -0
- package/src/opentype/shapers/IndicShaper.js +914 -0
- package/src/opentype/shapers/ThaiShaper.js +238 -0
- package/src/opentype/shapers/UniversalShaper.js +186 -0
- package/src/opentype/shapers/data.trie +0 -0
- package/src/opentype/shapers/gen-indic.js +208 -0
- package/src/opentype/shapers/gen-use.js +287 -0
- package/src/opentype/shapers/generate-data.js +33 -0
- package/src/opentype/shapers/index.js +109 -0
- package/src/opentype/shapers/indic-data.js +175 -0
- package/src/opentype/shapers/indic.json +1 -0
- package/src/opentype/shapers/indic.machine +31 -0
- package/src/opentype/shapers/indic.trie +0 -0
- package/src/opentype/shapers/use.json +1 -0
- package/src/opentype/shapers/use.machine +44 -0
- package/src/opentype/shapers/use.trie +0 -0
- package/src/packages/unicode-properties/LICENSE +8 -0
- package/src/packages/unicode-properties/README.md +12 -0
- package/src/packages/unicode-properties/data-trie.js +1 -0
- package/src/packages/unicode-properties/data.js +1 -0
- package/src/packages/unicode-properties/data.json +1 -0
- package/src/packages/unicode-properties/data.trie +0 -0
- package/src/packages/unicode-properties/dist/index.cjs +257 -0
- package/src/packages/unicode-properties/dist/index.cjs.map +7 -0
- package/src/packages/unicode-properties/dist/index.mjs +234 -0
- package/src/packages/unicode-properties/dist/index.mjs.map +7 -0
- package/src/packages/unicode-properties/generate.js +107 -0
- package/src/packages/unicode-properties/index.js +184 -0
- package/src/packages/unicode-properties/package.json +50 -0
- package/src/packages/unicode-trie/LICENSE +8 -0
- package/src/packages/unicode-trie/README.md +13 -0
- package/src/packages/unicode-trie/builder.js +965 -0
- package/src/packages/unicode-trie/dist/builder.cjs +711 -0
- package/src/packages/unicode-trie/dist/builder.cjs.map +7 -0
- package/src/packages/unicode-trie/dist/builder.mjs +690 -0
- package/src/packages/unicode-trie/dist/builder.mjs.map +7 -0
- package/src/packages/unicode-trie/dist/index.cjs +112 -0
- package/src/packages/unicode-trie/dist/index.cjs.map +7 -0
- package/src/packages/unicode-trie/dist/index.mjs +91 -0
- package/src/packages/unicode-trie/dist/index.mjs.map +7 -0
- package/src/packages/unicode-trie/index.js +135 -0
- package/src/packages/unicode-trie/package.json +49 -0
- package/src/packages/unicode-trie/swap.js +21 -0
- package/src/subset/CFFSubset.js +176 -0
- package/src/subset/Subset.js +63 -0
- package/src/subset/TTFSubset.js +130 -0
- package/src/tables/BASE.js +78 -0
- package/src/tables/COLR.js +25 -0
- package/src/tables/CPAL.js +24 -0
- package/src/tables/DSIG.js +21 -0
- package/src/tables/EBDT.js +91 -0
- package/src/tables/EBLC.js +80 -0
- package/src/tables/GDEF.js +57 -0
- package/src/tables/GPOS.js +209 -0
- package/src/tables/GSUB.js +85 -0
- package/src/tables/HVAR.js +44 -0
- package/src/tables/JSTF.js +43 -0
- package/src/tables/LTSH.js +10 -0
- package/src/tables/OS2.js +84 -0
- package/src/tables/PCLT.js +21 -0
- package/src/tables/STAT.js +99 -0
- package/src/tables/VDMX.js +33 -0
- package/src/tables/VORG.js +14 -0
- package/src/tables/WOFF2Directory.js +73 -0
- package/src/tables/WOFFDirectory.js +37 -0
- package/src/tables/aat.js +157 -0
- package/src/tables/avar.js +19 -0
- package/src/tables/bsln.js +31 -0
- package/src/tables/cmap.js +127 -0
- package/src/tables/cvt.js +6 -0
- package/src/tables/directory.js +58 -0
- package/src/tables/feat.js +28 -0
- package/src/tables/fpgm.js +8 -0
- package/src/tables/fvar.js +31 -0
- package/src/tables/gasp.js +15 -0
- package/src/tables/glyf.js +4 -0
- package/src/tables/gvar.js +27 -0
- package/src/tables/hdmx.js +15 -0
- package/src/tables/head.js +25 -0
- package/src/tables/hhea.js +19 -0
- package/src/tables/hmtx.js +11 -0
- package/src/tables/index.js +119 -0
- package/src/tables/just.js +81 -0
- package/src/tables/kern.js +91 -0
- package/src/tables/loca.js +30 -0
- package/src/tables/maxp.js +20 -0
- package/src/tables/morx.js +79 -0
- package/src/tables/name.js +157 -0
- package/src/tables/opbd.js +15 -0
- package/src/tables/opentype.js +217 -0
- package/src/tables/post.js +34 -0
- package/src/tables/prep.js +6 -0
- package/src/tables/sbix.js +17 -0
- package/src/tables/variations.js +80 -0
- package/src/tables/vhea.js +19 -0
- package/src/tables/vmtx.js +12 -0
- package/src/utils.js +62 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import Subset from './Subset';
|
|
2
|
+
import CFFTop from '../cff/CFFTop';
|
|
3
|
+
import standardStrings from '../cff/CFFStandardStrings';
|
|
4
|
+
|
|
5
|
+
export default class CFFSubset extends Subset {
|
|
6
|
+
constructor(font) {
|
|
7
|
+
super(font);
|
|
8
|
+
|
|
9
|
+
this.cff = this.font['CFF '];
|
|
10
|
+
if (!this.cff) {
|
|
11
|
+
throw new Error('Not a CFF Font');
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
includeTable() {
|
|
16
|
+
throw new Error('includeTable is only supported for TrueType (glyf) subsets, not CFF.');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
subsetCharstrings() {
|
|
20
|
+
this.charstrings = [];
|
|
21
|
+
let gsubrs = {};
|
|
22
|
+
|
|
23
|
+
for (let gid of this.glyphs) {
|
|
24
|
+
this.charstrings.push(this.cff.getCharString(gid));
|
|
25
|
+
|
|
26
|
+
let glyph = this.font.getGlyph(gid);
|
|
27
|
+
void glyph.path; // this causes the glyph to be parsed
|
|
28
|
+
|
|
29
|
+
for (let subr in glyph._usedGsubrs) {
|
|
30
|
+
gsubrs[subr] = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
this.gsubrs = this.subsetSubrs(this.cff.globalSubrIndex, gsubrs);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
subsetSubrs(subrs, used) {
|
|
38
|
+
let res = [];
|
|
39
|
+
for (let i = 0; i < subrs.length; i++) {
|
|
40
|
+
let subr = subrs[i];
|
|
41
|
+
if (used[i]) {
|
|
42
|
+
this.cff.stream.pos = subr.offset;
|
|
43
|
+
res.push(this.cff.stream.readBuffer(subr.length));
|
|
44
|
+
} else {
|
|
45
|
+
res.push(new Uint8Array([11])); // return
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return res;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
subsetFontdict(topDict) {
|
|
53
|
+
topDict.FDArray = [];
|
|
54
|
+
topDict.FDSelect = {
|
|
55
|
+
version: 0,
|
|
56
|
+
fds: []
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
let used_fds = {};
|
|
60
|
+
let used_subrs = [];
|
|
61
|
+
let fd_select = {};
|
|
62
|
+
for (let gid of this.glyphs) {
|
|
63
|
+
let fd = this.cff.fdForGlyph(gid);
|
|
64
|
+
if (fd == null) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!used_fds[fd]) {
|
|
69
|
+
topDict.FDArray.push(Object.assign({}, this.cff.topDict.FDArray[fd]));
|
|
70
|
+
used_subrs.push({});
|
|
71
|
+
fd_select[fd] = topDict.FDArray.length - 1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
used_fds[fd] = true;
|
|
75
|
+
topDict.FDSelect.fds.push(fd_select[fd]);
|
|
76
|
+
|
|
77
|
+
let glyph = this.font.getGlyph(gid);
|
|
78
|
+
void glyph.path; // this causes the glyph to be parsed
|
|
79
|
+
for (let subr in glyph._usedSubrs) {
|
|
80
|
+
used_subrs[fd_select[fd]][subr] = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for (let i = 0; i < topDict.FDArray.length; i++) {
|
|
85
|
+
let dict = topDict.FDArray[i];
|
|
86
|
+
delete dict.FontName;
|
|
87
|
+
if (dict.Private && dict.Private.Subrs) {
|
|
88
|
+
dict.Private = Object.assign({}, dict.Private);
|
|
89
|
+
dict.Private.Subrs = this.subsetSubrs(dict.Private.Subrs, used_subrs[i]);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
createCIDFontdict(topDict) {
|
|
97
|
+
let used_subrs = {};
|
|
98
|
+
for (let gid of this.glyphs) {
|
|
99
|
+
let glyph = this.font.getGlyph(gid);
|
|
100
|
+
void glyph.path; // this causes the glyph to be parsed
|
|
101
|
+
|
|
102
|
+
for (let subr in glyph._usedSubrs) {
|
|
103
|
+
used_subrs[subr] = true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
let privateDict = Object.assign({}, this.cff.topDict.Private);
|
|
108
|
+
if (this.cff.topDict.Private && this.cff.topDict.Private.Subrs) {
|
|
109
|
+
privateDict.Subrs = this.subsetSubrs(this.cff.topDict.Private.Subrs, used_subrs);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
topDict.FDArray = [{ Private: privateDict }];
|
|
113
|
+
return topDict.FDSelect = {
|
|
114
|
+
version: 3,
|
|
115
|
+
nRanges: 1,
|
|
116
|
+
ranges: [{ first: 0, fd: 0 }],
|
|
117
|
+
sentinel: this.charstrings.length
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
addString(string) {
|
|
122
|
+
if (!string) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!this.strings) {
|
|
127
|
+
this.strings = [];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this.strings.push(string);
|
|
131
|
+
return standardStrings.length + this.strings.length - 1;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
encode() {
|
|
135
|
+
this.subsetCharstrings();
|
|
136
|
+
|
|
137
|
+
let charset = {
|
|
138
|
+
version: this.charstrings.length > 255 ? 2 : 1,
|
|
139
|
+
ranges: this.charstrings.length > 1
|
|
140
|
+
? [{ first: 1, nLeft: this.charstrings.length - 2 }]
|
|
141
|
+
: []
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
let topDict = Object.assign({}, this.cff.topDict);
|
|
145
|
+
topDict.Private = null;
|
|
146
|
+
topDict.charset = charset;
|
|
147
|
+
topDict.Encoding = null;
|
|
148
|
+
topDict.CharStrings = this.charstrings;
|
|
149
|
+
|
|
150
|
+
for (let key of ['version', 'Notice', 'Copyright', 'FullName', 'FamilyName', 'Weight', 'PostScript', 'BaseFontName', 'FontName']) {
|
|
151
|
+
topDict[key] = this.addString(this.cff.string(topDict[key]));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
topDict.ROS = [this.addString('Adobe'), this.addString('Identity'), 0];
|
|
155
|
+
topDict.CIDCount = this.charstrings.length;
|
|
156
|
+
|
|
157
|
+
if (this.cff.isCIDFont) {
|
|
158
|
+
this.subsetFontdict(topDict);
|
|
159
|
+
} else {
|
|
160
|
+
this.createCIDFontdict(topDict);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
let top = {
|
|
164
|
+
version: 1,
|
|
165
|
+
hdrSize: this.cff.hdrSize,
|
|
166
|
+
offSize: 4,
|
|
167
|
+
header: this.cff.header,
|
|
168
|
+
nameIndex: [this.cff.postscriptName],
|
|
169
|
+
topDictIndex: [topDict],
|
|
170
|
+
stringIndex: this.strings,
|
|
171
|
+
globalSubrIndex: this.gsubrs
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
return CFFTop.toBuffer(top);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import Tables from '../tables';
|
|
2
|
+
|
|
3
|
+
// Tables written by TTFSubset.encode; must not be overwritten via includeTable.
|
|
4
|
+
const MANAGED_TTF_TABLES = [
|
|
5
|
+
'head', 'hhea', 'loca', 'maxp', 'cvt ', 'prep', 'glyf', 'hmtx', 'fpgm'
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
export default class Subset {
|
|
9
|
+
constructor(font) {
|
|
10
|
+
this.font = font;
|
|
11
|
+
this.glyphs = [];
|
|
12
|
+
this.mapping = {};
|
|
13
|
+
// Extra OT table tags to copy into a TTF subset (e.g. 'OS/2', 'name', 'post').
|
|
14
|
+
this.includedTables = [];
|
|
15
|
+
|
|
16
|
+
// always include the missing glyph
|
|
17
|
+
this.includeGlyph(0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
includeGlyph(glyph) {
|
|
21
|
+
if (typeof glyph === 'object') {
|
|
22
|
+
glyph = glyph.id;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (this.mapping[glyph] == null) {
|
|
26
|
+
this.glyphs.push(glyph);
|
|
27
|
+
this.mapping[glyph] = this.glyphs.length - 1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return this.mapping[glyph];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Copy an OT table into the TTF subset (tag is a 4-byte string, e.g. 'OS/2').
|
|
34
|
+
// Only honored by TTFSubset.encode; CFFSubset overrides this to throw.
|
|
35
|
+
includeTable(tag) {
|
|
36
|
+
if (typeof tag !== 'string' || tag.length !== 4) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Invalid OpenType table tag ${JSON.stringify(tag)}: tags must be 4 characters ` +
|
|
39
|
+
`(pad with spaces if needed, e.g. "cvt ").`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (MANAGED_TTF_TABLES.includes(tag)) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Table "${tag}" is already managed by the TrueType subsetter and cannot be included explicitly.`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!this.font.directory.tables[tag]) {
|
|
50
|
+
throw new Error(`Table "${tag}" is not present in this font.`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!Tables[tag]) {
|
|
54
|
+
throw new Error(`Table "${tag}" cannot be encoded (no encoder registered in fontkit).`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!this.includedTables.includes(tag)) {
|
|
58
|
+
this.includedTables.push(tag);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import cloneDeep from 'clone';
|
|
2
|
+
import Subset from './Subset';
|
|
3
|
+
import Directory from '../tables/directory';
|
|
4
|
+
import TTFGlyphEncoder from '../glyph/TTFGlyphEncoder';
|
|
5
|
+
|
|
6
|
+
export default class TTFSubset extends Subset {
|
|
7
|
+
constructor(font) {
|
|
8
|
+
super(font);
|
|
9
|
+
this.glyphEncoder = new TTFGlyphEncoder;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
_addGlyph(gid) {
|
|
13
|
+
let glyph = this.font.getGlyph(gid);
|
|
14
|
+
let glyf = glyph._decode();
|
|
15
|
+
|
|
16
|
+
// get the offset to the glyph from the loca table
|
|
17
|
+
let curOffset = this.font.loca.offsets[gid];
|
|
18
|
+
let nextOffset = this.font.loca.offsets[gid + 1];
|
|
19
|
+
|
|
20
|
+
let stream = this.font._getTableStream('glyf');
|
|
21
|
+
stream.pos += curOffset;
|
|
22
|
+
|
|
23
|
+
let buffer = stream.readBuffer(nextOffset - curOffset);
|
|
24
|
+
|
|
25
|
+
// if it is a compound glyph, include its components
|
|
26
|
+
if (glyf && glyf.numberOfContours < 0) {
|
|
27
|
+
buffer = new Uint8Array(buffer);
|
|
28
|
+
let view = new DataView(buffer.buffer);
|
|
29
|
+
for (let component of glyf.components) {
|
|
30
|
+
gid = this.includeGlyph(component.glyphID);
|
|
31
|
+
view.setUint16(component.pos, gid);
|
|
32
|
+
}
|
|
33
|
+
} else if (glyf && this.font._variationProcessor) {
|
|
34
|
+
// If this is a TrueType variation glyph, re-encode the path
|
|
35
|
+
buffer = this.glyphEncoder.encodeSimple(glyph.path, glyf.instructions);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
this.glyf.push(buffer);
|
|
39
|
+
this.loca.offsets.push(this.offset);
|
|
40
|
+
|
|
41
|
+
this.hmtx.metrics.push({
|
|
42
|
+
advance: glyph.advanceWidth,
|
|
43
|
+
bearing: glyph._getMetrics().leftBearing
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this.offset += buffer.length;
|
|
47
|
+
return this.glyf.length - 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
encode() {
|
|
51
|
+
// tables required by PDF spec:
|
|
52
|
+
// head, hhea, loca, maxp, cvt , prep, glyf, hmtx, fpgm
|
|
53
|
+
//
|
|
54
|
+
// additional tables required for standalone fonts:
|
|
55
|
+
// name, cmap, OS/2, post
|
|
56
|
+
|
|
57
|
+
this.glyf = [];
|
|
58
|
+
this.offset = 0;
|
|
59
|
+
this.loca = {
|
|
60
|
+
offsets: [],
|
|
61
|
+
version: this.font.loca.version
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
this.hmtx = {
|
|
65
|
+
metrics: [],
|
|
66
|
+
bearings: []
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// include all the glyphs
|
|
70
|
+
// not using a for loop because we need to support adding more
|
|
71
|
+
// glyphs to the array as we go, and CoffeeScript caches the length.
|
|
72
|
+
let i = 0;
|
|
73
|
+
while (i < this.glyphs.length) {
|
|
74
|
+
this._addGlyph(this.glyphs[i++]);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let maxp = cloneDeep(this.font.maxp);
|
|
78
|
+
maxp.numGlyphs = this.glyf.length;
|
|
79
|
+
|
|
80
|
+
this.loca.offsets.push(this.offset);
|
|
81
|
+
|
|
82
|
+
let head = cloneDeep(this.font.head);
|
|
83
|
+
head.indexToLocFormat = this.loca.version;
|
|
84
|
+
|
|
85
|
+
let hhea = cloneDeep(this.font.hhea);
|
|
86
|
+
hhea.numberOfMetrics = this.hmtx.metrics.length;
|
|
87
|
+
|
|
88
|
+
// map = []
|
|
89
|
+
// for index in [0...256]
|
|
90
|
+
// if index < @numGlyphs
|
|
91
|
+
// map[index] = index
|
|
92
|
+
// else
|
|
93
|
+
// map[index] = 0
|
|
94
|
+
//
|
|
95
|
+
// cmapTable =
|
|
96
|
+
// version: 0
|
|
97
|
+
// length: 262
|
|
98
|
+
// language: 0
|
|
99
|
+
// codeMap: map
|
|
100
|
+
//
|
|
101
|
+
// cmap =
|
|
102
|
+
// version: 0
|
|
103
|
+
// numSubtables: 1
|
|
104
|
+
// tables: [
|
|
105
|
+
// platformID: 1
|
|
106
|
+
// encodingID: 0
|
|
107
|
+
// table: cmapTable
|
|
108
|
+
// ]
|
|
109
|
+
|
|
110
|
+
// TODO: subset prep, cvt, fpgm?
|
|
111
|
+
// The following is the minimum set of tables.
|
|
112
|
+
let t = {
|
|
113
|
+
head,
|
|
114
|
+
hhea,
|
|
115
|
+
loca: this.loca,
|
|
116
|
+
maxp,
|
|
117
|
+
'cvt ': this.font['cvt '],
|
|
118
|
+
prep: this.font.prep,
|
|
119
|
+
glyf: this.glyf,
|
|
120
|
+
hmtx: this.hmtx,
|
|
121
|
+
fpgm: this.font.fpgm,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
for (const tag of this.includedTables) {
|
|
125
|
+
t[tag] = cloneDeep(this.font[tag]);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return Directory.toBuffer({tables: t});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as r from 'restructure';
|
|
2
|
+
import {Device} from './opentype';
|
|
3
|
+
import {ItemVariationStore} from './variations';
|
|
4
|
+
|
|
5
|
+
let BaseCoord = new r.VersionedStruct(r.uint16, {
|
|
6
|
+
1: { // Design units only
|
|
7
|
+
coordinate: r.int16 // X or Y value, in design units
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
2: { // Design units plus contour point
|
|
11
|
+
coordinate: r.int16, // X or Y value, in design units
|
|
12
|
+
referenceGlyph: r.uint16, // GlyphID of control glyph
|
|
13
|
+
baseCoordPoint: r.uint16 // Index of contour point on the referenceGlyph
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
3: { // Design units plus Device table
|
|
17
|
+
coordinate: r.int16, // X or Y value, in design units
|
|
18
|
+
deviceTable: new r.Pointer(r.uint16, Device) // Device table for X or Y value
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
let BaseValues = new r.Struct({
|
|
23
|
+
defaultIndex: r.uint16, // Index of default baseline for this script-same index in the BaseTagList
|
|
24
|
+
baseCoordCount: r.uint16,
|
|
25
|
+
baseCoords: new r.Array(new r.Pointer(r.uint16, BaseCoord), 'baseCoordCount')
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
let FeatMinMaxRecord = new r.Struct({
|
|
29
|
+
tag: new r.String(4), // 4-byte feature identification tag-must match FeatureTag in FeatureList
|
|
30
|
+
minCoord: new r.Pointer(r.uint16, BaseCoord, {type: 'parent'}), // May be NULL
|
|
31
|
+
maxCoord: new r.Pointer(r.uint16, BaseCoord, {type: 'parent'}) // May be NULL
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
let MinMax = new r.Struct({
|
|
35
|
+
minCoord: new r.Pointer(r.uint16, BaseCoord), // May be NULL
|
|
36
|
+
maxCoord: new r.Pointer(r.uint16, BaseCoord), // May be NULL
|
|
37
|
+
featMinMaxCount: r.uint16, // May be 0
|
|
38
|
+
featMinMaxRecords: new r.Array(FeatMinMaxRecord, 'featMinMaxCount') // In alphabetical order
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
let BaseLangSysRecord = new r.Struct({
|
|
42
|
+
tag: new r.String(4), // 4-byte language system identification tag
|
|
43
|
+
minMax: new r.Pointer(r.uint16, MinMax, {type: 'parent'})
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
let BaseScript = new r.Struct({
|
|
47
|
+
baseValues: new r.Pointer(r.uint16, BaseValues), // May be NULL
|
|
48
|
+
defaultMinMax: new r.Pointer(r.uint16, MinMax), // May be NULL
|
|
49
|
+
baseLangSysCount: r.uint16, // May be 0
|
|
50
|
+
baseLangSysRecords: new r.Array(BaseLangSysRecord, 'baseLangSysCount') // in alphabetical order by BaseLangSysTag
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
let BaseScriptRecord = new r.Struct({
|
|
54
|
+
tag: new r.String(4), // 4-byte script identification tag
|
|
55
|
+
script: new r.Pointer(r.uint16, BaseScript, {type: 'parent'})
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
let BaseScriptList = new r.Array(BaseScriptRecord, r.uint16);
|
|
59
|
+
|
|
60
|
+
// Array of 4-byte baseline identification tags-must be in alphabetical order
|
|
61
|
+
let BaseTagList = new r.Array(new r.String(4), r.uint16);
|
|
62
|
+
|
|
63
|
+
let Axis = new r.Struct({
|
|
64
|
+
baseTagList: new r.Pointer(r.uint16, BaseTagList), // May be NULL
|
|
65
|
+
baseScriptList: new r.Pointer(r.uint16, BaseScriptList)
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export default new r.VersionedStruct(r.uint32, {
|
|
69
|
+
header: {
|
|
70
|
+
horizAxis: new r.Pointer(r.uint16, Axis), // May be NULL
|
|
71
|
+
vertAxis: new r.Pointer(r.uint16, Axis) // May be NULL
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
0x00010000: {},
|
|
75
|
+
0x00010001: {
|
|
76
|
+
itemVariationStore: new r.Pointer(r.uint32, ItemVariationStore)
|
|
77
|
+
}
|
|
78
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as r from 'restructure';
|
|
2
|
+
|
|
3
|
+
let LayerRecord = new r.Struct({
|
|
4
|
+
gid: r.uint16, // Glyph ID of layer glyph (must be in z-order from bottom to top).
|
|
5
|
+
paletteIndex: r.uint16 // Index value to use in the appropriate palette. This value must
|
|
6
|
+
}); // be less than numPaletteEntries in the CPAL table, except for
|
|
7
|
+
// the special case noted below. Each palette entry is 16 bits.
|
|
8
|
+
// A palette index of 0xFFFF is a special case indicating that
|
|
9
|
+
// the text foreground color should be used.
|
|
10
|
+
|
|
11
|
+
let BaseGlyphRecord = new r.Struct({
|
|
12
|
+
gid: r.uint16, // Glyph ID of reference glyph. This glyph is for reference only
|
|
13
|
+
// and is not rendered for color.
|
|
14
|
+
firstLayerIndex: r.uint16, // Index (from beginning of the Layer Records) to the layer record.
|
|
15
|
+
// There will be numLayers consecutive entries for this base glyph.
|
|
16
|
+
numLayers: r.uint16
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export default new r.Struct({
|
|
20
|
+
version: r.uint16,
|
|
21
|
+
numBaseGlyphRecords: r.uint16,
|
|
22
|
+
baseGlyphRecord: new r.Pointer(r.uint32, new r.Array(BaseGlyphRecord, 'numBaseGlyphRecords')),
|
|
23
|
+
layerRecords: new r.Pointer(r.uint32, new r.Array(LayerRecord, 'numLayerRecords'), { lazy: true }),
|
|
24
|
+
numLayerRecords: r.uint16
|
|
25
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as r from 'restructure';
|
|
2
|
+
|
|
3
|
+
let ColorRecord = new r.Struct({
|
|
4
|
+
blue: r.uint8,
|
|
5
|
+
green: r.uint8,
|
|
6
|
+
red: r.uint8,
|
|
7
|
+
alpha: r.uint8
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export default new r.VersionedStruct(r.uint16, {
|
|
11
|
+
header: {
|
|
12
|
+
numPaletteEntries: r.uint16,
|
|
13
|
+
numPalettes: r.uint16,
|
|
14
|
+
numColorRecords: r.uint16,
|
|
15
|
+
colorRecords: new r.Pointer(r.uint32, new r.Array(ColorRecord, 'numColorRecords')),
|
|
16
|
+
colorRecordIndices: new r.Array(r.uint16, 'numPalettes'),
|
|
17
|
+
},
|
|
18
|
+
0: {},
|
|
19
|
+
1: {
|
|
20
|
+
offsetPaletteTypeArray: new r.Pointer(r.uint32, new r.Array(r.uint32, 'numPalettes')),
|
|
21
|
+
offsetPaletteLabelArray: new r.Pointer(r.uint32, new r.Array(r.uint16, 'numPalettes')),
|
|
22
|
+
offsetPaletteEntryLabelArray: new r.Pointer(r.uint32, new r.Array(r.uint16, 'numPaletteEntries'))
|
|
23
|
+
}
|
|
24
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as r from 'restructure';
|
|
2
|
+
|
|
3
|
+
let Signature = new r.Struct({
|
|
4
|
+
format: r.uint32,
|
|
5
|
+
length: r.uint32,
|
|
6
|
+
offset: r.uint32
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
let SignatureBlock = new r.Struct({
|
|
10
|
+
reserved: new r.Reserved(r.uint16, 2),
|
|
11
|
+
cbSignature: r.uint32, // Length (in bytes) of the PKCS#7 packet in pbSignature
|
|
12
|
+
signature: new r.Buffer('cbSignature')
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export default new r.Struct({
|
|
16
|
+
ulVersion: r.uint32, // Version number of the DSIG table (0x00000001)
|
|
17
|
+
usNumSigs: r.uint16, // Number of signatures in the table
|
|
18
|
+
usFlag: r.uint16, // Permission flags
|
|
19
|
+
signatures: new r.Array(Signature, 'usNumSigs'),
|
|
20
|
+
signatureBlocks: new r.Array(SignatureBlock, 'usNumSigs')
|
|
21
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as r from 'restructure';
|
|
2
|
+
|
|
3
|
+
export let BigMetrics = new r.Struct({
|
|
4
|
+
height: r.uint8,
|
|
5
|
+
width: r.uint8,
|
|
6
|
+
horiBearingX: r.int8,
|
|
7
|
+
horiBearingY: r.int8,
|
|
8
|
+
horiAdvance: r.uint8,
|
|
9
|
+
vertBearingX: r.int8,
|
|
10
|
+
vertBearingY: r.int8,
|
|
11
|
+
vertAdvance: r.uint8
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export let SmallMetrics = new r.Struct({
|
|
15
|
+
height: r.uint8,
|
|
16
|
+
width: r.uint8,
|
|
17
|
+
bearingX: r.int8,
|
|
18
|
+
bearingY: r.int8,
|
|
19
|
+
advance: r.uint8
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
let EBDTComponent = new r.Struct({
|
|
23
|
+
glyph: r.uint16,
|
|
24
|
+
xOffset: r.int8,
|
|
25
|
+
yOffset: r.int8
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
class ByteAligned {}
|
|
29
|
+
|
|
30
|
+
class BitAligned {}
|
|
31
|
+
|
|
32
|
+
export let glyph = new r.VersionedStruct('version', {
|
|
33
|
+
1: {
|
|
34
|
+
metrics: SmallMetrics,
|
|
35
|
+
data: ByteAligned
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
2: {
|
|
39
|
+
metrics: SmallMetrics,
|
|
40
|
+
data: BitAligned
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
// format 3 is deprecated
|
|
44
|
+
// format 4 is not supported by Microsoft
|
|
45
|
+
|
|
46
|
+
5: {
|
|
47
|
+
data: BitAligned
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
6: {
|
|
51
|
+
metrics: BigMetrics,
|
|
52
|
+
data: ByteAligned
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
7: {
|
|
56
|
+
metrics: BigMetrics,
|
|
57
|
+
data: BitAligned
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
8: {
|
|
61
|
+
metrics: SmallMetrics,
|
|
62
|
+
pad: new r.Reserved(r.uint8),
|
|
63
|
+
numComponents: r.uint16,
|
|
64
|
+
components: new r.Array(EBDTComponent, 'numComponents')
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
9: {
|
|
68
|
+
metrics: BigMetrics,
|
|
69
|
+
pad: new r.Reserved(r.uint8),
|
|
70
|
+
numComponents: r.uint16,
|
|
71
|
+
components: new r.Array(EBDTComponent, 'numComponents')
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
17: {
|
|
75
|
+
metrics: SmallMetrics,
|
|
76
|
+
dataLen: r.uint32,
|
|
77
|
+
data: new r.Buffer('dataLen')
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
18: {
|
|
81
|
+
metrics: BigMetrics,
|
|
82
|
+
dataLen: r.uint32,
|
|
83
|
+
data: new r.Buffer('dataLen')
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
19: {
|
|
87
|
+
dataLen: r.uint32,
|
|
88
|
+
data: new r.Buffer('dataLen')
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as r from 'restructure';
|
|
2
|
+
import {BigMetrics} from './EBDT';
|
|
3
|
+
|
|
4
|
+
let SBitLineMetrics = new r.Struct({
|
|
5
|
+
ascender: r.int8,
|
|
6
|
+
descender: r.int8,
|
|
7
|
+
widthMax: r.uint8,
|
|
8
|
+
caretSlopeNumerator: r.int8,
|
|
9
|
+
caretSlopeDenominator: r.int8,
|
|
10
|
+
caretOffset: r.int8,
|
|
11
|
+
minOriginSB: r.int8,
|
|
12
|
+
minAdvanceSB: r.int8,
|
|
13
|
+
maxBeforeBL: r.int8,
|
|
14
|
+
minAfterBL: r.int8,
|
|
15
|
+
pad: new r.Reserved(r.int8, 2)
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
let CodeOffsetPair = new r.Struct({
|
|
19
|
+
glyphCode: r.uint16,
|
|
20
|
+
offset: r.uint16
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
let IndexSubtable = new r.VersionedStruct(r.uint16, {
|
|
24
|
+
header: {
|
|
25
|
+
imageFormat: r.uint16,
|
|
26
|
+
imageDataOffset: r.uint32
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
1: {
|
|
30
|
+
offsetArray: new r.Array(r.uint32, t => t.parent.lastGlyphIndex - t.parent.firstGlyphIndex + 1)
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
2: {
|
|
34
|
+
imageSize: r.uint32,
|
|
35
|
+
bigMetrics: BigMetrics
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
3: {
|
|
39
|
+
offsetArray: new r.Array(r.uint16, t => t.parent.lastGlyphIndex - t.parent.firstGlyphIndex + 1)
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
4: {
|
|
43
|
+
numGlyphs: r.uint32,
|
|
44
|
+
glyphArray: new r.Array(CodeOffsetPair, t => t.numGlyphs + 1)
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
5: {
|
|
48
|
+
imageSize: r.uint32,
|
|
49
|
+
bigMetrics: BigMetrics,
|
|
50
|
+
numGlyphs: r.uint32,
|
|
51
|
+
glyphCodeArray: new r.Array(r.uint16, 'numGlyphs')
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
let IndexSubtableArray = new r.Struct({
|
|
56
|
+
firstGlyphIndex: r.uint16,
|
|
57
|
+
lastGlyphIndex: r.uint16,
|
|
58
|
+
subtable: new r.Pointer(r.uint32, IndexSubtable)
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
let BitmapSizeTable = new r.Struct({
|
|
62
|
+
indexSubTableArray: new r.Pointer(r.uint32, new r.Array(IndexSubtableArray, 1), { type: 'parent' }),
|
|
63
|
+
indexTablesSize: r.uint32,
|
|
64
|
+
numberOfIndexSubTables: r.uint32,
|
|
65
|
+
colorRef: r.uint32,
|
|
66
|
+
hori: SBitLineMetrics,
|
|
67
|
+
vert: SBitLineMetrics,
|
|
68
|
+
startGlyphIndex: r.uint16,
|
|
69
|
+
endGlyphIndex: r.uint16,
|
|
70
|
+
ppemX: r.uint8,
|
|
71
|
+
ppemY: r.uint8,
|
|
72
|
+
bitDepth: r.uint8,
|
|
73
|
+
flags: new r.Bitfield(r.uint8, ['horizontal', 'vertical'])
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
export default new r.Struct({
|
|
77
|
+
version: r.uint32, // 0x00020000
|
|
78
|
+
numSizes: r.uint32,
|
|
79
|
+
sizes: new r.Array(BitmapSizeTable, 'numSizes')
|
|
80
|
+
});
|