@turntrout/subfont 1.7.0 → 1.8.0

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 (151) hide show
  1. package/CLAUDE.md +39 -13
  2. package/README.md +24 -14
  3. package/lib/FontTracerPool.d.ts +38 -0
  4. package/lib/FontTracerPool.d.ts.map +1 -0
  5. package/lib/FontTracerPool.js +230 -217
  6. package/lib/FontTracerPool.js.map +1 -0
  7. package/lib/HeadlessBrowser.d.ts +18 -0
  8. package/lib/HeadlessBrowser.d.ts.map +1 -0
  9. package/lib/HeadlessBrowser.js +216 -210
  10. package/lib/HeadlessBrowser.js.map +1 -0
  11. package/lib/cli.d.ts +3 -0
  12. package/lib/cli.d.ts.map +1 -0
  13. package/lib/cli.js +15 -12
  14. package/lib/cli.js.map +1 -0
  15. package/lib/codepointMaps.d.ts +4 -0
  16. package/lib/codepointMaps.d.ts.map +1 -0
  17. package/lib/codepointMaps.js +99 -0
  18. package/lib/codepointMaps.js.map +1 -0
  19. package/lib/collectFeatureGlyphIds.d.ts +3 -0
  20. package/lib/collectFeatureGlyphIds.d.ts.map +1 -0
  21. package/lib/collectFeatureGlyphIds.js +124 -138
  22. package/lib/collectFeatureGlyphIds.js.map +1 -0
  23. package/lib/collectTextsByPage.d.ts +41 -0
  24. package/lib/collectTextsByPage.d.ts.map +1 -0
  25. package/lib/collectTextsByPage.js +726 -965
  26. package/lib/collectTextsByPage.js.map +1 -0
  27. package/lib/concurrencyLimit.d.ts +3 -0
  28. package/lib/concurrencyLimit.d.ts.map +1 -0
  29. package/lib/concurrencyLimit.js +12 -11
  30. package/lib/concurrencyLimit.js.map +1 -0
  31. package/lib/escapeJsStringLiteral.d.ts +3 -0
  32. package/lib/escapeJsStringLiteral.d.ts.map +1 -0
  33. package/lib/escapeJsStringLiteral.js +7 -6
  34. package/lib/escapeJsStringLiteral.js.map +1 -0
  35. package/lib/extractReferencedCustomPropertyNames.d.ts +3 -0
  36. package/lib/extractReferencedCustomPropertyNames.d.ts.map +1 -0
  37. package/lib/extractReferencedCustomPropertyNames.js +15 -16
  38. package/lib/extractReferencedCustomPropertyNames.js.map +1 -0
  39. package/lib/extractVisibleText.d.ts +7 -0
  40. package/lib/extractVisibleText.d.ts.map +1 -0
  41. package/lib/extractVisibleText.js +110 -119
  42. package/lib/extractVisibleText.js.map +1 -0
  43. package/lib/findCustomPropertyDefinitions.d.ts +8 -0
  44. package/lib/findCustomPropertyDefinitions.d.ts.map +1 -0
  45. package/lib/findCustomPropertyDefinitions.js +41 -48
  46. package/lib/findCustomPropertyDefinitions.js.map +1 -0
  47. package/lib/fontConverter.d.ts +2 -0
  48. package/lib/fontConverter.d.ts.map +1 -0
  49. package/lib/fontConverter.js +40 -21
  50. package/lib/fontConverter.js.map +1 -0
  51. package/lib/fontConverterWorker.d.ts +2 -0
  52. package/lib/fontConverterWorker.d.ts.map +1 -0
  53. package/lib/fontConverterWorker.js +52 -15
  54. package/lib/fontConverterWorker.js.map +1 -0
  55. package/lib/fontFaceHelpers.d.ts +64 -0
  56. package/lib/fontFaceHelpers.d.ts.map +1 -0
  57. package/lib/fontFaceHelpers.js +237 -249
  58. package/lib/fontFaceHelpers.js.map +1 -0
  59. package/lib/fontFeatureHelpers.d.ts +30 -0
  60. package/lib/fontFeatureHelpers.d.ts.map +1 -0
  61. package/lib/fontFeatureHelpers.js +277 -212
  62. package/lib/fontFeatureHelpers.js.map +1 -0
  63. package/lib/fontTracerWorker.d.ts +11 -0
  64. package/lib/fontTracerWorker.d.ts.map +1 -0
  65. package/lib/fontTracerWorker.js +94 -60
  66. package/lib/fontTracerWorker.js.map +1 -0
  67. package/lib/gatherStylesheetsWithPredicates.d.ts +26 -0
  68. package/lib/gatherStylesheetsWithPredicates.d.ts.map +1 -0
  69. package/lib/gatherStylesheetsWithPredicates.js +75 -84
  70. package/lib/gatherStylesheetsWithPredicates.js.map +1 -0
  71. package/lib/getCssRulesByProperty.d.ts +29 -0
  72. package/lib/getCssRulesByProperty.d.ts.map +1 -0
  73. package/lib/getCssRulesByProperty.js +316 -316
  74. package/lib/getCssRulesByProperty.js.map +1 -0
  75. package/lib/getFontInfo.d.ts +11 -0
  76. package/lib/getFontInfo.d.ts.map +1 -0
  77. package/lib/getFontInfo.js +31 -33
  78. package/lib/getFontInfo.js.map +1 -0
  79. package/lib/initialValueByProp.d.ts +3 -0
  80. package/lib/initialValueByProp.d.ts.map +1 -0
  81. package/lib/initialValueByProp.js +20 -17
  82. package/lib/initialValueByProp.js.map +1 -0
  83. package/lib/injectSubsetDefinitions.d.ts +3 -0
  84. package/lib/injectSubsetDefinitions.d.ts.map +1 -0
  85. package/lib/injectSubsetDefinitions.js +55 -59
  86. package/lib/injectSubsetDefinitions.js.map +1 -0
  87. package/lib/normalizeFontPropertyValue.d.ts +3 -0
  88. package/lib/normalizeFontPropertyValue.d.ts.map +1 -0
  89. package/lib/normalizeFontPropertyValue.js +59 -54
  90. package/lib/normalizeFontPropertyValue.js.map +1 -0
  91. package/lib/parseCommandLineOptions.d.ts +9 -0
  92. package/lib/parseCommandLineOptions.d.ts.map +1 -0
  93. package/lib/parseCommandLineOptions.js +145 -149
  94. package/lib/parseCommandLineOptions.js.map +1 -0
  95. package/lib/parseFontVariationSettings.d.ts +3 -0
  96. package/lib/parseFontVariationSettings.d.ts.map +1 -0
  97. package/lib/parseFontVariationSettings.js +38 -36
  98. package/lib/parseFontVariationSettings.js.map +1 -0
  99. package/lib/progress.d.ts +27 -0
  100. package/lib/progress.d.ts.map +1 -0
  101. package/lib/progress.js +51 -54
  102. package/lib/progress.js.map +1 -0
  103. package/lib/sfntCache.d.ts +4 -0
  104. package/lib/sfntCache.d.ts.map +1 -0
  105. package/lib/sfntCache.js +67 -25
  106. package/lib/sfntCache.js.map +1 -0
  107. package/lib/stripLocalTokens.d.ts +3 -0
  108. package/lib/stripLocalTokens.d.ts.map +1 -0
  109. package/lib/stripLocalTokens.js +23 -21
  110. package/lib/stripLocalTokens.js.map +1 -0
  111. package/lib/subfont.d.ts +54 -0
  112. package/lib/subfont.d.ts.map +1 -0
  113. package/lib/subfont.js +531 -629
  114. package/lib/subfont.js.map +1 -0
  115. package/lib/subsetFontWithGlyphs.d.ts +21 -0
  116. package/lib/subsetFontWithGlyphs.d.ts.map +1 -0
  117. package/lib/subsetFontWithGlyphs.js +285 -259
  118. package/lib/subsetFontWithGlyphs.js.map +1 -0
  119. package/lib/subsetFonts.d.ts +55 -0
  120. package/lib/subsetFonts.d.ts.map +1 -0
  121. package/lib/subsetFonts.js +899 -1200
  122. package/lib/subsetFonts.js.map +1 -0
  123. package/lib/subsetGeneration.d.ts +36 -0
  124. package/lib/subsetGeneration.d.ts.map +1 -0
  125. package/lib/subsetGeneration.js +328 -325
  126. package/lib/subsetGeneration.js.map +1 -0
  127. package/lib/types/shared.d.ts +11 -0
  128. package/lib/types/shared.d.ts.map +1 -0
  129. package/lib/types/shared.js +3 -0
  130. package/lib/types/shared.js.map +1 -0
  131. package/lib/unicodeRange.d.ts +3 -0
  132. package/lib/unicodeRange.d.ts.map +1 -0
  133. package/lib/unicodeRange.js +17 -30
  134. package/lib/unicodeRange.js.map +1 -0
  135. package/lib/unquote.d.ts +3 -0
  136. package/lib/unquote.d.ts.map +1 -0
  137. package/lib/unquote.js +18 -25
  138. package/lib/unquote.js.map +1 -0
  139. package/lib/variationAxes.d.ts +33 -0
  140. package/lib/variationAxes.d.ts.map +1 -0
  141. package/lib/variationAxes.js +127 -157
  142. package/lib/variationAxes.js.map +1 -0
  143. package/lib/warnAboutMissingGlyphs.d.ts +43 -0
  144. package/lib/warnAboutMissingGlyphs.d.ts.map +1 -0
  145. package/lib/warnAboutMissingGlyphs.js +139 -147
  146. package/lib/warnAboutMissingGlyphs.js.map +1 -0
  147. package/lib/wasmQueue.d.ts +3 -0
  148. package/lib/wasmQueue.d.ts.map +1 -0
  149. package/lib/wasmQueue.js +13 -10
  150. package/lib/wasmQueue.js.map +1 -0
  151. package/package.json +12 -2
@@ -1,316 +1,342 @@
1
- const os = require('os');
2
- const { readFile } = require('fs').promises;
3
- const fontverter = require('fontverter');
4
- const { toSfnt } = require('./sfntCache');
5
- const { convert: convertInWorker } = require('./fontConverter');
6
-
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ const os = require("os");
36
+ const promises_1 = require("fs/promises");
37
+ const fontverter = __importStar(require("fontverter"));
38
+ const sfntCache_1 = require("./sfntCache");
39
+ const fontConverter_1 = require("./fontConverter");
7
40
  // hb_subset_sets_t enum values — https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-subset.h
8
41
  const HB_SUBSET_SETS_GLYPH_INDEX = 0;
9
- const HB_SUBSET_SETS_DROP_TABLE_TAG = 5;
10
- const HB_SUBSET_SETS_LAYOUT_FEATURE_TAG = 6;
42
+ const HB_SUBSET_SETS_DROP_TABLE_TAG = 3;
11
43
  const HB_SUBSET_SETS_NAME_ID = 4;
12
-
44
+ const HB_SUBSET_SETS_NAME_LANG_ID = 5;
45
+ const HB_SUBSET_SETS_LAYOUT_FEATURE_TAG = 6;
46
+ const HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG = 7;
47
+ // Windows English (United States). The only name-table language we keep —
48
+ // browsers don't expose localized name strings to web pages, so other lang
49
+ // IDs are pure overhead.
50
+ const KEEP_NAME_LANG_ID_EN_US = 0x0409;
13
51
  // hb_subset_flags_t
14
52
  const HB_SUBSET_FLAGS_NO_HINTING = 0x00000001;
15
-
16
53
  // Pool of WASM instances for parallel subsetting. Each instance has its
17
54
  // own linear memory so concurrent calls are safe. The module is compiled
18
55
  // once and instantiated N times (N = CPU count, capped at 8).
19
56
  let _compilePromise;
20
57
  function compileModule() {
21
- if (!_compilePromise) {
22
- // Assign the promise synchronously so concurrent callers share it
23
- // (an async function would await readFile before the assignment).
24
- _compilePromise = readFile(
25
- require.resolve('harfbuzzjs/hb-subset.wasm')
26
- ).then((buf) => WebAssembly.compile(buf));
27
- }
28
- return _compilePromise;
58
+ if (!_compilePromise) {
59
+ // Assign the promise synchronously so concurrent callers share it
60
+ // (an async function would await readFile before the assignment).
61
+ _compilePromise = (0, promises_1.readFile)(require.resolve('harfbuzzjs/hb-subset.wasm')).then((buf) => WebAssembly.compile(buf));
62
+ }
63
+ return _compilePromise;
29
64
  }
30
-
31
- const _pool = []; // Array of { exports, busy: boolean }
65
+ const _pool = [];
32
66
  let _poolReady;
33
67
  const POOL_SIZE = Math.max(1, Math.min(os.cpus().length, 8));
34
-
35
68
  async function initPool() {
36
- if (!_poolReady) {
37
- _poolReady = (async () => {
38
- const mod = await compileModule();
39
- const instantiations = [];
40
- for (let i = 0; i < POOL_SIZE; i++) {
41
- instantiations.push(
42
- WebAssembly.instantiate(mod).then(({ exports }) => {
43
- _pool.push({ exports, busy: false });
44
- })
45
- );
46
- }
47
- await Promise.all(instantiations);
48
- })();
49
- }
50
- return _poolReady;
69
+ if (!_poolReady) {
70
+ _poolReady = (async () => {
71
+ const mod = await compileModule();
72
+ const instantiations = [];
73
+ for (let i = 0; i < POOL_SIZE; i++) {
74
+ instantiations.push(WebAssembly.instantiate(mod).then((inst) => {
75
+ _pool.push({
76
+ // WebAssembly.Exports is opaque (Record<string, ExportValue>);
77
+ // bridge it to our typed surface in one place.
78
+ // eslint-disable-next-line no-restricted-syntax
79
+ exports: inst.exports,
80
+ busy: false,
81
+ });
82
+ }));
83
+ }
84
+ await Promise.all(instantiations);
85
+ })();
86
+ }
87
+ return _poolReady;
51
88
  }
52
-
53
89
  // Waiters queue: callers waiting for an idle WASM instance.
54
90
  const _waiters = [];
55
91
  const ACQUIRE_TIMEOUT_MS = 120_000;
56
-
57
92
  async function acquireInstance() {
58
- await initPool();
59
- const idle = _pool.find((inst) => !inst.busy);
60
- if (idle) {
61
- idle.busy = true;
62
- return idle;
63
- }
64
- // All instances busy — wait for one to be released.
65
- return new Promise((resolve, reject) => {
66
- const timer = setTimeout(() => {
67
- const idx = _waiters.indexOf(entry);
68
- if (idx !== -1) _waiters.splice(idx, 1);
69
- reject(
70
- new Error(
71
- `Timed out waiting for a WASM subsetting instance after ${ACQUIRE_TIMEOUT_MS}ms`
72
- )
73
- );
74
- }, ACQUIRE_TIMEOUT_MS);
75
- timer.unref();
76
- const entry = (inst) => {
77
- clearTimeout(timer);
78
- resolve(inst);
79
- };
80
- _waiters.push(entry);
81
- });
93
+ await initPool();
94
+ const idle = _pool.find((inst) => !inst.busy);
95
+ if (idle) {
96
+ idle.busy = true;
97
+ return idle;
98
+ }
99
+ // All instances busy — wait for one to be released.
100
+ return new Promise((resolve, reject) => {
101
+ const entry = (inst) => {
102
+ clearTimeout(timer);
103
+ resolve(inst);
104
+ };
105
+ const timer = setTimeout(() => {
106
+ const idx = _waiters.indexOf(entry);
107
+ if (idx !== -1)
108
+ _waiters.splice(idx, 1);
109
+ reject(new Error(`Timed out waiting for a WASM subsetting instance after ${ACQUIRE_TIMEOUT_MS}ms`));
110
+ }, ACQUIRE_TIMEOUT_MS);
111
+ timer.unref();
112
+ _waiters.push(entry);
113
+ });
82
114
  }
83
-
84
115
  function releaseInstance(inst) {
85
- inst.busy = false;
86
- if (_waiters.length > 0) {
87
- inst.busy = true;
88
- _waiters.shift()(inst);
89
- }
116
+ inst.busy = false;
117
+ if (_waiters.length > 0) {
118
+ inst.busy = true;
119
+ const waiter = _waiters.shift();
120
+ if (waiter)
121
+ waiter(inst);
122
+ }
90
123
  }
91
-
92
124
  // woff2 encode/decode uses wawoff2's WASM module, which has a shared
93
125
  // instance that corrupts memory under concurrent use. Instead of
94
126
  // serializing to p-limit(1) in the main thread, we route woff2
95
127
  // operations through fontConverterPool — each worker thread loads its
96
128
  // own wawoff2 instance, enabling safe parallel compression.
97
-
98
129
  // Re-create on every call — WASM memory.buffer is detached when memory grows,
99
130
  // so a cached Uint8Array would silently read/write stale data.
100
131
  function getHeapu8(exports) {
101
- return new Uint8Array(exports.memory.buffer);
132
+ return new Uint8Array(exports.memory.buffer);
102
133
  }
103
-
104
134
  // >>> 0 keeps the accumulator unsigned; without it, tags whose first byte
105
135
  // exceeds 0x7F would overflow into negative i32 territory after << 24.
106
136
  function HB_TAG(str) {
107
- return str.split('').reduce(function (a, ch) {
108
- return ((a << 8) >>> 0) + ch.charCodeAt(0);
109
- }, 0);
137
+ return str.split('').reduce(function (a, ch) {
138
+ return ((a << 8) >>> 0) + ch.charCodeAt(0);
139
+ }, 0);
110
140
  }
111
-
112
141
  function pinAxisLocation(exports, input, face, axisName, value) {
113
- const ok = exports.hb_subset_input_pin_axis_location(
114
- input,
115
- face,
116
- HB_TAG(axisName),
117
- value
118
- );
119
- if (!ok) {
120
- throw new Error(`Failed to pin axis ${axisName} to ${value}`);
121
- }
142
+ const ok = exports.hb_subset_input_pin_axis_location(input, face, HB_TAG(axisName), value);
143
+ if (!ok) {
144
+ throw new Error(`Failed to pin axis ${axisName} to ${value}`);
145
+ }
122
146
  }
123
-
124
147
  function setAxisRange(exports, input, face, axisName, value) {
125
- const ok = exports.hb_subset_input_set_axis_range(
126
- input,
127
- face,
128
- HB_TAG(axisName),
129
- value.min,
130
- value.max,
131
- value.default ?? NaN
132
- );
133
- if (!ok) {
134
- throw new Error(`Failed to set axis range for ${axisName}`);
135
- }
148
+ const ok = exports.hb_subset_input_set_axis_range(input, face, HB_TAG(axisName), value.min, value.max, value.default ?? NaN);
149
+ if (!ok) {
150
+ throw new Error(`Failed to set axis range for ${axisName}`);
151
+ }
136
152
  }
137
-
138
153
  // Tables unnecessary for web rendering — safe to drop unconditionally.
139
- // gasp is only meaningful when hinting is present (which we strip above).
154
+ // HB_SUBSET_FLAGS_NO_HINTING already drops cvt/fpgm/prep/hdmx in the
155
+ // harfbuzzjs build we use; gasp/LTSH/VDMX/DSIG/PCLT survive the flag and
156
+ // must be dropped here.
140
157
  const DROP_TABLE_TAGS = ['DSIG', 'LTSH', 'VDMX', 'hdmx', 'gasp', 'PCLT'];
141
-
158
+ // Color and bitmap tables — only relevant for color emoji (Apple/Google)
159
+ // and legacy bitmap fonts. Dropped only when the caller signals that no
160
+ // color content needs to render with this font.
161
+ // Note: 'SVG ' has a trailing space (4-byte tag).
162
+ const COLOR_TABLE_TAGS = [
163
+ 'COLR',
164
+ 'CPAL',
165
+ 'SVG ',
166
+ 'CBDT',
167
+ 'CBLC',
168
+ 'sbix',
169
+ 'EBDT',
170
+ 'EBLC',
171
+ 'EBSC',
172
+ ];
142
173
  // Name IDs needed for web fonts: family (1), subfamily (2), full name (4),
143
174
  // PostScript name (6). Copyright (0), unique ID (3), version (5), and
144
175
  // everything above 6 are display/license metadata that browsers never read.
145
176
  const KEEP_NAME_IDS = [1, 2, 4, 6];
146
-
147
- function configureSubsetInput(
148
- exports,
149
- input,
150
- face,
151
- text,
152
- glyphIds,
153
- variationAxes
154
- ) {
155
- // --- Retain all layout features ---
156
- const layoutFeatures = exports.hb_subset_input_set(
157
- input,
158
- HB_SUBSET_SETS_LAYOUT_FEATURE_TAG
159
- );
160
- exports.hb_set_clear(layoutFeatures);
161
- exports.hb_set_invert(layoutFeatures);
162
-
163
- // --- Strip hinting instructions (ignored by modern browsers) ---
164
- const flags = exports.hb_subset_input_get_flags(input);
165
- exports.hb_subset_input_set_flags(input, flags | HB_SUBSET_FLAGS_NO_HINTING);
166
-
167
- // --- Keep only essential name table entries ---
168
- const nameIdSet = exports.hb_subset_input_set(input, HB_SUBSET_SETS_NAME_ID);
169
- exports.hb_set_clear(nameIdSet);
170
- for (const id of KEEP_NAME_IDS) {
171
- exports.hb_set_add(nameIdSet, id);
172
- }
173
-
174
- // --- Drop tables not needed for web rendering ---
175
- const dropTableSet = exports.hb_subset_input_set(
176
- input,
177
- HB_SUBSET_SETS_DROP_TABLE_TAG
178
- );
179
- for (const tag of DROP_TABLE_TAGS) {
180
- exports.hb_set_add(dropTableSet, HB_TAG(tag));
181
- }
182
-
183
- // --- Add unicode codepoints ---
184
- const inputUnicodes = exports.hb_subset_input_unicode_set(input);
185
- // Include codepoints from both NFC and NFD normalized forms so the
186
- // subsetter covers precomposed and decomposed character variants.
187
- // This guards against harfbuzz subsetter not always expanding
188
- // codepoints to their NFC/NFD equivalents (harfbuzz issue #2283).
189
- const nfc = text.normalize('NFC');
190
- const nfd = text.normalize('NFD');
191
- for (const c of nfc) {
192
- exports.hb_set_add(inputUnicodes, c.codePointAt(0));
193
- }
194
- for (const c of nfd) {
195
- exports.hb_set_add(inputUnicodes, c.codePointAt(0));
196
- }
197
-
198
- // --- Add explicit glyph IDs (from feature glyph collection) ---
199
- if (glyphIds && glyphIds.length > 0) {
200
- const glyphSet = exports.hb_subset_input_set(
201
- input,
202
- HB_SUBSET_SETS_GLYPH_INDEX
203
- );
204
- for (const gid of glyphIds) {
205
- exports.hb_set_add(glyphSet, gid);
177
+ function configureSubsetInput(exports, input, face, text, glyphIds, variationAxes, featureTags, dropMathTable, dropColorTables, scriptTags) {
178
+ // --- Retain layout features ---
179
+ // hb_subset_input_create_or_fail pre-populates the layout-features set with
180
+ // a curated list of shaping-essential tags (locl, ccmp, calt, mark, mkmk,
181
+ // Indic/Arabic/Khmer shaping features, etc.). When the caller passes
182
+ // featureTags, we leave that default in place and add the CSS-requested
183
+ // tags on top. Optional features the page never references (e.g. ss##,
184
+ // cv##, smcp, swsh) are then dropped, shrinking the GSUB/GPOS tables.
185
+ // When featureTags is undefined, fall back to retain-all behavior.
186
+ const layoutFeatures = exports.hb_subset_input_set(input, HB_SUBSET_SETS_LAYOUT_FEATURE_TAG);
187
+ if (featureTags === undefined) {
188
+ exports.hb_set_clear(layoutFeatures);
189
+ exports.hb_set_invert(layoutFeatures);
190
+ }
191
+ else {
192
+ for (const tag of featureTags) {
193
+ exports.hb_set_add(layoutFeatures, HB_TAG(tag));
194
+ }
206
195
  }
207
- }
208
-
209
- // --- Pin/reduce variation axes ---
210
- if (variationAxes) {
211
- for (const [axisName, value] of Object.entries(variationAxes)) {
212
- if (typeof value === 'number') {
213
- pinAxisLocation(exports, input, face, axisName, value);
214
- } else if (value && typeof value === 'object') {
215
- setAxisRange(exports, input, face, axisName, value);
216
- }
196
+ // --- Retain layout scripts ---
197
+ // When scriptTags is provided, replace harfbuzz's default (all scripts)
198
+ // with exactly the listed tags. Undefined leaves the default in place.
199
+ if (scriptTags !== undefined) {
200
+ const layoutScripts = exports.hb_subset_input_set(input, HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG);
201
+ exports.hb_set_clear(layoutScripts);
202
+ for (const tag of scriptTags) {
203
+ exports.hb_set_add(layoutScripts, HB_TAG(tag));
204
+ }
205
+ }
206
+ // --- Strip hinting instructions (ignored by modern browsers) ---
207
+ const flags = exports.hb_subset_input_get_flags(input);
208
+ exports.hb_subset_input_set_flags(input, flags | HB_SUBSET_FLAGS_NO_HINTING);
209
+ // --- Keep only essential name table entries ---
210
+ const nameIdSet = exports.hb_subset_input_set(input, HB_SUBSET_SETS_NAME_ID);
211
+ exports.hb_set_clear(nameIdSet);
212
+ for (const id of KEEP_NAME_IDS) {
213
+ exports.hb_set_add(nameIdSet, id);
214
+ }
215
+ // --- Keep only en-US localized name strings ---
216
+ const nameLangSet = exports.hb_subset_input_set(input, HB_SUBSET_SETS_NAME_LANG_ID);
217
+ exports.hb_set_clear(nameLangSet);
218
+ exports.hb_set_add(nameLangSet, KEEP_NAME_LANG_ID_EN_US);
219
+ // --- Drop tables not needed for web rendering ---
220
+ const dropTableSet = exports.hb_subset_input_set(input, HB_SUBSET_SETS_DROP_TABLE_TAG);
221
+ for (const tag of DROP_TABLE_TAGS) {
222
+ exports.hb_set_add(dropTableSet, HB_TAG(tag));
223
+ }
224
+ if (dropMathTable) {
225
+ exports.hb_set_add(dropTableSet, HB_TAG('MATH'));
226
+ }
227
+ if (dropColorTables) {
228
+ for (const tag of COLOR_TABLE_TAGS) {
229
+ exports.hb_set_add(dropTableSet, HB_TAG(tag));
230
+ }
231
+ }
232
+ // --- Add unicode codepoints ---
233
+ const inputUnicodes = exports.hb_subset_input_unicode_set(input);
234
+ // Include codepoints from both NFC and NFD normalized forms so the
235
+ // subsetter covers precomposed and decomposed character variants.
236
+ // This guards against harfbuzz subsetter not always expanding
237
+ // codepoints to their NFC/NFD equivalents (harfbuzz issue #2283).
238
+ const nfc = text.normalize('NFC');
239
+ const nfd = text.normalize('NFD');
240
+ for (const c of nfc) {
241
+ exports.hb_set_add(inputUnicodes, c.codePointAt(0));
242
+ }
243
+ for (const c of nfd) {
244
+ exports.hb_set_add(inputUnicodes, c.codePointAt(0));
245
+ }
246
+ // --- Add explicit glyph IDs (from feature glyph collection) ---
247
+ if (glyphIds && glyphIds.length > 0) {
248
+ const glyphSet = exports.hb_subset_input_set(input, HB_SUBSET_SETS_GLYPH_INDEX);
249
+ for (const gid of glyphIds) {
250
+ exports.hb_set_add(glyphSet, gid);
251
+ }
252
+ }
253
+ // --- Pin/reduce variation axes ---
254
+ if (variationAxes) {
255
+ for (const [axisName, value] of Object.entries(variationAxes)) {
256
+ if (typeof value === 'number') {
257
+ pinAxisLocation(exports, input, face, axisName, value);
258
+ }
259
+ else if (value && typeof value === 'object') {
260
+ setAxisRange(exports, input, face, axisName, value);
261
+ }
262
+ }
217
263
  }
218
- }
219
264
  }
220
-
221
265
  function extractSubsetFont(exports, subset) {
222
- const result = exports.hb_face_reference_blob(subset);
223
- const offset = exports.hb_blob_get_data(result, 0);
224
- const subsetByteLength = exports.hb_blob_get_length(result);
225
-
226
- if (subsetByteLength === 0) {
227
- exports.hb_blob_destroy(result);
228
- throw new Error('Failed to create subset font');
229
- }
230
-
231
- // Fresh view AFTER the WASM calls above — memory.buffer may have been
232
- // detached by a grow during hb_face_reference_blob / hb_blob_get_data.
233
- const heapu8 = getHeapu8(exports);
234
-
235
- if (offset + subsetByteLength > heapu8.byteLength) {
266
+ const result = exports.hb_face_reference_blob(subset);
267
+ const offset = exports.hb_blob_get_data(result, 0);
268
+ const subsetByteLength = exports.hb_blob_get_length(result);
269
+ if (subsetByteLength === 0) {
270
+ exports.hb_blob_destroy(result);
271
+ throw new Error('Failed to create subset font');
272
+ }
273
+ // Fresh view AFTER the WASM calls above — memory.buffer may have been
274
+ // detached by a grow during hb_face_reference_blob / hb_blob_get_data.
275
+ const heapu8 = getHeapu8(exports);
276
+ if (offset < 0 || offset + subsetByteLength > heapu8.byteLength) {
277
+ exports.hb_blob_destroy(result);
278
+ throw new Error(`WASM returned out-of-bounds offset ${offset} + length ${subsetByteLength} (heap size ${heapu8.byteLength})`);
279
+ }
280
+ const subsetFont = Buffer.from(heapu8.subarray(offset, offset + subsetByteLength));
236
281
  exports.hb_blob_destroy(result);
237
- throw new Error(
238
- `WASM returned out-of-bounds offset ${offset} + length ${subsetByteLength} (heap size ${heapu8.byteLength})`
239
- );
240
- }
241
-
242
- const subsetFont = Buffer.from(
243
- heapu8.subarray(offset, offset + subsetByteLength)
244
- );
245
- exports.hb_blob_destroy(result);
246
- return subsetFont;
282
+ return subsetFont;
247
283
  }
248
-
249
- async function subsetFontWithGlyphs(
250
- originalFont,
251
- text,
252
- { targetFormat, glyphIds, variationAxes } = {}
253
- ) {
254
- // Reuse cached sfnt conversion when available (same buffer may have
255
- // been converted by getFontInfo or collectFeatureGlyphIds already).
256
- // sfntCache routes woff2 decompression through the worker pool.
257
- const ttf = await toSfnt(originalFont);
258
-
259
- const inst = await acquireInstance();
260
- const { exports } = inst;
261
- let released = false;
262
- try {
263
- const fontBuffer = exports.malloc(ttf.byteLength);
264
- // Fresh view — memory.buffer may have been detached by a prior malloc/grow.
265
- getHeapu8(exports).set(new Uint8Array(ttf), fontBuffer);
266
-
267
- const blob = exports.hb_blob_create(fontBuffer, ttf.byteLength, 2, 0, 0);
268
- const face = exports.hb_face_create(blob, 0);
269
- exports.hb_blob_destroy(blob);
270
-
271
- const input = exports.hb_subset_input_create_or_fail();
272
- if (input === 0) {
273
- exports.hb_face_destroy(face);
274
- exports.free(fontBuffer);
275
- throw new Error('hb_subset_input_create_or_fail returned zero');
276
- }
277
-
278
- let subsetFont;
279
- let subset = 0;
284
+ async function subsetFontWithGlyphs(originalFont, text, { targetFormat, glyphIds, variationAxes, featureTags, dropMathTable = false, dropColorTables = false, scriptTags, } = {}) {
285
+ // Reuse cached sfnt conversion when available (same buffer may have
286
+ // been converted by getFontInfo or collectFeatureGlyphIds already).
287
+ // sfntCache routes woff2 decompression through the worker pool.
288
+ const ttf = await (0, sfntCache_1.toSfnt)(originalFont);
289
+ const inst = await acquireInstance();
290
+ const { exports } = inst;
291
+ let released = false;
280
292
  try {
281
- configureSubsetInput(exports, input, face, text, glyphIds, variationAxes);
282
-
283
- subset = exports.hb_subset_or_fail(face, input);
284
- if (subset === 0) {
285
- throw new Error('hb_subset_or_fail returned zero');
286
- }
287
-
288
- subsetFont = extractSubsetFont(exports, subset);
289
- } finally {
290
- // Clean up all WASM resources while we still own the instance.
291
- if (subset) exports.hb_face_destroy(subset);
292
- exports.hb_subset_input_destroy(input);
293
- exports.hb_face_destroy(face);
294
- exports.free(fontBuffer);
293
+ const fontBuffer = exports.malloc(ttf.byteLength);
294
+ // Fresh view — memory.buffer may have been detached by a prior malloc/grow.
295
+ getHeapu8(exports).set(new Uint8Array(ttf), fontBuffer);
296
+ const blob = exports.hb_blob_create(fontBuffer, ttf.byteLength, 2, 0, 0);
297
+ const face = exports.hb_face_create(blob, 0);
298
+ exports.hb_blob_destroy(blob);
299
+ const input = exports.hb_subset_input_create_or_fail();
300
+ if (input === 0) {
301
+ exports.hb_face_destroy(face);
302
+ exports.free(fontBuffer);
303
+ throw new Error('hb_subset_input_create_or_fail returned zero');
304
+ }
305
+ let subsetFont;
306
+ let subset = 0;
307
+ try {
308
+ configureSubsetInput(exports, input, face, text, glyphIds, variationAxes, featureTags, dropMathTable, dropColorTables, scriptTags);
309
+ subset = exports.hb_subset_or_fail(face, input);
310
+ if (subset === 0) {
311
+ throw new Error('hb_subset_or_fail returned zero');
312
+ }
313
+ subsetFont = extractSubsetFont(exports, subset);
314
+ }
315
+ finally {
316
+ // Clean up all WASM resources while we still own the instance.
317
+ if (subset)
318
+ exports.hb_face_destroy(subset);
319
+ exports.hb_subset_input_destroy(input);
320
+ exports.hb_face_destroy(face);
321
+ exports.free(fontBuffer);
322
+ }
323
+ // Instance is fully cleaned up — release it so other subsetting
324
+ // calls can proceed while we wait for the serialized WOFF2 step.
325
+ released = true;
326
+ releaseInstance(inst);
327
+ // Route woff2 compression to a worker thread (each spawns its own
328
+ // wawoff2 WASM instance). Non-woff2 formats use JS-based converters
329
+ // that are safe to call concurrently in the main thread.
330
+ return targetFormat === 'woff2'
331
+ ? (0, fontConverter_1.convert)(subsetFont, targetFormat, 'truetype')
332
+ : fontverter.convert(subsetFont, targetFormat, 'truetype');
333
+ }
334
+ finally {
335
+ if (!released)
336
+ releaseInstance(inst);
295
337
  }
296
-
297
- // Instance is fully cleaned up — release it so other subsetting
298
- // calls can proceed while we wait for the serialized WOFF2 step.
299
- released = true;
300
- releaseInstance(inst);
301
-
302
- // Route woff2 compression to a worker thread (each spawns its own
303
- // wawoff2 WASM instance). Non-woff2 formats use JS-based converters
304
- // that are safe to call concurrently in the main thread.
305
- return targetFormat === 'woff2'
306
- ? convertInWorker(subsetFont, targetFormat, 'truetype')
307
- : fontverter.convert(subsetFont, targetFormat, 'truetype');
308
- } finally {
309
- if (!released) releaseInstance(inst);
310
- }
311
338
  }
312
-
313
339
  // Pre-warm the WASM pool: call early to overlap compilation with other work.
314
340
  subsetFontWithGlyphs.warmup = () => initPool();
315
-
316
341
  module.exports = subsetFontWithGlyphs;
342
+ //# sourceMappingURL=subsetFontWithGlyphs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subsetFontWithGlyphs.js","sourceRoot":"","sources":["../src/subsetFontWithGlyphs.ts"],"names":[],"mappings":"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"}