@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,166 @@
|
|
|
1
|
+
import isEqual from 'fast-deep-equal';
|
|
2
|
+
import CFFOperand from './CFFOperand';
|
|
3
|
+
import { PropertyDescriptor } from 'restructure';
|
|
4
|
+
|
|
5
|
+
export default class CFFDict {
|
|
6
|
+
constructor(ops = []) {
|
|
7
|
+
this.ops = ops;
|
|
8
|
+
this.fields = {};
|
|
9
|
+
for (let field of ops) {
|
|
10
|
+
let key = Array.isArray(field[0]) ? field[0][0] << 8 | field[0][1] : field[0];
|
|
11
|
+
this.fields[key] = field;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
decodeOperands(type, stream, ret, operands) {
|
|
16
|
+
if (Array.isArray(type)) {
|
|
17
|
+
return operands.map((op, i) => this.decodeOperands(type[i], stream, ret, [op]));
|
|
18
|
+
} else if (type.decode != null) {
|
|
19
|
+
return type.decode(stream, ret, operands);
|
|
20
|
+
} else {
|
|
21
|
+
switch (type) {
|
|
22
|
+
case 'number':
|
|
23
|
+
case 'offset':
|
|
24
|
+
case 'sid':
|
|
25
|
+
return operands[0];
|
|
26
|
+
case 'boolean':
|
|
27
|
+
return !!operands[0];
|
|
28
|
+
default:
|
|
29
|
+
return operands;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
encodeOperands(type, stream, ctx, operands) {
|
|
35
|
+
if (Array.isArray(type)) {
|
|
36
|
+
return operands.map((op, i) => this.encodeOperands(type[i], stream, ctx, op)[0]);
|
|
37
|
+
} else if (type.encode != null) {
|
|
38
|
+
return type.encode(stream, operands, ctx);
|
|
39
|
+
} else if (typeof operands === 'number') {
|
|
40
|
+
return [operands];
|
|
41
|
+
} else if (typeof operands === 'boolean') {
|
|
42
|
+
return [+operands];
|
|
43
|
+
} else if (Array.isArray(operands)) {
|
|
44
|
+
return operands;
|
|
45
|
+
} else {
|
|
46
|
+
return [operands];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
decode(stream, parent) {
|
|
51
|
+
let end = stream.pos + parent.length;
|
|
52
|
+
let ret = {};
|
|
53
|
+
let operands = [];
|
|
54
|
+
|
|
55
|
+
// define hidden properties
|
|
56
|
+
Object.defineProperties(ret, {
|
|
57
|
+
parent: { value: parent },
|
|
58
|
+
_startOffset: { value: stream.pos }
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// fill in defaults
|
|
62
|
+
for (let key in this.fields) {
|
|
63
|
+
let field = this.fields[key];
|
|
64
|
+
ret[field[1]] = field[3];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
while (stream.pos < end) {
|
|
68
|
+
let b = stream.readUInt8();
|
|
69
|
+
if (b < 28) {
|
|
70
|
+
if (b === 12) {
|
|
71
|
+
b = (b << 8) | stream.readUInt8();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let field = this.fields[b];
|
|
75
|
+
if (!field) {
|
|
76
|
+
throw new Error(`Unknown operator ${b}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let val = this.decodeOperands(field[2], stream, ret, operands);
|
|
80
|
+
if (val != null) {
|
|
81
|
+
if (val instanceof PropertyDescriptor) {
|
|
82
|
+
Object.defineProperty(ret, field[1], val);
|
|
83
|
+
} else {
|
|
84
|
+
ret[field[1]] = val;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
operands = [];
|
|
89
|
+
} else {
|
|
90
|
+
operands.push(CFFOperand.decode(stream, b));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return ret;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
size(dict, parent, includePointers = true) {
|
|
98
|
+
let ctx = {
|
|
99
|
+
parent,
|
|
100
|
+
val: dict,
|
|
101
|
+
pointerSize: 0,
|
|
102
|
+
startOffset: parent.startOffset || 0
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
let len = 0;
|
|
106
|
+
|
|
107
|
+
for (let k in this.fields) {
|
|
108
|
+
let field = this.fields[k];
|
|
109
|
+
let val = dict[field[1]];
|
|
110
|
+
if (val == null || isEqual(val, field[3])) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let operands = this.encodeOperands(field[2], null, ctx, val);
|
|
115
|
+
for (let op of operands) {
|
|
116
|
+
len += CFFOperand.size(op);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let key = Array.isArray(field[0]) ? field[0] : [field[0]];
|
|
120
|
+
len += key.length;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (includePointers) {
|
|
124
|
+
len += ctx.pointerSize;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return len;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
encode(stream, dict, parent) {
|
|
131
|
+
let ctx = {
|
|
132
|
+
pointers: [],
|
|
133
|
+
startOffset: stream.pos,
|
|
134
|
+
parent,
|
|
135
|
+
val: dict,
|
|
136
|
+
pointerSize: 0
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
ctx.pointerOffset = stream.pos + this.size(dict, ctx, false);
|
|
140
|
+
|
|
141
|
+
for (let field of this.ops) {
|
|
142
|
+
let val = dict[field[1]];
|
|
143
|
+
if (val == null || isEqual(val, field[3])) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let operands = this.encodeOperands(field[2], stream, ctx, val);
|
|
148
|
+
for (let op of operands) {
|
|
149
|
+
CFFOperand.encode(stream, op);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
let key = Array.isArray(field[0]) ? field[0] : [field[0]];
|
|
153
|
+
for (let op of key) {
|
|
154
|
+
stream.writeUInt8(op);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let i = 0;
|
|
159
|
+
while (i < ctx.pointers.length) {
|
|
160
|
+
let ptr = ctx.pointers[i++];
|
|
161
|
+
ptr.type.encode(stream, ptr.val, ptr.parent);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export let StandardEncoding = [
|
|
2
|
+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
3
|
+
'', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright',
|
|
4
|
+
'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',
|
|
5
|
+
'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',
|
|
6
|
+
'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
|
|
7
|
+
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
|
|
8
|
+
'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
|
9
|
+
'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', '', '', '', '', '', '', '',
|
|
10
|
+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
11
|
+
'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle',
|
|
12
|
+
'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger',
|
|
13
|
+
'daggerdbl', 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright',
|
|
14
|
+
'guillemotright', 'ellipsis', 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', 'tilde',
|
|
15
|
+
'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', '', 'hungarumlaut', 'ogonek', 'caron',
|
|
16
|
+
'emdash', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', '',
|
|
17
|
+
'', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '',
|
|
18
|
+
'lslash', 'oslash', 'oe', 'germandbls'
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
export let ExpertEncoding = [
|
|
22
|
+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
23
|
+
'', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', 'dollarsuperior',
|
|
24
|
+
'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader',
|
|
25
|
+
'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
|
|
26
|
+
'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',
|
|
27
|
+
'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', '', 'asuperior',
|
|
28
|
+
'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior',
|
|
29
|
+
'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', '', 'ff', 'fi', 'fl', 'ffi', 'ffl',
|
|
30
|
+
'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall',
|
|
31
|
+
'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall',
|
|
32
|
+
'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
|
|
33
|
+
'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '',
|
|
34
|
+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
35
|
+
'exclamdownsmall', 'centoldstyle', 'Lslashsmall', '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
|
|
36
|
+
'Brevesmall', 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', 'figuredash', 'hypheninferior',
|
|
37
|
+
'', '', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',
|
|
38
|
+
'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', '',
|
|
39
|
+
'', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
|
|
40
|
+
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
|
|
41
|
+
'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior',
|
|
42
|
+
'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
|
|
43
|
+
'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall',
|
|
44
|
+
'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
|
|
45
|
+
'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall',
|
|
46
|
+
'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
|
|
47
|
+
'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall'
|
|
48
|
+
];
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import CFFTop from './CFFTop';
|
|
2
|
+
import standardStrings from './CFFStandardStrings';
|
|
3
|
+
|
|
4
|
+
class CFFFont {
|
|
5
|
+
constructor(stream) {
|
|
6
|
+
this.stream = stream;
|
|
7
|
+
this.decode();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static decode(stream) {
|
|
11
|
+
return new CFFFont(stream);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
decode() {
|
|
15
|
+
let top = CFFTop.decode(this.stream);
|
|
16
|
+
for (let key in top) {
|
|
17
|
+
let val = top[key];
|
|
18
|
+
this[key] = val;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (this.version < 2) {
|
|
22
|
+
if (this.topDictIndex.length !== 1) {
|
|
23
|
+
throw new Error("Only a single font is allowed in CFF");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
this.topDict = this.topDictIndex[0];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.isCIDFont = this.topDict.ROS != null;
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
string(sid) {
|
|
34
|
+
if (this.version >= 2) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (sid < standardStrings.length) {
|
|
39
|
+
return standardStrings[sid];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return this.stringIndex[sid - standardStrings.length];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get postscriptName() {
|
|
46
|
+
if (this.version < 2) {
|
|
47
|
+
return this.nameIndex[0];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get fullName() {
|
|
54
|
+
return this.string(this.topDict.FullName);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get familyName() {
|
|
58
|
+
return this.string(this.topDict.FamilyName);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
getCharString(glyph) {
|
|
62
|
+
this.stream.pos = this.topDict.CharStrings[glyph].offset;
|
|
63
|
+
return this.stream.readBuffer(this.topDict.CharStrings[glyph].length);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getGlyphName(gid) {
|
|
67
|
+
// CFF2 glyph names are in the post table.
|
|
68
|
+
if (this.version >= 2) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// CID-keyed fonts don't have glyph names
|
|
73
|
+
if (this.isCIDFont) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let { charset } = this.topDict;
|
|
78
|
+
if (Array.isArray(charset)) {
|
|
79
|
+
return charset[gid];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (gid === 0) {
|
|
83
|
+
return '.notdef';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
gid -= 1;
|
|
87
|
+
|
|
88
|
+
switch (charset.version) {
|
|
89
|
+
case 0:
|
|
90
|
+
return this.string(charset.glyphs[gid]);
|
|
91
|
+
|
|
92
|
+
case 1:
|
|
93
|
+
case 2:
|
|
94
|
+
for (let i = 0; i < charset.ranges.length; i++) {
|
|
95
|
+
let range = charset.ranges[i];
|
|
96
|
+
if (range.offset <= gid && gid <= range.offset + range.nLeft) {
|
|
97
|
+
return this.string(range.first + (gid - range.offset));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
fdForGlyph(gid) {
|
|
107
|
+
if (!this.topDict.FDSelect) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
switch (this.topDict.FDSelect.version) {
|
|
112
|
+
case 0:
|
|
113
|
+
return this.topDict.FDSelect.fds[gid];
|
|
114
|
+
|
|
115
|
+
case 3:
|
|
116
|
+
case 4: {
|
|
117
|
+
let { ranges } = this.topDict.FDSelect;
|
|
118
|
+
let low = 0;
|
|
119
|
+
let high = ranges.length - 1;
|
|
120
|
+
|
|
121
|
+
while (low <= high) {
|
|
122
|
+
let mid = (low + high) >> 1;
|
|
123
|
+
|
|
124
|
+
if (gid < ranges[mid].first) {
|
|
125
|
+
high = mid - 1;
|
|
126
|
+
} else if (mid < high && gid >= ranges[mid + 1].first) {
|
|
127
|
+
low = mid + 1;
|
|
128
|
+
} else {
|
|
129
|
+
return ranges[mid].fd;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
throw new Error(`Unknown FDSelect version: ${this.topDict.FDSelect.version}`);
|
|
134
|
+
}
|
|
135
|
+
default:
|
|
136
|
+
throw new Error(`Unknown FDSelect version: ${this.topDict.FDSelect.version}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
privateDictForGlyph(gid) {
|
|
141
|
+
if (this.topDict.FDSelect) {
|
|
142
|
+
let fd = this.fdForGlyph(gid);
|
|
143
|
+
if (this.topDict.FDArray[fd]) {
|
|
144
|
+
return this.topDict.FDArray[fd].Private;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (this.version < 2) {
|
|
151
|
+
return this.topDict.Private;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return this.topDict.FDArray[0].Private;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export default CFFFont;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import * as r from 'restructure';
|
|
2
|
+
|
|
3
|
+
export default class CFFIndex {
|
|
4
|
+
constructor(type) {
|
|
5
|
+
this.type = type;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
getCFFVersion(ctx) {
|
|
9
|
+
while (ctx && !ctx.hdrSize) {
|
|
10
|
+
ctx = ctx.parent;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return ctx ? ctx.version : -1;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
decode(stream, parent) {
|
|
17
|
+
let version = this.getCFFVersion(parent);
|
|
18
|
+
let count = version >= 2
|
|
19
|
+
? stream.readUInt32BE()
|
|
20
|
+
: stream.readUInt16BE();
|
|
21
|
+
|
|
22
|
+
if (count === 0) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let offSize = stream.readUInt8();
|
|
27
|
+
let offsetType;
|
|
28
|
+
if (offSize === 1) {
|
|
29
|
+
offsetType = r.uint8;
|
|
30
|
+
} else if (offSize === 2) {
|
|
31
|
+
offsetType = r.uint16;
|
|
32
|
+
} else if (offSize === 3) {
|
|
33
|
+
offsetType = r.uint24;
|
|
34
|
+
} else if (offSize === 4) {
|
|
35
|
+
offsetType = r.uint32;
|
|
36
|
+
} else {
|
|
37
|
+
throw new Error(`Bad offset size in CFFIndex: ${offSize} ${stream.pos}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let ret = [];
|
|
41
|
+
let startPos = stream.pos + ((count + 1) * offSize) - 1;
|
|
42
|
+
|
|
43
|
+
let start = offsetType.decode(stream);
|
|
44
|
+
for (let i = 0; i < count; i++) {
|
|
45
|
+
let end = offsetType.decode(stream);
|
|
46
|
+
|
|
47
|
+
if (this.type != null) {
|
|
48
|
+
let pos = stream.pos;
|
|
49
|
+
stream.pos = startPos + start;
|
|
50
|
+
|
|
51
|
+
parent.length = end - start;
|
|
52
|
+
ret.push(this.type.decode(stream, parent));
|
|
53
|
+
stream.pos = pos;
|
|
54
|
+
} else {
|
|
55
|
+
ret.push({
|
|
56
|
+
offset: startPos + start,
|
|
57
|
+
length: end - start
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
start = end;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
stream.pos = startPos + start;
|
|
65
|
+
return ret;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
size(arr, parent) {
|
|
69
|
+
let size = 2;
|
|
70
|
+
if (arr.length === 0) {
|
|
71
|
+
return size;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let type = this.type || new r.Buffer;
|
|
75
|
+
|
|
76
|
+
// find maximum offset to detminine offset type
|
|
77
|
+
let offset = 1;
|
|
78
|
+
for (let i = 0; i < arr.length; i++) {
|
|
79
|
+
let item = arr[i];
|
|
80
|
+
offset += type.size(item, parent);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let offsetType;
|
|
84
|
+
if (offset <= 0xff) {
|
|
85
|
+
offsetType = r.uint8;
|
|
86
|
+
} else if (offset <= 0xffff) {
|
|
87
|
+
offsetType = r.uint16;
|
|
88
|
+
} else if (offset <= 0xffffff) {
|
|
89
|
+
offsetType = r.uint24;
|
|
90
|
+
} else if (offset <= 0xffffffff) {
|
|
91
|
+
offsetType = r.uint32;
|
|
92
|
+
} else {
|
|
93
|
+
throw new Error("Bad offset in CFFIndex");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
size += 1 + offsetType.size() * (arr.length + 1);
|
|
97
|
+
size += offset - 1;
|
|
98
|
+
|
|
99
|
+
return size;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
encode(stream, arr, parent) {
|
|
103
|
+
stream.writeUInt16BE(arr.length);
|
|
104
|
+
if (arr.length === 0) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let type = this.type || new r.Buffer;
|
|
109
|
+
|
|
110
|
+
// find maximum offset to detminine offset type
|
|
111
|
+
let sizes = [];
|
|
112
|
+
let offset = 1;
|
|
113
|
+
for (let item of arr) {
|
|
114
|
+
let s = type.size(item, parent);
|
|
115
|
+
sizes.push(s);
|
|
116
|
+
offset += s;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let offsetType;
|
|
120
|
+
if (offset <= 0xff) {
|
|
121
|
+
offsetType = r.uint8;
|
|
122
|
+
} else if (offset <= 0xffff) {
|
|
123
|
+
offsetType = r.uint16;
|
|
124
|
+
} else if (offset <= 0xffffff) {
|
|
125
|
+
offsetType = r.uint24;
|
|
126
|
+
} else if (offset <= 0xffffffff) {
|
|
127
|
+
offsetType = r.uint32;
|
|
128
|
+
} else {
|
|
129
|
+
throw new Error("Bad offset in CFFIndex");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// write offset size
|
|
133
|
+
stream.writeUInt8(offsetType.size());
|
|
134
|
+
|
|
135
|
+
// write elements
|
|
136
|
+
offset = 1;
|
|
137
|
+
offsetType.encode(stream, offset);
|
|
138
|
+
|
|
139
|
+
for (let size of sizes) {
|
|
140
|
+
offset += size;
|
|
141
|
+
offsetType.encode(stream, offset);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
for (let item of arr) {
|
|
145
|
+
type.encode(stream, item, parent);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
const FLOAT_EOF = 0xf;
|
|
2
|
+
const FLOAT_LOOKUP = [
|
|
3
|
+
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
4
|
+
'8', '9', '.', 'E', 'E-', null, '-'
|
|
5
|
+
];
|
|
6
|
+
|
|
7
|
+
const FLOAT_ENCODE_LOOKUP = {
|
|
8
|
+
'.': 10,
|
|
9
|
+
'E': 11,
|
|
10
|
+
'E-': 12,
|
|
11
|
+
'-': 14
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default class CFFOperand {
|
|
15
|
+
static decode(stream, value) {
|
|
16
|
+
if (32 <= value && value <= 246) {
|
|
17
|
+
return value - 139;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (247 <= value && value <= 250) {
|
|
21
|
+
return (value - 247) * 256 + stream.readUInt8() + 108;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (251 <= value && value <= 254) {
|
|
25
|
+
return -(value - 251) * 256 - stream.readUInt8() - 108;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (value === 28) {
|
|
29
|
+
return stream.readInt16BE();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (value === 29) {
|
|
33
|
+
return stream.readInt32BE();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (value === 30) {
|
|
37
|
+
let str = '';
|
|
38
|
+
while (true) {
|
|
39
|
+
let b = stream.readUInt8();
|
|
40
|
+
|
|
41
|
+
let n1 = b >> 4;
|
|
42
|
+
if (n1 === FLOAT_EOF) { break; }
|
|
43
|
+
str += FLOAT_LOOKUP[n1];
|
|
44
|
+
|
|
45
|
+
let n2 = b & 15;
|
|
46
|
+
if (n2 === FLOAT_EOF) { break; }
|
|
47
|
+
str += FLOAT_LOOKUP[n2];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return parseFloat(str);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static size(value) {
|
|
57
|
+
// if the value needs to be forced to the largest size (32 bit)
|
|
58
|
+
// e.g. for unknown pointers, set to 32768
|
|
59
|
+
if (value.forceLarge) {
|
|
60
|
+
value = 32768;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if ((value | 0) !== value) { // floating point
|
|
64
|
+
let str = '' + value;
|
|
65
|
+
return 1 + Math.ceil((str.length + 1) / 2);
|
|
66
|
+
|
|
67
|
+
} else if (-107 <= value && value <= 107) {
|
|
68
|
+
return 1;
|
|
69
|
+
|
|
70
|
+
} else if (108 <= value && value <= 1131 || -1131 <= value && value <= -108) {
|
|
71
|
+
return 2;
|
|
72
|
+
|
|
73
|
+
} else if (-32768 <= value && value <= 32767) {
|
|
74
|
+
return 3;
|
|
75
|
+
|
|
76
|
+
} else {
|
|
77
|
+
return 5;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static encode(stream, value) {
|
|
82
|
+
// if the value needs to be forced to the largest size (32 bit)
|
|
83
|
+
// e.g. for unknown pointers, save the old value and set to 32768
|
|
84
|
+
let val = Number(value);
|
|
85
|
+
|
|
86
|
+
if (value.forceLarge) {
|
|
87
|
+
stream.writeUInt8(29);
|
|
88
|
+
return stream.writeInt32BE(val);
|
|
89
|
+
|
|
90
|
+
} else if ((val | 0) !== val) { // floating point
|
|
91
|
+
stream.writeUInt8(30);
|
|
92
|
+
|
|
93
|
+
let str = '' + val;
|
|
94
|
+
let n2;
|
|
95
|
+
for (let i = 0; i < str.length; i += 2) {
|
|
96
|
+
let c1 = str[i];
|
|
97
|
+
let n1 = FLOAT_ENCODE_LOOKUP[c1] || +c1;
|
|
98
|
+
|
|
99
|
+
if (i === str.length - 1) {
|
|
100
|
+
n2 = FLOAT_EOF;
|
|
101
|
+
} else {
|
|
102
|
+
let c2 = str[i + 1];
|
|
103
|
+
n2 = FLOAT_ENCODE_LOOKUP[c2] || +c2;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
stream.writeUInt8((n1 << 4) | (n2 & 15));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (n2 !== FLOAT_EOF) {
|
|
110
|
+
return stream.writeUInt8((FLOAT_EOF << 4));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
} else if (-107 <= val && val <= 107) {
|
|
114
|
+
return stream.writeUInt8(val + 139);
|
|
115
|
+
|
|
116
|
+
} else if (108 <= val && val <= 1131) {
|
|
117
|
+
val -= 108;
|
|
118
|
+
stream.writeUInt8((val >> 8) + 247);
|
|
119
|
+
return stream.writeUInt8(val & 0xff);
|
|
120
|
+
|
|
121
|
+
} else if (-1131 <= val && val <= -108) {
|
|
122
|
+
val = -val - 108;
|
|
123
|
+
stream.writeUInt8((val >> 8) + 251);
|
|
124
|
+
return stream.writeUInt8(val & 0xff);
|
|
125
|
+
|
|
126
|
+
} else if (-32768 <= val && val <= 32767) {
|
|
127
|
+
stream.writeUInt8(28);
|
|
128
|
+
return stream.writeInt16BE(val);
|
|
129
|
+
|
|
130
|
+
} else {
|
|
131
|
+
stream.writeUInt8(29);
|
|
132
|
+
return stream.writeInt32BE(val);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|