@weasel-js/font 1.9.3 → 1.9.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.
@@ -97,6 +97,19 @@ function parseBmFont(raw) {
97
97
  if (!Array.isArray(r.chars)) throw new Error("parseBmFont: chars must be an array");
98
98
  const info = r.info;
99
99
  const common = r.common;
100
+ const positive = [
101
+ ["info.size", info.size],
102
+ ["common.scaleW", common.scaleW],
103
+ ["common.scaleH", common.scaleH]
104
+ ];
105
+ for (const [name, value] of positive) {
106
+ if (typeof value !== "number" || !(value > 0) || !Number.isFinite(value)) {
107
+ throw new Error(`parseBmFont: ${name} must be a positive number`);
108
+ }
109
+ }
110
+ if (typeof common.base !== "number" || !Number.isFinite(common.base)) {
111
+ throw new Error("parseBmFont: common.base must be a number");
112
+ }
100
113
  const chars = r.chars;
101
114
  const kernings = Array.isArray(r.kernings) ? r.kernings : [];
102
115
  const charMap = /* @__PURE__ */ new Map();
@@ -601,9 +614,7 @@ function _resetDynamicFontsForTests() {
601
614
  // src/outline/OutlineFace.ts
602
615
  var OUTLINE_PRECISION = 5;
603
616
 
604
- // src/outline/sfnt.ts
605
- var SFNT_HEADER_BYTES = 12;
606
- var TABLE_RECORD_BYTES = 16;
617
+ // src/outline/tag.ts
607
618
  function tagAt(view, offset) {
608
619
  return String.fromCharCode(
609
620
  view.getUint8(offset),
@@ -612,10 +623,11 @@ function tagAt(view, offset) {
612
623
  view.getUint8(offset + 3)
613
624
  );
614
625
  }
615
- function isFontCollection(bytes) {
616
- if (bytes.byteLength < 4) return false;
617
- return tagAt(new DataView(bytes), 0) === "ttcf";
618
- }
626
+
627
+ // src/outline/dataFork.ts
628
+ var RESOURCE_HEADER_BYTES = 16;
629
+ var TYPE_ENTRY_BYTES = 8;
630
+ var REFERENCE_BYTES = 12;
619
631
  var FONT_SIGNATURES = /* @__PURE__ */ new Set([
620
632
  "\0\0\0",
621
633
  "true",
@@ -625,7 +637,6 @@ var FONT_SIGNATURES = /* @__PURE__ */ new Set([
625
637
  "wOFF",
626
638
  "wOF2"
627
639
  ]);
628
- var RESOURCE_HEADER_BYTES = 16;
629
640
  function isDataForkFont(bytes) {
630
641
  if (bytes.byteLength < RESOURCE_HEADER_BYTES) return false;
631
642
  const view = new DataView(bytes);
@@ -636,6 +647,46 @@ function isDataForkFont(bytes) {
636
647
  const mapLength = view.getUint32(12);
637
648
  return dataOffset >= RESOURCE_HEADER_BYTES && dataOffset + dataLength === mapOffset && mapOffset + mapLength <= bytes.byteLength;
638
649
  }
650
+ var truncated = () => new Error("Datafork TrueType (.dfont) is truncated: a resource runs past the end of its segment.");
651
+ function sfntResources(bytes) {
652
+ const view = new DataView(bytes);
653
+ const dataOffset = view.getUint32(0);
654
+ const mapOffset = view.getUint32(4);
655
+ const dataLength = view.getUint32(8);
656
+ const mapEnd = mapOffset + view.getUint32(12);
657
+ const inMap = (at, count) => at >= mapOffset && at + count <= mapEnd;
658
+ if (!inMap(mapOffset + 24, 2)) return [];
659
+ const typeList = mapOffset + view.getUint16(mapOffset + 24);
660
+ if (!inMap(typeList, 2)) return [];
661
+ const typeCount = view.getUint16(typeList) + 1 & 65535;
662
+ const out = [];
663
+ for (let t = 0; t < typeCount; t++) {
664
+ const entry = typeList + 2 + t * TYPE_ENTRY_BYTES;
665
+ if (!inMap(entry, TYPE_ENTRY_BYTES)) throw truncated();
666
+ if (tagAt(view, entry) !== "sfnt") continue;
667
+ const count = view.getUint16(entry + 4) + 1;
668
+ const references = typeList + view.getUint16(entry + 6);
669
+ for (let i = 0; i < count; i++) {
670
+ const ref = references + i * REFERENCE_BYTES;
671
+ if (!inMap(ref, REFERENCE_BYTES)) throw truncated();
672
+ const offset = view.getUint32(ref + 4) & 16777215;
673
+ if (offset + 4 > dataLength) throw truncated();
674
+ const start = dataOffset + offset + 4;
675
+ const length = view.getUint32(start - 4);
676
+ if (offset + 4 + length > dataLength) throw truncated();
677
+ out.push(bytes.slice(start, start + length));
678
+ }
679
+ }
680
+ return out;
681
+ }
682
+
683
+ // src/outline/sfnt.ts
684
+ var SFNT_HEADER_BYTES = 12;
685
+ var TABLE_RECORD_BYTES = 16;
686
+ function isFontCollection(bytes) {
687
+ if (bytes.byteLength < 4) return false;
688
+ return tagAt(new DataView(bytes), 0) === "ttcf";
689
+ }
639
690
  function readTableDirectory(view, dirOffset) {
640
691
  const numTables = view.getUint16(dirOffset + 4);
641
692
  const records = [];
@@ -674,7 +725,12 @@ function extractFont(source, view, dirOffset) {
674
725
  const records = readTableDirectory(view, dirOffset);
675
726
  const padded = (n) => n + 3 & -4;
676
727
  let total = SFNT_HEADER_BYTES + records.length * TABLE_RECORD_BYTES;
677
- for (const r of records) total += padded(r.length);
728
+ for (const r of records) {
729
+ if (r.offset + r.length > source.byteLength) {
730
+ throw new Error(`font collection is truncated: table "${r.tag}" runs past the end of the file`);
731
+ }
732
+ total += padded(r.length);
733
+ }
678
734
  const out = new ArrayBuffer(total);
679
735
  const dst = new DataView(out);
680
736
  const dstBytes = new Uint8Array(out);
@@ -700,9 +756,13 @@ function extractFont(source, view, dirOffset) {
700
756
  }
701
757
  function sfntFromCollection(bytes, postScriptName) {
702
758
  if (isDataForkFont(bytes)) {
703
- throw new Error(
704
- "Datafork TrueType (.dfont) is not supported \u2014 the outline tier reads sfnt tables and a .dfont holds them inside a Macintosh resource map."
705
- );
759
+ const fonts = sfntResources(bytes);
760
+ if (fonts.length === 0) throw new Error("Datafork TrueType (.dfont) holds no sfnt resource.");
761
+ const named = postScriptName ? fonts.find((font) => {
762
+ const view2 = new DataView(font);
763
+ return postScriptNameAt(view2, readTableDirectory(view2, 0)) === postScriptName;
764
+ }) : void 0;
765
+ return { bytes: named ?? fonts[0], matched: named !== void 0 || !postScriptName };
706
766
  }
707
767
  if (!isFontCollection(bytes)) return { bytes, matched: true };
708
768
  const view = new DataView(bytes);
@@ -1301,6 +1361,7 @@ function missResolveResult(family, weight, style, suppressWarn = false) {
1301
1361
  source: "outline"
1302
1362
  };
1303
1363
  }
1364
+ if (fontPending(family, weight, style)) return pendingMiss(family, weight, style);
1304
1365
  const policy2 = getFontFallbackPolicy();
1305
1366
  if (policy2 === "canvas") {
1306
1367
  autoEnrollCanvasFont(family);
@@ -1606,5 +1667,5 @@ function _resetDomFacesForTests() {
1606
1667
  }
1607
1668
 
1608
1669
  export { DEFAULT_BAKE_BUDGET, FIXTURE_FONT, PAGE_SIZE, SDF_RADIUS, __setGlyphRasterizerForTests, _getPagesForTests, _resetDomFacesForTests, _resetDynamicFontsForTests, _resetFallbackForTests, _resetFontOutlinesForTests, _resetFontRegistryForTests, createOpenTypeParser, cssFamilyName, cssFontFamily, cssFontFamilyLoading, dynamicPageTextureId, ensureFontTexture, faceMetricsFor, faceMetricsFromTables, faceMetricsOf, fontOutlineRegistry, fontPending, fontRegistry, getDefaultFontFamily, getFont, getFontFallbackPolicy, glyphGeneration, glyphOutline, hasFontOutlines, isCanvasFont, listCanvasFonts, listFontOutlines, listFontWeights, listFonts, loadFontOutlines, markAllFontsNotUploaded, outlineMetrics, outlineStatus, parseBmFont, registerCanvasFont, registerFont, registerFontOutlines, resetBakeBudget, resolveFontVariant, resolveGlyphFallback, setDefaultFontFamily, setFontFallbackPolicy, subscribeGlyphReady, syncDynamicPageTexture, textureCacheKey, unregisterCanvasFont, unregisterFontOutlines, verticalMetricsFromTables, warmFonts };
1609
- //# sourceMappingURL=chunk-OYLAXZOV.js.map
1610
- //# sourceMappingURL=chunk-OYLAXZOV.js.map
1670
+ //# sourceMappingURL=chunk-ERSHQYJL.js.map
1671
+ //# sourceMappingURL=chunk-ERSHQYJL.js.map