@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.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +274 -0
  3. package/dist/browser-module.mjs +13660 -0
  4. package/dist/browser-module.mjs.map +1 -0
  5. package/dist/browser.cjs +13689 -0
  6. package/dist/browser.cjs.map +1 -0
  7. package/dist/main.cjs +13712 -0
  8. package/dist/main.cjs.map +1 -0
  9. package/dist/module.mjs +13673 -0
  10. package/dist/module.mjs.map +1 -0
  11. package/package.json +99 -0
  12. package/src/CmapProcessor.js +285 -0
  13. package/src/DFont.js +113 -0
  14. package/src/TTFFont.js +621 -0
  15. package/src/TrueTypeCollection.js +65 -0
  16. package/src/WOFF2Font.js +222 -0
  17. package/src/WOFFFont.js +56 -0
  18. package/src/aat/AATFeatureMap.js +545 -0
  19. package/src/aat/AATLayoutEngine.js +48 -0
  20. package/src/aat/AATLookupTable.js +125 -0
  21. package/src/aat/AATMorxProcessor.js +429 -0
  22. package/src/aat/AATStateMachine.js +96 -0
  23. package/src/base.js +29 -0
  24. package/src/cff/CFFCharsets.js +99 -0
  25. package/src/cff/CFFDict.js +166 -0
  26. package/src/cff/CFFEncodings.js +48 -0
  27. package/src/cff/CFFFont.js +158 -0
  28. package/src/cff/CFFIndex.js +150 -0
  29. package/src/cff/CFFOperand.js +135 -0
  30. package/src/cff/CFFPointer.js +50 -0
  31. package/src/cff/CFFPrivateDict.js +39 -0
  32. package/src/cff/CFFStandardStrings.js +71 -0
  33. package/src/cff/CFFTop.js +236 -0
  34. package/src/decorators.js +36 -0
  35. package/src/encodings.js +219 -0
  36. package/src/fs.js +12 -0
  37. package/src/glyph/BBox.js +72 -0
  38. package/src/glyph/CBDTGlyph.js +9 -0
  39. package/src/glyph/CFFGlyph.js +635 -0
  40. package/src/glyph/COLRGlyph.js +108 -0
  41. package/src/glyph/Glyph.js +270 -0
  42. package/src/glyph/GlyphVariationProcessor.js +487 -0
  43. package/src/glyph/Path.js +257 -0
  44. package/src/glyph/SBIXGlyph.js +54 -0
  45. package/src/glyph/StandardNames.js +27 -0
  46. package/src/glyph/TTFGlyph.js +408 -0
  47. package/src/glyph/TTFGlyphEncoder.js +158 -0
  48. package/src/glyph/WOFF2Glyph.js +70 -0
  49. package/src/index.js +15 -0
  50. package/src/layout/GlyphPosition.js +30 -0
  51. package/src/layout/GlyphRun.js +108 -0
  52. package/src/layout/KernProcessor.js +97 -0
  53. package/src/layout/LayoutEngine.js +190 -0
  54. package/src/layout/Script.js +231 -0
  55. package/src/layout/UnicodeLayoutEngine.js +250 -0
  56. package/src/node.js +16 -0
  57. package/src/opentype/GPOSProcessor.js +311 -0
  58. package/src/opentype/GSUBProcessor.js +208 -0
  59. package/src/opentype/GlyphInfo.js +57 -0
  60. package/src/opentype/GlyphIterator.js +82 -0
  61. package/src/opentype/OTLayoutEngine.js +117 -0
  62. package/src/opentype/OTProcessor.js +472 -0
  63. package/src/opentype/ShapingPlan.js +121 -0
  64. package/src/opentype/shapers/ArabicShaper.js +124 -0
  65. package/src/opentype/shapers/DefaultShaper.js +116 -0
  66. package/src/opentype/shapers/HangulShaper.js +285 -0
  67. package/src/opentype/shapers/HebrewShaper.js +105 -0
  68. package/src/opentype/shapers/IndicShaper.js +914 -0
  69. package/src/opentype/shapers/ThaiShaper.js +238 -0
  70. package/src/opentype/shapers/UniversalShaper.js +186 -0
  71. package/src/opentype/shapers/data.trie +0 -0
  72. package/src/opentype/shapers/gen-indic.js +208 -0
  73. package/src/opentype/shapers/gen-use.js +287 -0
  74. package/src/opentype/shapers/generate-data.js +33 -0
  75. package/src/opentype/shapers/index.js +109 -0
  76. package/src/opentype/shapers/indic-data.js +175 -0
  77. package/src/opentype/shapers/indic.json +1 -0
  78. package/src/opentype/shapers/indic.machine +31 -0
  79. package/src/opentype/shapers/indic.trie +0 -0
  80. package/src/opentype/shapers/use.json +1 -0
  81. package/src/opentype/shapers/use.machine +44 -0
  82. package/src/opentype/shapers/use.trie +0 -0
  83. package/src/packages/unicode-properties/LICENSE +8 -0
  84. package/src/packages/unicode-properties/README.md +12 -0
  85. package/src/packages/unicode-properties/data-trie.js +1 -0
  86. package/src/packages/unicode-properties/data.js +1 -0
  87. package/src/packages/unicode-properties/data.json +1 -0
  88. package/src/packages/unicode-properties/data.trie +0 -0
  89. package/src/packages/unicode-properties/dist/index.cjs +257 -0
  90. package/src/packages/unicode-properties/dist/index.cjs.map +7 -0
  91. package/src/packages/unicode-properties/dist/index.mjs +234 -0
  92. package/src/packages/unicode-properties/dist/index.mjs.map +7 -0
  93. package/src/packages/unicode-properties/generate.js +107 -0
  94. package/src/packages/unicode-properties/index.js +184 -0
  95. package/src/packages/unicode-properties/package.json +50 -0
  96. package/src/packages/unicode-trie/LICENSE +8 -0
  97. package/src/packages/unicode-trie/README.md +13 -0
  98. package/src/packages/unicode-trie/builder.js +965 -0
  99. package/src/packages/unicode-trie/dist/builder.cjs +711 -0
  100. package/src/packages/unicode-trie/dist/builder.cjs.map +7 -0
  101. package/src/packages/unicode-trie/dist/builder.mjs +690 -0
  102. package/src/packages/unicode-trie/dist/builder.mjs.map +7 -0
  103. package/src/packages/unicode-trie/dist/index.cjs +112 -0
  104. package/src/packages/unicode-trie/dist/index.cjs.map +7 -0
  105. package/src/packages/unicode-trie/dist/index.mjs +91 -0
  106. package/src/packages/unicode-trie/dist/index.mjs.map +7 -0
  107. package/src/packages/unicode-trie/index.js +135 -0
  108. package/src/packages/unicode-trie/package.json +49 -0
  109. package/src/packages/unicode-trie/swap.js +21 -0
  110. package/src/subset/CFFSubset.js +176 -0
  111. package/src/subset/Subset.js +63 -0
  112. package/src/subset/TTFSubset.js +130 -0
  113. package/src/tables/BASE.js +78 -0
  114. package/src/tables/COLR.js +25 -0
  115. package/src/tables/CPAL.js +24 -0
  116. package/src/tables/DSIG.js +21 -0
  117. package/src/tables/EBDT.js +91 -0
  118. package/src/tables/EBLC.js +80 -0
  119. package/src/tables/GDEF.js +57 -0
  120. package/src/tables/GPOS.js +209 -0
  121. package/src/tables/GSUB.js +85 -0
  122. package/src/tables/HVAR.js +44 -0
  123. package/src/tables/JSTF.js +43 -0
  124. package/src/tables/LTSH.js +10 -0
  125. package/src/tables/OS2.js +84 -0
  126. package/src/tables/PCLT.js +21 -0
  127. package/src/tables/STAT.js +99 -0
  128. package/src/tables/VDMX.js +33 -0
  129. package/src/tables/VORG.js +14 -0
  130. package/src/tables/WOFF2Directory.js +73 -0
  131. package/src/tables/WOFFDirectory.js +37 -0
  132. package/src/tables/aat.js +157 -0
  133. package/src/tables/avar.js +19 -0
  134. package/src/tables/bsln.js +31 -0
  135. package/src/tables/cmap.js +127 -0
  136. package/src/tables/cvt.js +6 -0
  137. package/src/tables/directory.js +58 -0
  138. package/src/tables/feat.js +28 -0
  139. package/src/tables/fpgm.js +8 -0
  140. package/src/tables/fvar.js +31 -0
  141. package/src/tables/gasp.js +15 -0
  142. package/src/tables/glyf.js +4 -0
  143. package/src/tables/gvar.js +27 -0
  144. package/src/tables/hdmx.js +15 -0
  145. package/src/tables/head.js +25 -0
  146. package/src/tables/hhea.js +19 -0
  147. package/src/tables/hmtx.js +11 -0
  148. package/src/tables/index.js +119 -0
  149. package/src/tables/just.js +81 -0
  150. package/src/tables/kern.js +91 -0
  151. package/src/tables/loca.js +30 -0
  152. package/src/tables/maxp.js +20 -0
  153. package/src/tables/morx.js +79 -0
  154. package/src/tables/name.js +157 -0
  155. package/src/tables/opbd.js +15 -0
  156. package/src/tables/opentype.js +217 -0
  157. package/src/tables/post.js +34 -0
  158. package/src/tables/prep.js +6 -0
  159. package/src/tables/sbix.js +17 -0
  160. package/src/tables/variations.js +80 -0
  161. package/src/tables/vhea.js +19 -0
  162. package/src/tables/vmtx.js +12 -0
  163. package/src/utils.js +62 -0
package/package.json ADDED
@@ -0,0 +1,99 @@
1
+ {
2
+ "name": "@cantoo/fontkit",
3
+ "version": "2.0.4",
4
+ "description": "An advanced font engine for Node and the browser",
5
+ "keywords": [
6
+ "opentype",
7
+ "font",
8
+ "typography",
9
+ "subset",
10
+ "emoji",
11
+ "glyph",
12
+ "layout"
13
+ ],
14
+ "scripts": {
15
+ "clean": "shx rm -rf src/opentype/shapers/data.trie src/opentype/shapers/use.trie src/opentype/shapers/use.json src/opentype/shapers/indic.trie src/opentype/shapers/indic.json dist src/packages/unicode-trie/dist src/packages/unicode-properties/dist",
16
+ "trie:data": "node src/opentype/shapers/generate-data.js",
17
+ "trie:use": "node src/opentype/shapers/gen-use.js",
18
+ "trie:indic": "node src/opentype/shapers/gen-indic.js",
19
+ "tries": "npm run trie:data && npm run trie:use && npm run trie:indic",
20
+ "build:packages": "node scripts/build-unicode-packages.js",
21
+ "build": "npm run build:packages && tsup",
22
+ "prebuild": "node --input-type=module -e \"import fs from 'node:fs'; if (!fs.existsSync('src/opentype/shapers/data.trie')) { console.error('Missing trie files. Run: npm run tries'); process.exit(1); }\"",
23
+ "lint": "eslint .",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "coverage": "vitest run --coverage",
27
+ "prepublishOnly": "npm run tries && npm run build",
28
+ "release": "release-it"
29
+ },
30
+ "type": "module",
31
+ "main": "dist/main.cjs",
32
+ "node-module": "dist/module.mjs",
33
+ "browser": "dist/browser.cjs",
34
+ "module": "dist/browser-module.mjs",
35
+ "source": "src/index.js",
36
+ "exports": {
37
+ ".": {
38
+ "node": {
39
+ "import": "./dist/module.mjs",
40
+ "require": "./dist/main.cjs"
41
+ },
42
+ "import": "./dist/browser-module.mjs",
43
+ "require": "./dist/browser.cjs"
44
+ },
45
+ "./unicode-trie": {
46
+ "import": "./src/packages/unicode-trie/dist/index.mjs",
47
+ "require": "./src/packages/unicode-trie/dist/index.cjs"
48
+ },
49
+ "./unicode-trie/builder.js": {
50
+ "import": "./src/packages/unicode-trie/dist/builder.mjs",
51
+ "require": "./src/packages/unicode-trie/dist/builder.cjs"
52
+ },
53
+ "./unicode-properties": {
54
+ "import": "./src/packages/unicode-properties/dist/index.mjs",
55
+ "require": "./src/packages/unicode-properties/dist/index.cjs"
56
+ },
57
+ "./package.json": "./package.json"
58
+ },
59
+ "files": [
60
+ "src",
61
+ "dist"
62
+ ],
63
+ "author": "Devon Govett <devongovett@gmail.com>",
64
+ "license": "MIT",
65
+ "repository": {
66
+ "type": "git",
67
+ "url": "git://github.com/cantoo-scribe/fontkit.git"
68
+ },
69
+ "publishConfig": {
70
+ "access": "public"
71
+ },
72
+ "dependencies": {
73
+ "brotli": "^1.3.2",
74
+ "clone": "^2.1.2",
75
+ "dfa": "^1.2.0",
76
+ "fast-deep-equal": "^3.1.3",
77
+ "fflate": "^0.8.3",
78
+ "restructure": "^3.0.0"
79
+ },
80
+ "devDependencies": {
81
+ "@babel/core": "^8.0.1",
82
+ "@babel/eslint-parser": "^8.0.1",
83
+ "@babel/plugin-proposal-decorators": "^8.0.2",
84
+ "@eslint/js": "^10.0.1",
85
+ "@vitest/coverage-v8": "^5.0.0",
86
+ "codepoints": "^1.3.0",
87
+ "esbuild": "^0.28.2",
88
+ "eslint": "^10.10.0",
89
+ "globals": "^17.12.0",
90
+ "release-it": "^21.0.2",
91
+ "shx": "^0.4.0",
92
+ "tsup": "^8.5.1",
93
+ "typescript": "^7.0.2",
94
+ "vitest": "^5.0.0"
95
+ },
96
+ "overrides": {
97
+ "esbuild": "^0.28.2"
98
+ }
99
+ }
@@ -0,0 +1,285 @@
1
+ import { binarySearch } from './utils';
2
+ import { getEncoding, getEncodingMapping } from './encodings';
3
+ import { cache } from './decorators';
4
+ import { range } from './utils';
5
+
6
+ export default class CmapProcessor {
7
+ constructor(cmapTable) {
8
+ // Attempt to find a Unicode cmap first
9
+ this.encoding = null;
10
+ this.cmap = this.findSubtable(cmapTable, [
11
+ // 32-bit subtables
12
+ [3, 10],
13
+ [0, 6],
14
+ [0, 4],
15
+
16
+ // 16-bit subtables
17
+ [3, 1],
18
+ [0, 3],
19
+ [0, 2],
20
+ [0, 1],
21
+ [0, 0]
22
+ ]);
23
+
24
+ // If not unicode cmap was found, take the first table with a supported encoding.
25
+ if (!this.cmap) {
26
+ for (let cmap of cmapTable.tables) {
27
+ let encoding = getEncoding(cmap.platformID, cmap.encodingID, cmap.table.language - 1);
28
+ let mapping = getEncodingMapping(encoding);
29
+ if (mapping) {
30
+ this.cmap = cmap.table;
31
+ this.encoding = mapping;
32
+ }
33
+ }
34
+ }
35
+
36
+ if (!this.cmap) {
37
+ throw new Error("Could not find a supported cmap table");
38
+ }
39
+
40
+ this.uvs = this.findSubtable(cmapTable, [[0, 5]]);
41
+ if (this.uvs && this.uvs.version !== 14) {
42
+ this.uvs = null;
43
+ }
44
+ }
45
+
46
+ findSubtable(cmapTable, pairs) {
47
+ for (let [platformID, encodingID] of pairs) {
48
+ for (let cmap of cmapTable.tables) {
49
+ if (cmap.platformID === platformID && cmap.encodingID === encodingID) {
50
+ return cmap.table;
51
+ }
52
+ }
53
+ }
54
+
55
+ return null;
56
+ }
57
+
58
+ lookup(codepoint, variationSelector) {
59
+ // If there is no Unicode cmap in this font, we need to re-encode
60
+ // the codepoint in the encoding that the cmap supports.
61
+ if (this.encoding) {
62
+ codepoint = this.encoding.get(codepoint) || codepoint;
63
+
64
+ // Otherwise, try to get a Unicode variation selector for this codepoint if one is provided.
65
+ } else if (variationSelector) {
66
+ let gid = this.getVariationSelector(codepoint, variationSelector);
67
+ if (gid) {
68
+ return gid;
69
+ }
70
+ }
71
+
72
+ let cmap = this.cmap;
73
+ switch (cmap.version) {
74
+ case 0:
75
+ return cmap.codeMap.get(codepoint) || 0;
76
+
77
+ case 4: {
78
+ let min = 0;
79
+ let max = cmap.segCount - 1;
80
+ while (min <= max) {
81
+ let mid = (min + max) >> 1;
82
+
83
+ if (codepoint < cmap.startCode.get(mid)) {
84
+ max = mid - 1;
85
+ } else if (codepoint > cmap.endCode.get(mid)) {
86
+ min = mid + 1;
87
+ } else {
88
+ let rangeOffset = cmap.idRangeOffset.get(mid);
89
+ let gid;
90
+
91
+ if (rangeOffset === 0) {
92
+ gid = codepoint + cmap.idDelta.get(mid);
93
+ } else {
94
+ let index = rangeOffset / 2 + (codepoint - cmap.startCode.get(mid)) - (cmap.segCount - mid);
95
+ gid = cmap.glyphIndexArray.get(index) || 0;
96
+ if (gid !== 0) {
97
+ gid += cmap.idDelta.get(mid);
98
+ }
99
+ }
100
+
101
+ return gid & 0xffff;
102
+ }
103
+ }
104
+
105
+ return 0;
106
+ }
107
+
108
+ case 8:
109
+ throw new Error('TODO: cmap format 8');
110
+
111
+ case 6:
112
+ case 10:
113
+ return cmap.glyphIndices.get(codepoint - cmap.firstCode) || 0;
114
+
115
+ case 12:
116
+ case 13: {
117
+ let min = 0;
118
+ let max = cmap.nGroups - 1;
119
+ while (min <= max) {
120
+ let mid = (min + max) >> 1;
121
+ let group = cmap.groups.get(mid);
122
+
123
+ if (codepoint < group.startCharCode) {
124
+ max = mid - 1;
125
+ } else if (codepoint > group.endCharCode) {
126
+ min = mid + 1;
127
+ } else {
128
+ if (cmap.version === 12) {
129
+ return group.glyphID + (codepoint - group.startCharCode);
130
+ } else {
131
+ return group.glyphID;
132
+ }
133
+ }
134
+ }
135
+
136
+ return 0;
137
+ }
138
+
139
+ case 14:
140
+ throw new Error('TODO: cmap format 14');
141
+
142
+ default:
143
+ throw new Error(`Unknown cmap format ${cmap.version}`);
144
+ }
145
+ }
146
+
147
+ getVariationSelector(codepoint, variationSelector) {
148
+ if (!this.uvs) {
149
+ return 0;
150
+ }
151
+
152
+ let selectors = this.uvs.varSelectors.toArray();
153
+ let i = binarySearch(selectors, x => variationSelector - x.varSelector);
154
+ if (i === -1) {
155
+ return 0;
156
+ }
157
+
158
+ let {defaultUVS, nonDefaultUVS} = selectors[i];
159
+
160
+ // Default UVS: fall back to the base character's normal cmap glyph.
161
+ if (defaultUVS && binarySearch(defaultUVS, x =>
162
+ codepoint < x.startUnicodeValue ? -1 : codepoint > x.startUnicodeValue + x.additionalCount ? 1 : 0
163
+ ) !== -1) return 0;
164
+
165
+ if (!nonDefaultUVS) return 0;
166
+
167
+ let ni = binarySearch(nonDefaultUVS, x => codepoint - x.unicodeValue);
168
+ return ni !== -1 ? nonDefaultUVS[ni].glyphID : 0;
169
+ }
170
+
171
+ @cache
172
+ getCharacterSet() {
173
+ let cmap = this.cmap;
174
+ switch (cmap.version) {
175
+ case 0:
176
+ return range(0, cmap.codeMap.length);
177
+
178
+ case 4: {
179
+ let res = [];
180
+ let endCodes = cmap.endCode.toArray();
181
+ for (let i = 0; i < endCodes.length; i++) {
182
+ let tail = endCodes[i] + 1;
183
+ let start = cmap.startCode.get(i);
184
+ res.push(...range(start, tail));
185
+ }
186
+
187
+ return res;
188
+ }
189
+
190
+ case 8:
191
+ throw new Error('TODO: cmap format 8');
192
+
193
+ case 6:
194
+ case 10:
195
+ return range(cmap.firstCode, cmap.firstCode + cmap.glyphIndices.length);
196
+
197
+ case 12:
198
+ case 13: {
199
+ let res = [];
200
+ for (let group of cmap.groups.toArray()) {
201
+ res.push(...range(group.startCharCode, group.endCharCode + 1));
202
+ }
203
+
204
+ return res;
205
+ }
206
+
207
+ case 14:
208
+ throw new Error('TODO: cmap format 14');
209
+
210
+ default:
211
+ throw new Error(`Unknown cmap format ${cmap.version}`);
212
+ }
213
+ }
214
+
215
+ @cache
216
+ codePointsForGlyph(gid) {
217
+ let cmap = this.cmap;
218
+ switch (cmap.version) {
219
+ case 0: {
220
+ let res = [];
221
+ for (let i = 0; i < 256; i++) {
222
+ if (cmap.codeMap.get(i) === gid) {
223
+ res.push(i);
224
+ }
225
+ }
226
+
227
+ return res;
228
+ }
229
+
230
+ case 4: {
231
+ let res = [];
232
+ for (let i = 0; i < cmap.segCount; i++) {
233
+ let end = cmap.endCode.get(i);
234
+ let start = cmap.startCode.get(i);
235
+ let rangeOffset = cmap.idRangeOffset.get(i);
236
+ let delta = cmap.idDelta.get(i);
237
+
238
+ for (var c = start; c <= end; c++) {
239
+ let g;
240
+ if (rangeOffset === 0) {
241
+ g = c + delta;
242
+ } else {
243
+ let index = rangeOffset / 2 + (c - start) - (cmap.segCount - i);
244
+ g = cmap.glyphIndexArray.get(index) || 0;
245
+ if (g !== 0) {
246
+ g += delta;
247
+ }
248
+ }
249
+
250
+ if ((g & 0xffff) === gid) {
251
+ res.push(c);
252
+ }
253
+ }
254
+ }
255
+
256
+ return res;
257
+ }
258
+
259
+ case 12: {
260
+ let res = [];
261
+ for (let group of cmap.groups.toArray()) {
262
+ if (gid >= group.glyphID && gid <= group.glyphID + (group.endCharCode - group.startCharCode)) {
263
+ res.push(group.startCharCode + (gid - group.glyphID));
264
+ }
265
+ }
266
+
267
+ return res;
268
+ }
269
+
270
+ case 13: {
271
+ let res = [];
272
+ for (let group of cmap.groups.toArray()) {
273
+ if (gid === group.glyphID) {
274
+ res.push(...range(group.startCharCode, group.endCharCode + 1));
275
+ }
276
+ }
277
+
278
+ return res;
279
+ }
280
+
281
+ default:
282
+ throw new Error(`Unknown cmap format ${cmap.version}`);
283
+ }
284
+ }
285
+ }
package/src/DFont.js ADDED
@@ -0,0 +1,113 @@
1
+ import * as r from 'restructure';
2
+ import TTFFont from './TTFFont';
3
+
4
+ let DFontName = new r.String(r.uint8);
5
+
6
+ let Ref = new r.Struct({
7
+ id: r.uint16,
8
+ nameOffset: r.int16,
9
+ attr: r.uint8,
10
+ dataOffset: r.uint24,
11
+ handle: r.uint32
12
+ });
13
+
14
+ let Type = new r.Struct({
15
+ name: new r.String(4),
16
+ maxTypeIndex: r.uint16,
17
+ refList: new r.Pointer(r.uint16, new r.Array(Ref, t => t.maxTypeIndex + 1), { type: 'parent' })
18
+ });
19
+
20
+ let TypeList = new r.Struct({
21
+ length: r.uint16,
22
+ types: new r.Array(Type, t => t.length + 1)
23
+ });
24
+
25
+ let DFontMap = new r.Struct({
26
+ reserved: new r.Reserved(r.uint8, 24),
27
+ typeList: new r.Pointer(r.uint16, TypeList),
28
+ nameListOffset: new r.Pointer(r.uint16, 'void')
29
+ });
30
+
31
+ let DFontHeader = new r.Struct({
32
+ dataOffset: r.uint32,
33
+ map: new r.Pointer(r.uint32, DFontMap),
34
+ dataLength: r.uint32,
35
+ mapLength: r.uint32
36
+ });
37
+
38
+ export default class DFont {
39
+ type = 'DFont';
40
+
41
+ static probe(buffer) {
42
+ let stream = new r.DecodeStream(buffer);
43
+
44
+ try {
45
+ var header = DFontHeader.decode(stream);
46
+ } catch (e) {
47
+ return false;
48
+ }
49
+
50
+ for (let type of header.map.typeList.types) {
51
+ if (type.name === 'sfnt') {
52
+ return true;
53
+ }
54
+ }
55
+
56
+ return false;
57
+ }
58
+
59
+ constructor(stream) {
60
+ this.stream = stream;
61
+ this.header = DFontHeader.decode(this.stream);
62
+
63
+ for (let type of this.header.map.typeList.types) {
64
+ for (let ref of type.refList) {
65
+ if (ref.nameOffset >= 0) {
66
+ this.stream.pos = ref.nameOffset + this.header.map.nameListOffset;
67
+ ref.name = DFontName.decode(this.stream);
68
+ } else {
69
+ ref.name = null;
70
+ }
71
+ }
72
+
73
+ if (type.name === 'sfnt') {
74
+ this.sfnt = type;
75
+ }
76
+ }
77
+ }
78
+
79
+ getFont(name) {
80
+ if (!this.sfnt) {
81
+ return null;
82
+ }
83
+
84
+ for (let ref of this.sfnt.refList) {
85
+ let pos = this.header.dataOffset + ref.dataOffset + 4;
86
+ let stream = new r.DecodeStream(this.stream.buffer.slice(pos));
87
+ let font = new TTFFont(stream);
88
+ if (
89
+ font.postscriptName === name ||
90
+ (
91
+ font.postscriptName instanceof Uint8Array &&
92
+ name instanceof Uint8Array &&
93
+ font.postscriptName.every((v, i) => name[i] === v)
94
+ )
95
+ ) {
96
+ return font;
97
+ }
98
+ }
99
+
100
+ return null;
101
+ }
102
+
103
+ get fonts() {
104
+ let fonts = [];
105
+ for (let ref of this.sfnt.refList) {
106
+ let pos = this.header.dataOffset + ref.dataOffset + 4;
107
+ let stream = new r.DecodeStream(this.stream.buffer.slice(pos));
108
+ fonts.push(new TTFFont(stream));
109
+ }
110
+
111
+ return fonts;
112
+ }
113
+ }