@cantoo/fontkit 2.0.4 → 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 +4448 -1142
- package/dist/browser-module.mjs.map +1 -1
- package/dist/browser.cjs +4449 -1142
- package/dist/browser.cjs.map +1 -1
- package/dist/main.cjs +4449 -1142
- package/dist/main.cjs.map +1 -1
- package/dist/module.mjs +4448 -1142
- package/dist/module.mjs.map +1 -1
- package/package.json +4 -1
- package/src/CmapProcessor.js +60 -21
- package/src/DFont.js +114 -14
- package/src/TTFFont.js +260 -62
- package/src/TrueTypeCollection.js +59 -15
- package/src/WOFF2Font.js +128 -22
- package/src/WOFFFont.js +45 -8
- package/src/aat/AATFeatureMap.js +83 -40
- package/src/aat/AATLayoutEngine.js +34 -2
- package/src/aat/AATLookupTable.js +24 -6
- package/src/aat/AATMorxProcessor.js +202 -65
- package/src/aat/AATStateMachine.js +35 -3
- package/src/base.js +20 -1
- package/src/cff/CFFCharsets.js +3 -0
- package/src/cff/CFFDict.js +81 -11
- package/src/cff/CFFEncodings.js +2 -0
- package/src/cff/CFFFont.js +120 -24
- package/src/cff/CFFIndex.js +66 -9
- package/src/cff/CFFOperand.js +53 -28
- package/src/cff/CFFPointer.js +41 -2
- package/src/cff/CFFPrivateDict.js +34 -24
- package/src/cff/CFFStandardStrings.js +68 -67
- package/src/cff/CFFTop.js +161 -68
- package/src/decorators.js +34 -15
- package/src/encodings.js +133 -116
- package/src/fs.js +10 -0
- package/src/glyph/BBox.js +14 -0
- package/src/glyph/CFFGlyph.js +293 -152
- package/src/glyph/COLRGlyph.js +40 -5
- package/src/glyph/Glyph.js +72 -13
- package/src/glyph/GlyphVariationProcessor.js +158 -62
- package/src/glyph/Path.js +119 -32
- package/src/glyph/SBIXGlyph.js +57 -8
- package/src/glyph/StandardNames.js +1 -0
- package/src/glyph/TTFGlyph.js +203 -63
- package/src/glyph/TTFGlyphEncoder.js +58 -26
- package/src/glyph/WOFF2Glyph.js +25 -6
- package/src/layout/GlyphPosition.js +6 -0
- package/src/layout/GlyphRun.js +28 -10
- package/src/layout/KernProcessor.js +63 -4
- package/src/layout/LayoutEngine.js +99 -26
- package/src/layout/Script.js +52 -26
- package/src/layout/UnicodeLayoutEngine.js +34 -10
- package/src/opentype/GPOSProcessor.js +156 -45
- package/src/opentype/GSUBProcessor.js +92 -33
- package/src/opentype/GlyphInfo.js +53 -5
- package/src/opentype/GlyphIterator.js +51 -2
- package/src/opentype/OTLayoutEngine.js +66 -8
- package/src/opentype/OTProcessor.js +284 -71
- package/src/opentype/ShapingPlan.js +52 -5
- package/src/opentype/shapers/ArabicShaper.js +27 -8
- package/src/opentype/shapers/DefaultShaper.js +54 -10
- package/src/opentype/shapers/HangulShaper.js +120 -42
- package/src/opentype/shapers/HebrewShaper.js +50 -16
- package/src/opentype/shapers/IndicShaper.js +159 -44
- package/src/opentype/shapers/ThaiShaper.js +50 -19
- package/src/opentype/shapers/UniversalShaper.js +83 -17
- package/src/opentype/shapers/index.js +48 -35
- package/src/opentype/shapers/indic-data.js +2 -2
- package/src/packages/unicode-properties/data-trie.js +2 -1
- package/src/packages/unicode-properties/data.js +13 -1
- package/src/packages/unicode-properties/dist/index.cjs +23 -10
- package/src/packages/unicode-properties/dist/index.cjs.map +2 -2
- package/src/packages/unicode-properties/dist/index.mjs +22 -10
- package/src/packages/unicode-properties/dist/index.mjs.map +2 -2
- package/src/packages/unicode-properties/generate.js +3 -4
- package/src/packages/unicode-properties/index.js +95 -30
- package/src/packages/unicode-properties/package.json +1 -1
- package/src/packages/unicode-trie/builder.js +146 -29
- package/src/packages/unicode-trie/dist/builder.cjs +135 -25
- package/src/packages/unicode-trie/dist/builder.cjs.map +2 -2
- package/src/packages/unicode-trie/dist/builder.mjs +134 -25
- 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 +63 -12
- package/src/packages/unicode-trie/package.json +1 -1
- package/src/packages/unicode-trie/swap.js +15 -2
- package/src/subset/CFFSubset.js +112 -22
- package/src/subset/Subset.js +23 -3
- package/src/subset/TTFSubset.js +84 -41
- package/src/tables/BASE.js +28 -27
- package/src/tables/COLR.js +10 -9
- package/src/tables/CPAL.js +2 -1
- package/src/tables/DSIG.js +8 -7
- package/src/tables/EBDT.js +10 -4
- package/src/tables/EBLC.js +70 -10
- package/src/tables/GDEF.js +18 -17
- package/src/tables/GPOS.js +153 -90
- package/src/tables/GSUB.js +50 -39
- package/src/tables/HVAR.js +51 -5
- package/src/tables/JSTF.js +17 -16
- package/src/tables/LTSH.js +4 -3
- package/src/tables/OS2.js +50 -49
- package/src/tables/PCLT.js +16 -15
- package/src/tables/STAT.js +46 -6
- package/src/tables/VDMX.js +18 -17
- package/src/tables/VORG.js +8 -7
- package/src/tables/WOFF2Directory.js +57 -9
- package/src/tables/WOFFDirectory.js +32 -20
- 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 +83 -63
- package/src/tables/cvt.js +1 -0
- package/src/tables/directory.js +56 -28
- 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 +6 -5
- package/src/tables/glyf.js +2 -1
- package/src/tables/gvar.js +29 -2
- package/src/tables/hdmx.js +18 -7
- package/src/tables/head.js +17 -16
- package/src/tables/hhea.js +15 -14
- package/src/tables/hmtx.js +18 -2
- package/src/tables/index.js +1 -5
- package/src/tables/just.js +15 -4
- package/src/tables/kern.js +84 -47
- package/src/tables/loca.js +23 -10
- package/src/tables/maxp.js +16 -15
- package/src/tables/morx.js +27 -20
- package/src/tables/name.js +120 -39
- package/src/tables/opbd.js +2 -1
- package/src/tables/opentype.js +126 -91
- package/src/tables/post.js +18 -11
- package/src/tables/prep.js +1 -0
- package/src/tables/sbix.js +12 -1
- package/src/tables/variations.js +29 -9
- package/src/tables/vhea.js +15 -14
- package/src/tables/vmtx.js +20 -4
- package/src/utils.js +15 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -45,6 +46,9 @@ var swap32LE = (array) => {
|
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
// index.js
|
|
49
|
+
function isNodeBuffer(value) {
|
|
50
|
+
return typeof value === "object" && value !== null && "readUInt32BE" in value && "readUInt32LE" in value && "slice" in value && typeof value.readUInt32BE === "function" && typeof value.readUInt32LE === "function" && typeof value.slice === "function";
|
|
51
|
+
}
|
|
48
52
|
var SHIFT_1 = 6 + 5;
|
|
49
53
|
var SHIFT_2 = 5;
|
|
50
54
|
var SHIFT_1_2 = SHIFT_1 - SHIFT_2;
|
|
@@ -62,29 +66,38 @@ var UTF8_2B_INDEX_2_LENGTH = 2048 >> 6;
|
|
|
62
66
|
var INDEX_1_OFFSET = UTF8_2B_INDEX_2_OFFSET + UTF8_2B_INDEX_2_LENGTH;
|
|
63
67
|
var DATA_GRANULARITY = 1 << INDEX_SHIFT;
|
|
64
68
|
var UnicodeTrie = class {
|
|
69
|
+
/**
|
|
70
|
+
* @param {Uint8Array | Buffer | UnicodeTrieInit} data
|
|
71
|
+
*/
|
|
65
72
|
constructor(data) {
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
if (isNodeBuffer(data) || data instanceof Uint8Array) {
|
|
74
|
+
let bytes;
|
|
68
75
|
let uncompressedLength;
|
|
69
|
-
if (
|
|
76
|
+
if (isNodeBuffer(data)) {
|
|
70
77
|
this.highStart = data.readUInt32LE(0);
|
|
71
78
|
this.errorValue = data.readUInt32LE(4);
|
|
72
79
|
uncompressedLength = data.readUInt32LE(8);
|
|
73
|
-
|
|
80
|
+
bytes = new Uint8Array(data.buffer, data.byteOffset + 12, data.byteLength - 12);
|
|
74
81
|
} else {
|
|
75
82
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
76
83
|
this.highStart = view.getUint32(0, true);
|
|
77
84
|
this.errorValue = view.getUint32(4, true);
|
|
78
85
|
uncompressedLength = view.getUint32(8, true);
|
|
79
|
-
|
|
86
|
+
bytes = data.subarray(12);
|
|
80
87
|
}
|
|
81
|
-
|
|
82
|
-
swap32LE(
|
|
83
|
-
this.data = new Uint32Array(
|
|
88
|
+
bytes = (0, import_fflate.inflateSync)(bytes, { out: new Uint8Array(uncompressedLength) });
|
|
89
|
+
swap32LE(bytes);
|
|
90
|
+
this.data = new Uint32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >> 2);
|
|
84
91
|
} else {
|
|
85
|
-
|
|
92
|
+
this.data = data.data;
|
|
93
|
+
this.highStart = data.highStart;
|
|
94
|
+
this.errorValue = data.errorValue;
|
|
86
95
|
}
|
|
87
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* @param {number} codePoint
|
|
99
|
+
* @returns {number}
|
|
100
|
+
*/
|
|
88
101
|
get(codePoint) {
|
|
89
102
|
let index;
|
|
90
103
|
if (codePoint < 0 || codePoint > 1114111) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../index.js", "../swap.js"],
|
|
4
|
-
"sourcesContent": ["import { inflateSync } from 'fflate';\nimport { swap32LE } from './swap.js';\n\n// Shift size for getting the index-1 table offset.\nconst SHIFT_1 = 6 + 5;\n\n// Shift size for getting the index-2 table offset.\nconst SHIFT_2 = 5;\n\n// Difference between the two shift sizes,\n// for getting an index-1 offset from an index-2 offset. 6=11-5\nconst SHIFT_1_2 = SHIFT_1 - SHIFT_2;\n\n// Number of index-1 entries for the BMP. 32=0x20\n// This part of the index-1 table is omitted from the serialized form.\nconst OMITTED_BMP_INDEX_1_LENGTH = 0x10000 >> SHIFT_1;\n\n// Number of entries in an index-2 block. 64=0x40\nconst INDEX_2_BLOCK_LENGTH = 1 << SHIFT_1_2;\n\n// Mask for getting the lower bits for the in-index-2-block offset. */\nconst INDEX_2_MASK = INDEX_2_BLOCK_LENGTH - 1;\n\n// Shift size for shifting left the index array values.\n// Increases possible data size with 16-bit index values at the cost\n// of compactability.\n// This requires data blocks to be aligned by DATA_GRANULARITY.\nconst INDEX_SHIFT = 2;\n\n// Number of entries in a data block. 32=0x20\nconst DATA_BLOCK_LENGTH = 1 << SHIFT_2;\n\n// Mask for getting the lower bits for the in-data-block offset.\nconst DATA_MASK = DATA_BLOCK_LENGTH - 1;\n\n// The part of the index-2 table for U+D800..U+DBFF stores values for\n// lead surrogate code _units_ not code _points_.\n// Values for lead surrogate code _points_ are indexed with this portion of the table.\n// Length=32=0x20=0x400>>SHIFT_2. (There are 1024=0x400 lead surrogates.)\nconst LSCP_INDEX_2_OFFSET = 0x10000 >> SHIFT_2;\nconst LSCP_INDEX_2_LENGTH = 0x400 >> SHIFT_2;\n\n// Count the lengths of both BMP pieces. 2080=0x820\nconst INDEX_2_BMP_LENGTH = LSCP_INDEX_2_OFFSET + LSCP_INDEX_2_LENGTH;\n\n// The 2-byte UTF-8 version of the index-2 table follows at offset 2080=0x820.\n// Length 32=0x20 for lead bytes C0..DF, regardless of SHIFT_2.\nconst UTF8_2B_INDEX_2_OFFSET = INDEX_2_BMP_LENGTH;\nconst UTF8_2B_INDEX_2_LENGTH = 0x800 >> 6;
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { inflateSync } from 'fflate';\nimport { swap32LE } from './swap.js';\n\n/**\n * Pre-parsed trie payload (e.g. from UnicodeTrieBuilder.freeze).\n * @typedef {object} UnicodeTrieInit\n * @property {Int32Array | Uint32Array} data\n * @property {number} highStart\n * @property {number} errorValue\n */\n\n/**\n * Duck-type Node Buffer (has LE/BE readers + slice), matching prior runtime checks.\n * @param {unknown} value\n * @returns {value is Buffer}\n */\nfunction isNodeBuffer(value) {\n return (\n typeof value === 'object'\n && value !== null\n && 'readUInt32BE' in value\n && 'readUInt32LE' in value\n && 'slice' in value\n && typeof value.readUInt32BE === 'function'\n && typeof value.readUInt32LE === 'function'\n && typeof value.slice === 'function'\n );\n}\n\n// Shift size for getting the index-1 table offset.\nconst SHIFT_1 = 6 + 5;\n\n// Shift size for getting the index-2 table offset.\nconst SHIFT_2 = 5;\n\n// Difference between the two shift sizes,\n// for getting an index-1 offset from an index-2 offset. 6=11-5\nconst SHIFT_1_2 = SHIFT_1 - SHIFT_2;\n\n// Number of index-1 entries for the BMP. 32=0x20\n// This part of the index-1 table is omitted from the serialized form.\nconst OMITTED_BMP_INDEX_1_LENGTH = 0x10000 >> SHIFT_1;\n\n// Number of entries in an index-2 block. 64=0x40\nconst INDEX_2_BLOCK_LENGTH = 1 << SHIFT_1_2;\n\n// Mask for getting the lower bits for the in-index-2-block offset. */\nconst INDEX_2_MASK = INDEX_2_BLOCK_LENGTH - 1;\n\n// Shift size for shifting left the index array values.\n// Increases possible data size with 16-bit index values at the cost\n// of compactability.\n// This requires data blocks to be aligned by DATA_GRANULARITY.\nconst INDEX_SHIFT = 2;\n\n// Number of entries in a data block. 32=0x20\nconst DATA_BLOCK_LENGTH = 1 << SHIFT_2;\n\n// Mask for getting the lower bits for the in-data-block offset.\nconst DATA_MASK = DATA_BLOCK_LENGTH - 1;\n\n// The part of the index-2 table for U+D800..U+DBFF stores values for\n// lead surrogate code _units_ not code _points_.\n// Values for lead surrogate code _points_ are indexed with this portion of the table.\n// Length=32=0x20=0x400>>SHIFT_2. (There are 1024=0x400 lead surrogates.)\nconst LSCP_INDEX_2_OFFSET = 0x10000 >> SHIFT_2;\nconst LSCP_INDEX_2_LENGTH = 0x400 >> SHIFT_2;\n\n// Count the lengths of both BMP pieces. 2080=0x820\nconst INDEX_2_BMP_LENGTH = LSCP_INDEX_2_OFFSET + LSCP_INDEX_2_LENGTH;\n\n// The 2-byte UTF-8 version of the index-2 table follows at offset 2080=0x820.\n// Length 32=0x20 for lead bytes C0..DF, regardless of SHIFT_2.\nconst UTF8_2B_INDEX_2_OFFSET = INDEX_2_BMP_LENGTH;\nconst UTF8_2B_INDEX_2_LENGTH = 0x800 >> 6; // U+0800 is the first code point after 2-byte UTF-8\n\n// The index-1 table, only used for supplementary code points, at offset 2112=0x840.\n// Variable length, for code points up to highStart, where the last single-value range starts.\n// Maximum length 512=0x200=0x100000>>SHIFT_1.\n// (For 0x100000 supplementary code points U+10000..U+10ffff.)\n//\n// The part of the index-2 table for supplementary code points starts\n// after this index-1 table.\n//\n// Both the index-1 table and the following part of the index-2 table\n// are omitted completely if there is only BMP data.\nconst INDEX_1_OFFSET = UTF8_2B_INDEX_2_OFFSET + UTF8_2B_INDEX_2_LENGTH;\n\n// The alignment size of a data block. Also the granularity for compaction.\nconst DATA_GRANULARITY = 1 << INDEX_SHIFT;\n\nclass UnicodeTrie {\n /**\n * @param {Uint8Array | Buffer | UnicodeTrieInit} data\n */\n constructor(data) {\n if (isNodeBuffer(data) || data instanceof Uint8Array) {\n // read binary format\n /** @type {Uint8Array} */\n let bytes;\n let uncompressedLength;\n if (isNodeBuffer(data)) {\n this.highStart = data.readUInt32LE(0);\n this.errorValue = data.readUInt32LE(4);\n uncompressedLength = data.readUInt32LE(8);\n // View past the 12-byte header (avoids Buffer.slice \u2192 Uint8Array assignability issues).\n bytes = new Uint8Array(data.buffer, data.byteOffset + 12, data.byteLength - 12);\n } else {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n this.highStart = view.getUint32(0, true);\n this.errorValue = view.getUint32(4, true);\n uncompressedLength = view.getUint32(8, true);\n bytes = data.subarray(12);\n }\n\n // inflate the actual trie data (raw deflate, matching builder)\n bytes = inflateSync(bytes, { out: new Uint8Array(uncompressedLength) });\n\n // swap bytes from little-endian\n swap32LE(bytes);\n\n /**\n * Compacted index + data table.\n * @type {Uint32Array | Int32Array}\n */\n this.data = new Uint32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >> 2);\n } else {\n // pre-parsed data\n /**\n * Compacted index + data table.\n * @type {Uint32Array | Int32Array}\n */\n this.data = data.data;\n /**\n * First code point of the final single-value range.\n * @type {number}\n */\n this.highStart = data.highStart;\n /**\n * Value returned for out-of-range code points.\n * @type {number}\n */\n this.errorValue = data.errorValue;\n }\n }\n\n /**\n * @param {number} codePoint\n * @returns {number}\n */\n get(codePoint) {\n let index;\n if ((codePoint < 0) || (codePoint > 0x10ffff)) {\n return this.errorValue;\n }\n\n if ((codePoint < 0xd800) || ((codePoint > 0xdbff) && (codePoint <= 0xffff))) {\n // Ordinary BMP code point, excluding leading surrogates.\n // BMP uses a single level lookup. BMP index starts at offset 0 in the index.\n // data is stored in the index array itself.\n index = (this.data[codePoint >> SHIFT_2] << INDEX_SHIFT) + (codePoint & DATA_MASK);\n return this.data[index];\n }\n\n if (codePoint <= 0xffff) {\n // Lead Surrogate Code Point. A Separate index section is stored for\n // lead surrogate code units and code points.\n // The main index has the code unit data.\n // For this function, we need the code point data.\n index = (this.data[LSCP_INDEX_2_OFFSET + ((codePoint - 0xd800) >> SHIFT_2)] << INDEX_SHIFT) + (codePoint & DATA_MASK);\n return this.data[index];\n }\n\n if (codePoint < this.highStart) {\n // Supplemental code point, use two-level lookup.\n index = this.data[(INDEX_1_OFFSET - OMITTED_BMP_INDEX_1_LENGTH) + (codePoint >> SHIFT_1)];\n index = this.data[index + ((codePoint >> SHIFT_2) & INDEX_2_MASK)];\n index = (index << INDEX_SHIFT) + (codePoint & DATA_MASK);\n return this.data[index];\n }\n\n return this.data[this.data.length - DATA_GRANULARITY];\n }\n}\n\nexport default UnicodeTrie;\n", "const isBigEndian = (new Uint8Array(new Uint32Array([0x12345678]).buffer)[0] === 0x12);\n\n/**\n * @param {Uint8Array} b\n * @param {number} n\n * @param {number} m\n */\nconst swap = (b, n, m) => {\n let i = b[n];\n b[n] = b[m];\n b[m] = i;\n};\n\n/**\n * @param {Uint8Array} array\n */\nconst swap32 = (array) => {\n const len = array.length;\n for (let i = 0; i < len; i += 4) {\n swap(array, i, i + 3);\n swap(array, i + 1, i + 2);\n }\n};\n\n/**\n * Swap byte order of each 32-bit word in-place when running on a big-endian host,\n * so the trie data is little-endian as expected by the runtime.\n * @param {Uint8Array} array\n */\nexport const swap32LE = (array) => {\n if (isBigEndian) {\n swap32(array);\n }\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -22,6 +22,9 @@ var swap32LE = (array) => {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
// index.js
|
|
25
|
+
function isNodeBuffer(value) {
|
|
26
|
+
return typeof value === "object" && value !== null && "readUInt32BE" in value && "readUInt32LE" in value && "slice" in value && typeof value.readUInt32BE === "function" && typeof value.readUInt32LE === "function" && typeof value.slice === "function";
|
|
27
|
+
}
|
|
25
28
|
var SHIFT_1 = 6 + 5;
|
|
26
29
|
var SHIFT_2 = 5;
|
|
27
30
|
var SHIFT_1_2 = SHIFT_1 - SHIFT_2;
|
|
@@ -39,29 +42,38 @@ var UTF8_2B_INDEX_2_LENGTH = 2048 >> 6;
|
|
|
39
42
|
var INDEX_1_OFFSET = UTF8_2B_INDEX_2_OFFSET + UTF8_2B_INDEX_2_LENGTH;
|
|
40
43
|
var DATA_GRANULARITY = 1 << INDEX_SHIFT;
|
|
41
44
|
var UnicodeTrie = class {
|
|
45
|
+
/**
|
|
46
|
+
* @param {Uint8Array | Buffer | UnicodeTrieInit} data
|
|
47
|
+
*/
|
|
42
48
|
constructor(data) {
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
if (isNodeBuffer(data) || data instanceof Uint8Array) {
|
|
50
|
+
let bytes;
|
|
45
51
|
let uncompressedLength;
|
|
46
|
-
if (
|
|
52
|
+
if (isNodeBuffer(data)) {
|
|
47
53
|
this.highStart = data.readUInt32LE(0);
|
|
48
54
|
this.errorValue = data.readUInt32LE(4);
|
|
49
55
|
uncompressedLength = data.readUInt32LE(8);
|
|
50
|
-
|
|
56
|
+
bytes = new Uint8Array(data.buffer, data.byteOffset + 12, data.byteLength - 12);
|
|
51
57
|
} else {
|
|
52
58
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
53
59
|
this.highStart = view.getUint32(0, true);
|
|
54
60
|
this.errorValue = view.getUint32(4, true);
|
|
55
61
|
uncompressedLength = view.getUint32(8, true);
|
|
56
|
-
|
|
62
|
+
bytes = data.subarray(12);
|
|
57
63
|
}
|
|
58
|
-
|
|
59
|
-
swap32LE(
|
|
60
|
-
this.data = new Uint32Array(
|
|
64
|
+
bytes = inflateSync(bytes, { out: new Uint8Array(uncompressedLength) });
|
|
65
|
+
swap32LE(bytes);
|
|
66
|
+
this.data = new Uint32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >> 2);
|
|
61
67
|
} else {
|
|
62
|
-
|
|
68
|
+
this.data = data.data;
|
|
69
|
+
this.highStart = data.highStart;
|
|
70
|
+
this.errorValue = data.errorValue;
|
|
63
71
|
}
|
|
64
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* @param {number} codePoint
|
|
75
|
+
* @returns {number}
|
|
76
|
+
*/
|
|
65
77
|
get(codePoint) {
|
|
66
78
|
let index;
|
|
67
79
|
if (codePoint < 0 || codePoint > 1114111) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../index.js", "../swap.js"],
|
|
4
|
-
"sourcesContent": ["import { inflateSync } from 'fflate';\nimport { swap32LE } from './swap.js';\n\n// Shift size for getting the index-1 table offset.\nconst SHIFT_1 = 6 + 5;\n\n// Shift size for getting the index-2 table offset.\nconst SHIFT_2 = 5;\n\n// Difference between the two shift sizes,\n// for getting an index-1 offset from an index-2 offset. 6=11-5\nconst SHIFT_1_2 = SHIFT_1 - SHIFT_2;\n\n// Number of index-1 entries for the BMP. 32=0x20\n// This part of the index-1 table is omitted from the serialized form.\nconst OMITTED_BMP_INDEX_1_LENGTH = 0x10000 >> SHIFT_1;\n\n// Number of entries in an index-2 block. 64=0x40\nconst INDEX_2_BLOCK_LENGTH = 1 << SHIFT_1_2;\n\n// Mask for getting the lower bits for the in-index-2-block offset. */\nconst INDEX_2_MASK = INDEX_2_BLOCK_LENGTH - 1;\n\n// Shift size for shifting left the index array values.\n// Increases possible data size with 16-bit index values at the cost\n// of compactability.\n// This requires data blocks to be aligned by DATA_GRANULARITY.\nconst INDEX_SHIFT = 2;\n\n// Number of entries in a data block. 32=0x20\nconst DATA_BLOCK_LENGTH = 1 << SHIFT_2;\n\n// Mask for getting the lower bits for the in-data-block offset.\nconst DATA_MASK = DATA_BLOCK_LENGTH - 1;\n\n// The part of the index-2 table for U+D800..U+DBFF stores values for\n// lead surrogate code _units_ not code _points_.\n// Values for lead surrogate code _points_ are indexed with this portion of the table.\n// Length=32=0x20=0x400>>SHIFT_2. (There are 1024=0x400 lead surrogates.)\nconst LSCP_INDEX_2_OFFSET = 0x10000 >> SHIFT_2;\nconst LSCP_INDEX_2_LENGTH = 0x400 >> SHIFT_2;\n\n// Count the lengths of both BMP pieces. 2080=0x820\nconst INDEX_2_BMP_LENGTH = LSCP_INDEX_2_OFFSET + LSCP_INDEX_2_LENGTH;\n\n// The 2-byte UTF-8 version of the index-2 table follows at offset 2080=0x820.\n// Length 32=0x20 for lead bytes C0..DF, regardless of SHIFT_2.\nconst UTF8_2B_INDEX_2_OFFSET = INDEX_2_BMP_LENGTH;\nconst UTF8_2B_INDEX_2_LENGTH = 0x800 >> 6;
|
|
5
|
-
"mappings": ";AAAA,SAAS,mBAAmB;;;ACA5B,IAAM,cAAe,IAAI,WAAW,IAAI,YAAY,CAAC,SAAU,CAAC,EAAE,MAAM,EAAE,CAAC,MAAM;
|
|
4
|
+
"sourcesContent": ["import { inflateSync } from 'fflate';\nimport { swap32LE } from './swap.js';\n\n/**\n * Pre-parsed trie payload (e.g. from UnicodeTrieBuilder.freeze).\n * @typedef {object} UnicodeTrieInit\n * @property {Int32Array | Uint32Array} data\n * @property {number} highStart\n * @property {number} errorValue\n */\n\n/**\n * Duck-type Node Buffer (has LE/BE readers + slice), matching prior runtime checks.\n * @param {unknown} value\n * @returns {value is Buffer}\n */\nfunction isNodeBuffer(value) {\n return (\n typeof value === 'object'\n && value !== null\n && 'readUInt32BE' in value\n && 'readUInt32LE' in value\n && 'slice' in value\n && typeof value.readUInt32BE === 'function'\n && typeof value.readUInt32LE === 'function'\n && typeof value.slice === 'function'\n );\n}\n\n// Shift size for getting the index-1 table offset.\nconst SHIFT_1 = 6 + 5;\n\n// Shift size for getting the index-2 table offset.\nconst SHIFT_2 = 5;\n\n// Difference between the two shift sizes,\n// for getting an index-1 offset from an index-2 offset. 6=11-5\nconst SHIFT_1_2 = SHIFT_1 - SHIFT_2;\n\n// Number of index-1 entries for the BMP. 32=0x20\n// This part of the index-1 table is omitted from the serialized form.\nconst OMITTED_BMP_INDEX_1_LENGTH = 0x10000 >> SHIFT_1;\n\n// Number of entries in an index-2 block. 64=0x40\nconst INDEX_2_BLOCK_LENGTH = 1 << SHIFT_1_2;\n\n// Mask for getting the lower bits for the in-index-2-block offset. */\nconst INDEX_2_MASK = INDEX_2_BLOCK_LENGTH - 1;\n\n// Shift size for shifting left the index array values.\n// Increases possible data size with 16-bit index values at the cost\n// of compactability.\n// This requires data blocks to be aligned by DATA_GRANULARITY.\nconst INDEX_SHIFT = 2;\n\n// Number of entries in a data block. 32=0x20\nconst DATA_BLOCK_LENGTH = 1 << SHIFT_2;\n\n// Mask for getting the lower bits for the in-data-block offset.\nconst DATA_MASK = DATA_BLOCK_LENGTH - 1;\n\n// The part of the index-2 table for U+D800..U+DBFF stores values for\n// lead surrogate code _units_ not code _points_.\n// Values for lead surrogate code _points_ are indexed with this portion of the table.\n// Length=32=0x20=0x400>>SHIFT_2. (There are 1024=0x400 lead surrogates.)\nconst LSCP_INDEX_2_OFFSET = 0x10000 >> SHIFT_2;\nconst LSCP_INDEX_2_LENGTH = 0x400 >> SHIFT_2;\n\n// Count the lengths of both BMP pieces. 2080=0x820\nconst INDEX_2_BMP_LENGTH = LSCP_INDEX_2_OFFSET + LSCP_INDEX_2_LENGTH;\n\n// The 2-byte UTF-8 version of the index-2 table follows at offset 2080=0x820.\n// Length 32=0x20 for lead bytes C0..DF, regardless of SHIFT_2.\nconst UTF8_2B_INDEX_2_OFFSET = INDEX_2_BMP_LENGTH;\nconst UTF8_2B_INDEX_2_LENGTH = 0x800 >> 6; // U+0800 is the first code point after 2-byte UTF-8\n\n// The index-1 table, only used for supplementary code points, at offset 2112=0x840.\n// Variable length, for code points up to highStart, where the last single-value range starts.\n// Maximum length 512=0x200=0x100000>>SHIFT_1.\n// (For 0x100000 supplementary code points U+10000..U+10ffff.)\n//\n// The part of the index-2 table for supplementary code points starts\n// after this index-1 table.\n//\n// Both the index-1 table and the following part of the index-2 table\n// are omitted completely if there is only BMP data.\nconst INDEX_1_OFFSET = UTF8_2B_INDEX_2_OFFSET + UTF8_2B_INDEX_2_LENGTH;\n\n// The alignment size of a data block. Also the granularity for compaction.\nconst DATA_GRANULARITY = 1 << INDEX_SHIFT;\n\nclass UnicodeTrie {\n /**\n * @param {Uint8Array | Buffer | UnicodeTrieInit} data\n */\n constructor(data) {\n if (isNodeBuffer(data) || data instanceof Uint8Array) {\n // read binary format\n /** @type {Uint8Array} */\n let bytes;\n let uncompressedLength;\n if (isNodeBuffer(data)) {\n this.highStart = data.readUInt32LE(0);\n this.errorValue = data.readUInt32LE(4);\n uncompressedLength = data.readUInt32LE(8);\n // View past the 12-byte header (avoids Buffer.slice \u2192 Uint8Array assignability issues).\n bytes = new Uint8Array(data.buffer, data.byteOffset + 12, data.byteLength - 12);\n } else {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n this.highStart = view.getUint32(0, true);\n this.errorValue = view.getUint32(4, true);\n uncompressedLength = view.getUint32(8, true);\n bytes = data.subarray(12);\n }\n\n // inflate the actual trie data (raw deflate, matching builder)\n bytes = inflateSync(bytes, { out: new Uint8Array(uncompressedLength) });\n\n // swap bytes from little-endian\n swap32LE(bytes);\n\n /**\n * Compacted index + data table.\n * @type {Uint32Array | Int32Array}\n */\n this.data = new Uint32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >> 2);\n } else {\n // pre-parsed data\n /**\n * Compacted index + data table.\n * @type {Uint32Array | Int32Array}\n */\n this.data = data.data;\n /**\n * First code point of the final single-value range.\n * @type {number}\n */\n this.highStart = data.highStart;\n /**\n * Value returned for out-of-range code points.\n * @type {number}\n */\n this.errorValue = data.errorValue;\n }\n }\n\n /**\n * @param {number} codePoint\n * @returns {number}\n */\n get(codePoint) {\n let index;\n if ((codePoint < 0) || (codePoint > 0x10ffff)) {\n return this.errorValue;\n }\n\n if ((codePoint < 0xd800) || ((codePoint > 0xdbff) && (codePoint <= 0xffff))) {\n // Ordinary BMP code point, excluding leading surrogates.\n // BMP uses a single level lookup. BMP index starts at offset 0 in the index.\n // data is stored in the index array itself.\n index = (this.data[codePoint >> SHIFT_2] << INDEX_SHIFT) + (codePoint & DATA_MASK);\n return this.data[index];\n }\n\n if (codePoint <= 0xffff) {\n // Lead Surrogate Code Point. A Separate index section is stored for\n // lead surrogate code units and code points.\n // The main index has the code unit data.\n // For this function, we need the code point data.\n index = (this.data[LSCP_INDEX_2_OFFSET + ((codePoint - 0xd800) >> SHIFT_2)] << INDEX_SHIFT) + (codePoint & DATA_MASK);\n return this.data[index];\n }\n\n if (codePoint < this.highStart) {\n // Supplemental code point, use two-level lookup.\n index = this.data[(INDEX_1_OFFSET - OMITTED_BMP_INDEX_1_LENGTH) + (codePoint >> SHIFT_1)];\n index = this.data[index + ((codePoint >> SHIFT_2) & INDEX_2_MASK)];\n index = (index << INDEX_SHIFT) + (codePoint & DATA_MASK);\n return this.data[index];\n }\n\n return this.data[this.data.length - DATA_GRANULARITY];\n }\n}\n\nexport default UnicodeTrie;\n", "const isBigEndian = (new Uint8Array(new Uint32Array([0x12345678]).buffer)[0] === 0x12);\n\n/**\n * @param {Uint8Array} b\n * @param {number} n\n * @param {number} m\n */\nconst swap = (b, n, m) => {\n let i = b[n];\n b[n] = b[m];\n b[m] = i;\n};\n\n/**\n * @param {Uint8Array} array\n */\nconst swap32 = (array) => {\n const len = array.length;\n for (let i = 0; i < len; i += 4) {\n swap(array, i, i + 3);\n swap(array, i + 1, i + 2);\n }\n};\n\n/**\n * Swap byte order of each 32-bit word in-place when running on a big-endian host,\n * so the trie data is little-endian as expected by the runtime.\n * @param {Uint8Array} array\n */\nexport const swap32LE = (array) => {\n if (isBigEndian) {\n swap32(array);\n }\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
import { inflateSync } from 'fflate';
|
|
2
2
|
import { swap32LE } from './swap.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Pre-parsed trie payload (e.g. from UnicodeTrieBuilder.freeze).
|
|
6
|
+
* @typedef {object} UnicodeTrieInit
|
|
7
|
+
* @property {Int32Array | Uint32Array} data
|
|
8
|
+
* @property {number} highStart
|
|
9
|
+
* @property {number} errorValue
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Duck-type Node Buffer (has LE/BE readers + slice), matching prior runtime checks.
|
|
14
|
+
* @param {unknown} value
|
|
15
|
+
* @returns {value is Buffer}
|
|
16
|
+
*/
|
|
17
|
+
function isNodeBuffer(value) {
|
|
18
|
+
return (
|
|
19
|
+
typeof value === 'object'
|
|
20
|
+
&& value !== null
|
|
21
|
+
&& 'readUInt32BE' in value
|
|
22
|
+
&& 'readUInt32LE' in value
|
|
23
|
+
&& 'slice' in value
|
|
24
|
+
&& typeof value.readUInt32BE === 'function'
|
|
25
|
+
&& typeof value.readUInt32LE === 'function'
|
|
26
|
+
&& typeof value.slice === 'function'
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
4
30
|
// Shift size for getting the index-1 table offset.
|
|
5
31
|
const SHIFT_1 = 6 + 5;
|
|
6
32
|
|
|
@@ -46,7 +72,7 @@ const INDEX_2_BMP_LENGTH = LSCP_INDEX_2_OFFSET + LSCP_INDEX_2_LENGTH;
|
|
|
46
72
|
// The 2-byte UTF-8 version of the index-2 table follows at offset 2080=0x820.
|
|
47
73
|
// Length 32=0x20 for lead bytes C0..DF, regardless of SHIFT_2.
|
|
48
74
|
const UTF8_2B_INDEX_2_OFFSET = INDEX_2_BMP_LENGTH;
|
|
49
|
-
const UTF8_2B_INDEX_2_LENGTH = 0x800 >> 6;
|
|
75
|
+
const UTF8_2B_INDEX_2_LENGTH = 0x800 >> 6; // U+0800 is the first code point after 2-byte UTF-8
|
|
50
76
|
|
|
51
77
|
// The index-1 table, only used for supplementary code points, at offset 2112=0x840.
|
|
52
78
|
// Variable length, for code points up to highStart, where the last single-value range starts.
|
|
@@ -64,39 +90,64 @@ const INDEX_1_OFFSET = UTF8_2B_INDEX_2_OFFSET + UTF8_2B_INDEX_2_LENGTH;
|
|
|
64
90
|
const DATA_GRANULARITY = 1 << INDEX_SHIFT;
|
|
65
91
|
|
|
66
92
|
class UnicodeTrie {
|
|
93
|
+
/**
|
|
94
|
+
* @param {Uint8Array | Buffer | UnicodeTrieInit} data
|
|
95
|
+
*/
|
|
67
96
|
constructor(data) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (isBuffer || data instanceof Uint8Array) {
|
|
97
|
+
if (isNodeBuffer(data) || data instanceof Uint8Array) {
|
|
71
98
|
// read binary format
|
|
99
|
+
/** @type {Uint8Array} */
|
|
100
|
+
let bytes;
|
|
72
101
|
let uncompressedLength;
|
|
73
|
-
if (
|
|
102
|
+
if (isNodeBuffer(data)) {
|
|
74
103
|
this.highStart = data.readUInt32LE(0);
|
|
75
104
|
this.errorValue = data.readUInt32LE(4);
|
|
76
105
|
uncompressedLength = data.readUInt32LE(8);
|
|
77
|
-
|
|
106
|
+
// View past the 12-byte header (avoids Buffer.slice → Uint8Array assignability issues).
|
|
107
|
+
bytes = new Uint8Array(data.buffer, data.byteOffset + 12, data.byteLength - 12);
|
|
78
108
|
} else {
|
|
79
109
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
80
110
|
this.highStart = view.getUint32(0, true);
|
|
81
111
|
this.errorValue = view.getUint32(4, true);
|
|
82
112
|
uncompressedLength = view.getUint32(8, true);
|
|
83
|
-
|
|
113
|
+
bytes = data.subarray(12);
|
|
84
114
|
}
|
|
85
115
|
|
|
86
116
|
// inflate the actual trie data (raw deflate, matching builder)
|
|
87
|
-
|
|
117
|
+
bytes = inflateSync(bytes, { out: new Uint8Array(uncompressedLength) });
|
|
88
118
|
|
|
89
119
|
// swap bytes from little-endian
|
|
90
|
-
swap32LE(
|
|
91
|
-
|
|
92
|
-
this.data = new Uint32Array(data.buffer, data.byteOffset, data.byteLength >> 2);
|
|
120
|
+
swap32LE(bytes);
|
|
93
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Compacted index + data table.
|
|
124
|
+
* @type {Uint32Array | Int32Array}
|
|
125
|
+
*/
|
|
126
|
+
this.data = new Uint32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >> 2);
|
|
94
127
|
} else {
|
|
95
128
|
// pre-parsed data
|
|
96
|
-
|
|
129
|
+
/**
|
|
130
|
+
* Compacted index + data table.
|
|
131
|
+
* @type {Uint32Array | Int32Array}
|
|
132
|
+
*/
|
|
133
|
+
this.data = data.data;
|
|
134
|
+
/**
|
|
135
|
+
* First code point of the final single-value range.
|
|
136
|
+
* @type {number}
|
|
137
|
+
*/
|
|
138
|
+
this.highStart = data.highStart;
|
|
139
|
+
/**
|
|
140
|
+
* Value returned for out-of-range code points.
|
|
141
|
+
* @type {number}
|
|
142
|
+
*/
|
|
143
|
+
this.errorValue = data.errorValue;
|
|
97
144
|
}
|
|
98
145
|
}
|
|
99
146
|
|
|
147
|
+
/**
|
|
148
|
+
* @param {number} codePoint
|
|
149
|
+
* @returns {number}
|
|
150
|
+
*/
|
|
100
151
|
get(codePoint) {
|
|
101
152
|
let index;
|
|
102
153
|
if ((codePoint < 0) || (codePoint > 0x10ffff)) {
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
const isBigEndian = (new Uint8Array(new Uint32Array([0x12345678]).buffer)[0] === 0x12);
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @param {Uint8Array} b
|
|
5
|
+
* @param {number} n
|
|
6
|
+
* @param {number} m
|
|
7
|
+
*/
|
|
3
8
|
const swap = (b, n, m) => {
|
|
4
9
|
let i = b[n];
|
|
5
10
|
b[n] = b[m];
|
|
6
11
|
b[m] = i;
|
|
7
12
|
};
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
/**
|
|
15
|
+
* @param {Uint8Array} array
|
|
16
|
+
*/
|
|
17
|
+
const swap32 = (array) => {
|
|
10
18
|
const len = array.length;
|
|
11
19
|
for (let i = 0; i < len; i += 4) {
|
|
12
20
|
swap(array, i, i + 3);
|
|
@@ -14,7 +22,12 @@ const swap32 = array => {
|
|
|
14
22
|
}
|
|
15
23
|
};
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Swap byte order of each 32-bit word in-place when running on a big-endian host,
|
|
27
|
+
* so the trie data is little-endian as expected by the runtime.
|
|
28
|
+
* @param {Uint8Array} array
|
|
29
|
+
*/
|
|
30
|
+
export const swap32LE = (array) => {
|
|
18
31
|
if (isBigEndian) {
|
|
19
32
|
swap32(array);
|
|
20
33
|
}
|
package/src/subset/CFFSubset.js
CHANGED
|
@@ -2,39 +2,84 @@ import Subset from './Subset';
|
|
|
2
2
|
import CFFTop from '../cff/CFFTop';
|
|
3
3
|
import standardStrings from '../cff/CFFStandardStrings';
|
|
4
4
|
|
|
5
|
+
/** @typedef {import('../../types/fontkit').SubsetFont} SubsetFont */
|
|
6
|
+
/** @typedef {import('../../types/fontkit').CFFFontLike} CFFFontLike */
|
|
7
|
+
/** @typedef {import('../../types/fontkit').CFFTopDict} CFFTopDict */
|
|
8
|
+
/** @typedef {import('../../types/fontkit').CFFCharString} CFFCharString */
|
|
9
|
+
/** @typedef {import('restructure').BinaryBuffer} BinaryBuffer */
|
|
10
|
+
/** @typedef {import('restructure').StructValue} StructValue */
|
|
11
|
+
|
|
5
12
|
export default class CFFSubset extends Subset {
|
|
13
|
+
/** @type {CFFFontLike} */
|
|
14
|
+
cff;
|
|
15
|
+
/** @type {BinaryBuffer[] | null} */
|
|
16
|
+
charstrings = null;
|
|
17
|
+
/** @type {BinaryBuffer[] | null} */
|
|
18
|
+
gsubrs = null;
|
|
19
|
+
/** @type {string[] | null} */
|
|
20
|
+
strings = null;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {SubsetFont} font
|
|
24
|
+
*/
|
|
6
25
|
constructor(font) {
|
|
7
26
|
super(font);
|
|
8
27
|
|
|
9
|
-
|
|
10
|
-
if (!
|
|
28
|
+
let cff = this.font['CFF '];
|
|
29
|
+
if (!cff) {
|
|
11
30
|
throw new Error('Not a CFF Font');
|
|
12
31
|
}
|
|
32
|
+
this.cff = cff;
|
|
13
33
|
}
|
|
14
34
|
|
|
15
|
-
|
|
35
|
+
/**
|
|
36
|
+
* @param {string} [_tag]
|
|
37
|
+
* @returns {never}
|
|
38
|
+
*/
|
|
39
|
+
includeTable(_tag) {
|
|
16
40
|
throw new Error('includeTable is only supported for TrueType (glyf) subsets, not CFF.');
|
|
17
41
|
}
|
|
18
42
|
|
|
43
|
+
/**
|
|
44
|
+
* @returns {void}
|
|
45
|
+
*/
|
|
19
46
|
subsetCharstrings() {
|
|
20
47
|
this.charstrings = [];
|
|
48
|
+
/** @type {Record<string, boolean>} */
|
|
21
49
|
let gsubrs = {};
|
|
22
50
|
|
|
23
51
|
for (let gid of this.glyphs) {
|
|
52
|
+
if (!this.cff.getCharString) {
|
|
53
|
+
throw new Error('CFF font missing getCharString()');
|
|
54
|
+
}
|
|
24
55
|
this.charstrings.push(this.cff.getCharString(gid));
|
|
25
56
|
|
|
26
57
|
let glyph = this.font.getGlyph(gid);
|
|
58
|
+
if (!glyph) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
27
61
|
void glyph.path; // this causes the glyph to be parsed
|
|
28
62
|
|
|
29
|
-
|
|
30
|
-
|
|
63
|
+
if (glyph._usedGsubrs) {
|
|
64
|
+
for (let subr in glyph._usedGsubrs) {
|
|
65
|
+
gsubrs[subr] = true;
|
|
66
|
+
}
|
|
31
67
|
}
|
|
32
68
|
}
|
|
33
69
|
|
|
34
|
-
this.gsubrs = this.subsetSubrs(
|
|
70
|
+
this.gsubrs = this.subsetSubrs(
|
|
71
|
+
/** @type {Array<{ offset: number, length: number }>} */ (this.cff.globalSubrIndex || []),
|
|
72
|
+
gsubrs
|
|
73
|
+
);
|
|
35
74
|
}
|
|
36
75
|
|
|
76
|
+
/**
|
|
77
|
+
* @param {Array<{ offset: number, length: number }>} subrs
|
|
78
|
+
* @param {Record<string | number, boolean>} used
|
|
79
|
+
* @returns {BinaryBuffer[]}
|
|
80
|
+
*/
|
|
37
81
|
subsetSubrs(subrs, used) {
|
|
82
|
+
/** @type {BinaryBuffer[]} */
|
|
38
83
|
let res = [];
|
|
39
84
|
for (let i = 0; i < subrs.length; i++) {
|
|
40
85
|
let subr = subrs[i];
|
|
@@ -49,6 +94,10 @@ export default class CFFSubset extends Subset {
|
|
|
49
94
|
return res;
|
|
50
95
|
}
|
|
51
96
|
|
|
97
|
+
/**
|
|
98
|
+
* @param {CFFTopDict} topDict
|
|
99
|
+
* @returns {void}
|
|
100
|
+
*/
|
|
52
101
|
subsetFontdict(topDict) {
|
|
53
102
|
topDict.FDArray = [];
|
|
54
103
|
topDict.FDSelect = {
|
|
@@ -56,28 +105,42 @@ export default class CFFSubset extends Subset {
|
|
|
56
105
|
fds: []
|
|
57
106
|
};
|
|
58
107
|
|
|
108
|
+
/** @type {Record<number, boolean>} */
|
|
59
109
|
let used_fds = {};
|
|
110
|
+
/** @type {Array<Record<string, boolean>>} */
|
|
60
111
|
let used_subrs = [];
|
|
112
|
+
/** @type {Record<number, number>} */
|
|
61
113
|
let fd_select = {};
|
|
62
114
|
for (let gid of this.glyphs) {
|
|
115
|
+
if (!this.cff.fdForGlyph) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
63
118
|
let fd = this.cff.fdForGlyph(gid);
|
|
64
119
|
if (fd == null) {
|
|
65
120
|
continue;
|
|
66
121
|
}
|
|
67
122
|
|
|
68
123
|
if (!used_fds[fd]) {
|
|
69
|
-
topDict.FDArray
|
|
124
|
+
let src = this.cff.topDict.FDArray && this.cff.topDict.FDArray[fd];
|
|
125
|
+
topDict.FDArray.push(Object.assign({}, src));
|
|
70
126
|
used_subrs.push({});
|
|
71
127
|
fd_select[fd] = topDict.FDArray.length - 1;
|
|
72
128
|
}
|
|
73
129
|
|
|
74
130
|
used_fds[fd] = true;
|
|
75
|
-
topDict.FDSelect.fds
|
|
131
|
+
if (topDict.FDSelect.fds) {
|
|
132
|
+
topDict.FDSelect.fds.push(fd_select[fd]);
|
|
133
|
+
}
|
|
76
134
|
|
|
77
135
|
let glyph = this.font.getGlyph(gid);
|
|
136
|
+
if (!glyph) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
78
139
|
void glyph.path; // this causes the glyph to be parsed
|
|
79
|
-
|
|
80
|
-
|
|
140
|
+
if (glyph._usedSubrs) {
|
|
141
|
+
for (let subr in glyph._usedSubrs) {
|
|
142
|
+
used_subrs[fd_select[fd]][subr] = true;
|
|
143
|
+
}
|
|
81
144
|
}
|
|
82
145
|
}
|
|
83
146
|
|
|
@@ -86,38 +149,59 @@ export default class CFFSubset extends Subset {
|
|
|
86
149
|
delete dict.FontName;
|
|
87
150
|
if (dict.Private && dict.Private.Subrs) {
|
|
88
151
|
dict.Private = Object.assign({}, dict.Private);
|
|
89
|
-
dict.Private.Subrs = this.subsetSubrs(
|
|
152
|
+
dict.Private.Subrs = this.subsetSubrs(
|
|
153
|
+
/** @type {Array<{ offset: number, length: number }>} */ (dict.Private.Subrs),
|
|
154
|
+
used_subrs[i]
|
|
155
|
+
);
|
|
90
156
|
}
|
|
91
157
|
}
|
|
92
158
|
|
|
93
159
|
return;
|
|
94
160
|
}
|
|
95
161
|
|
|
162
|
+
/**
|
|
163
|
+
* @param {CFFTopDict} topDict
|
|
164
|
+
* @returns {StructValue}
|
|
165
|
+
*/
|
|
96
166
|
createCIDFontdict(topDict) {
|
|
167
|
+
/** @type {Record<string, boolean>} */
|
|
97
168
|
let used_subrs = {};
|
|
98
169
|
for (let gid of this.glyphs) {
|
|
99
170
|
let glyph = this.font.getGlyph(gid);
|
|
171
|
+
if (!glyph) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
100
174
|
void glyph.path; // this causes the glyph to be parsed
|
|
101
175
|
|
|
102
|
-
|
|
103
|
-
|
|
176
|
+
if (glyph._usedSubrs) {
|
|
177
|
+
for (let subr in glyph._usedSubrs) {
|
|
178
|
+
used_subrs[subr] = true;
|
|
179
|
+
}
|
|
104
180
|
}
|
|
105
181
|
}
|
|
106
182
|
|
|
107
183
|
let privateDict = Object.assign({}, this.cff.topDict.Private);
|
|
108
184
|
if (this.cff.topDict.Private && this.cff.topDict.Private.Subrs) {
|
|
109
|
-
privateDict.Subrs = this.subsetSubrs(
|
|
185
|
+
privateDict.Subrs = this.subsetSubrs(
|
|
186
|
+
/** @type {Array<{ offset: number, length: number }>} */ (this.cff.topDict.Private.Subrs),
|
|
187
|
+
used_subrs
|
|
188
|
+
);
|
|
110
189
|
}
|
|
111
190
|
|
|
112
191
|
topDict.FDArray = [{ Private: privateDict }];
|
|
192
|
+
let charstrings = this.charstrings || [];
|
|
113
193
|
return topDict.FDSelect = {
|
|
114
194
|
version: 3,
|
|
115
195
|
nRanges: 1,
|
|
116
196
|
ranges: [{ first: 0, fd: 0 }],
|
|
117
|
-
sentinel:
|
|
197
|
+
sentinel: charstrings.length
|
|
118
198
|
};
|
|
119
199
|
}
|
|
120
200
|
|
|
201
|
+
/**
|
|
202
|
+
* @param {string | null | undefined} string
|
|
203
|
+
* @returns {number | null}
|
|
204
|
+
*/
|
|
121
205
|
addString(string) {
|
|
122
206
|
if (!string) {
|
|
123
207
|
return null;
|
|
@@ -131,28 +215,34 @@ export default class CFFSubset extends Subset {
|
|
|
131
215
|
return standardStrings.length + this.strings.length - 1;
|
|
132
216
|
}
|
|
133
217
|
|
|
218
|
+
/**
|
|
219
|
+
* @returns {import('restructure').BinaryBuffer}
|
|
220
|
+
*/
|
|
134
221
|
encode() {
|
|
135
222
|
this.subsetCharstrings();
|
|
136
223
|
|
|
224
|
+
let charstrings = this.charstrings || [];
|
|
225
|
+
|
|
137
226
|
let charset = {
|
|
138
|
-
version:
|
|
139
|
-
ranges:
|
|
140
|
-
? [{ first: 1, nLeft:
|
|
227
|
+
version: charstrings.length > 255 ? 2 : 1,
|
|
228
|
+
ranges: charstrings.length > 1
|
|
229
|
+
? [{ first: 1, nLeft: charstrings.length - 2 }]
|
|
141
230
|
: []
|
|
142
231
|
};
|
|
143
232
|
|
|
144
|
-
let topDict = Object.assign({}, this.cff.topDict);
|
|
233
|
+
let topDict = /** @type {CFFTopDict} */ (Object.assign({}, this.cff.topDict));
|
|
145
234
|
topDict.Private = null;
|
|
146
235
|
topDict.charset = charset;
|
|
147
236
|
topDict.Encoding = null;
|
|
148
|
-
topDict.CharStrings =
|
|
237
|
+
topDict.CharStrings = charstrings;
|
|
149
238
|
|
|
150
239
|
for (let key of ['version', 'Notice', 'Copyright', 'FullName', 'FamilyName', 'Weight', 'PostScript', 'BaseFontName', 'FontName']) {
|
|
151
|
-
|
|
240
|
+
let sid = /** @type {number | null | undefined} */ (topDict[key]);
|
|
241
|
+
topDict[key] = this.cff.string ? this.addString(this.cff.string(sid)) : null;
|
|
152
242
|
}
|
|
153
243
|
|
|
154
244
|
topDict.ROS = [this.addString('Adobe'), this.addString('Identity'), 0];
|
|
155
|
-
topDict.CIDCount =
|
|
245
|
+
topDict.CIDCount = charstrings.length;
|
|
156
246
|
|
|
157
247
|
if (this.cff.isCIDFont) {
|
|
158
248
|
this.subsetFontdict(topDict);
|