From 7448b852f1fcfd961982a90c7cd8e136f297e246 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Mon, 8 Jun 2026 18:39:49 -0300 Subject: [PATCH 1/3] feat(fallbacks): expose advance measurement basis --- packages/fallbacks/README.md | 1 + packages/fallbacks/fallbacks.test.ts | 24 ++++++++++++++++++++++++ packages/fallbacks/records.json | 14 ++++++++++++++ packages/fallbacks/src/data.ts | 14 ++++++++++++++ packages/fallbacks/src/types.ts | 11 ++++++++++- 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/packages/fallbacks/README.md b/packages/fallbacks/README.md index 25d4502..bc6aff2 100644 --- a/packages/fallbacks/README.md +++ b/packages/fallbacks/README.md @@ -71,6 +71,7 @@ Some fallbacks are face-scoped. Use `getRenderableFallbackForFace`, or respect t - `verdict` - measured fidelity, such as `metric_safe`, `near_metric`, `cell_width_only`, or `visual_only`. - `lineBreakSafe` - true when advances preserve line breaks. - `glyphExceptions` - named glyphs that can reflow. +- `advance.basis` - sample/model used for mean and max deltas, such as `latin_core`, `latin_text`, or `monospace_cell`. - `generic` - CSS generic family for last-resort fallback. - `evidenceId` - stable id for the reviewed evidence row. diff --git a/packages/fallbacks/fallbacks.test.ts b/packages/fallbacks/fallbacks.test.ts index 0a6f5c9..b734724 100644 --- a/packages/fallbacks/fallbacks.test.ts +++ b/packages/fallbacks/fallbacks.test.ts @@ -324,6 +324,30 @@ describe("generic CSS family metadata", () => { }); }); +describe("advance measurement basis", () => { + test("every measured row states which sample/model produced its deltas", () => { + const BASES = new Set(["latin_core", "latin_text", "monospace_cell"]); + for (const row of SUBSTITUTION_EVIDENCE) { + if (!row.advance) continue; + expect( + BASES.has(row.advance.basis), + `${row.evidenceId} (${row.advance.basis})`, + ).toBe(true); + } + }); + + test("monospace cell-width rows are not labeled as proportional Latin measurements", () => { + expect( + SUBSTITUTION_EVIDENCE.find((row) => row.evidenceId === "consolas") + ?.advance?.basis, + ).toBe("monospace_cell"); + expect( + SUBSTITUTION_EVIDENCE.find((row) => row.evidenceId === "calibri")?.advance + ?.basis, + ).toBe("latin_core"); + }); +}); + describe("Cooper Black -> Caprasimo (Regular-only, metric_safe)", () => { const renderAll = { canRenderFamily: () => true }; const onlyCaprasimo = { canRenderFamily: (f: string) => f === "Caprasimo" }; diff --git a/packages/fallbacks/records.json b/packages/fallbacks/records.json index bf3204e..89c6d6e 100644 --- a/packages/fallbacks/records.json +++ b/packages/fallbacks/records.json @@ -24,6 +24,7 @@ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, @@ -56,6 +57,7 @@ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0.0002378, "maxDelta": 0.2310758 }, @@ -97,6 +99,7 @@ "measurementRefs": ["arial__liberation-sans#analytic_advance#2026-06-03"], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, @@ -126,6 +129,7 @@ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, @@ -155,6 +159,7 @@ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, @@ -191,6 +196,7 @@ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0.0000197, "maxDelta": 0.0183727 }, @@ -243,6 +249,7 @@ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0.5 }, @@ -309,6 +316,7 @@ ], "exportRule": "preserve_original_name", "advance": { + "basis": "monospace_cell", "meanDelta": 0.00035999999999999997, "maxDelta": 0.00035999999999999997 }, @@ -407,6 +415,7 @@ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0.1005, "maxDelta": 0.1419 }, @@ -503,6 +512,7 @@ "measurementRefs": ["lucida-console__cousine#analytic_advance#2026-06-03"], "exportRule": "preserve_original_name", "advance": { + "basis": "monospace_cell", "meanDelta": 0.004050000000000001, "maxDelta": 0.004050000000000001 }, @@ -576,6 +586,7 @@ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, @@ -603,6 +614,7 @@ "measurementRefs": ["calibri-light__carlito#analytic_advance#2026-06-05"], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0.0148, "maxDelta": 0.066 }, @@ -632,6 +644,7 @@ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0.4915590863952334 }, @@ -672,6 +685,7 @@ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, diff --git a/packages/fallbacks/src/data.ts b/packages/fallbacks/src/data.ts index c8e35e2..d6fd986 100644 --- a/packages/fallbacks/src/data.ts +++ b/packages/fallbacks/src/data.ts @@ -27,6 +27,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, @@ -59,6 +60,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0.0002378, "maxDelta": 0.2310758 }, @@ -102,6 +104,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, @@ -131,6 +134,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, @@ -160,6 +164,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, @@ -196,6 +201,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0.0000197, "maxDelta": 0.0183727 }, @@ -248,6 +254,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0.5 }, @@ -316,6 +323,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "monospace_cell", "meanDelta": 0.00035999999999999997, "maxDelta": 0.00035999999999999997 }, @@ -420,6 +428,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0.1005, "maxDelta": 0.1419 }, @@ -524,6 +533,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "monospace_cell", "meanDelta": 0.004050000000000001, "maxDelta": 0.004050000000000001 }, @@ -597,6 +607,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, @@ -626,6 +637,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0.0148, "maxDelta": 0.066 }, @@ -655,6 +667,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0.4915590863952334 }, @@ -695,6 +708,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { + "basis": "latin_core", "meanDelta": 0, "maxDelta": 0 }, diff --git a/packages/fallbacks/src/types.ts b/packages/fallbacks/src/types.ts index aa1150d..104fb0a 100644 --- a/packages/fallbacks/src/types.ts +++ b/packages/fallbacks/src/types.ts @@ -33,10 +33,19 @@ export type FaceSlot = "regular" | "bold" | "italic" | "boldItalic"; */ export type CssGeneric = "serif" | "sans-serif" | "monospace"; +/** Which advance sample/model produced the row's mean and max deltas. */ +export type AdvanceBasis = "latin_core" | "latin_text" | "monospace_cell"; + /** Advance-width divergence vs the licensed reference font, as fractions (0 = identical advances). */ export interface AdvanceDelta { + /** + * Measurement basis for the deltas. `latin_core` uses the reviewed Latin sample including + * punctuation/symbols, `latin_text` uses text-carrying Latin codepoints, and `monospace_cell` is a + * cell-width measurement for monospace rows. + */ + basis: AdvanceBasis; meanDelta: number; - /** the worst-case delta, not the mean, is what gates line-break fidelity. */ + /** the worst-case delta for this basis, not the mean, is what gates line-break fidelity. */ maxDelta: number; } From 65fd4266449685fdd48054422fdba00087728454 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Mon, 8 Jun 2026 18:49:05 -0300 Subject: [PATCH 2/3] fix(corpus): require full compare coverage --- tools/corpus/compare.test.ts | 59 +++++++++++++++++++++++++++++++++--- tools/corpus/src/report.ts | 6 ++++ tools/corpus/src/score.ts | 5 +-- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/tools/corpus/compare.test.ts b/tools/corpus/compare.test.ts index f6a6eb8..677a498 100644 --- a/tools/corpus/compare.test.ts +++ b/tools/corpus/compare.test.ts @@ -25,6 +25,7 @@ import { const UNITS_PER_EM = 1000; const ADVANCES = [500, 600, 300, 750]; // by glyph id +const SYNTHETIC_SAMPLE = [0x20, 0x41, 0x42] as const; function u16(value: number): number[] { return [(value >> 8) & 0xff, value & 0xff]; @@ -265,10 +266,26 @@ describe("scoreAdvances", () => { expect(score.maxDelta).toBe(0); expect(score.over1Percent).toBe(0); expect(score.over2_5Percent).toBe(0); - expect(score.tier).toBe("metric_safe"); + expect(score.tier).toBe("visual_only"); expect(score.worstGlyphs).toEqual([]); }); + test("does not give a metric tier to low-coverage candidates", () => { + const reference = new Map( + LATIN_TEXT_SAMPLE.map((codepoint) => [codepoint, 0.5] as const), + ); + const candidate = new Map([[0x20, 0.5]]); + const score = scoreAdvances(reference, candidate, { + reportSample: LATIN_SAMPLE, + tierSample: LATIN_TEXT_SAMPLE, + }); + expect(score.compared).toBe(1); + expect(score.total).toBe(LATIN_TEXT_SAMPLE.length); + expect(score.meanDelta).toBe(0); + expect(score.maxDelta).toBe(0); + expect(score.tier).toBe("visual_only"); + }); + test("computes mean and max deltas and worst glyphs", () => { const reference = new Map([ [0x41, 0.5], @@ -480,6 +497,33 @@ describe("renderReport", () => { expect(lines[3]).toContain("visual_only"); }); + test("ranks fuller coverage before lower-mean partial matches within a tier", () => { + const sample = [0x41, 0x42, 0x43]; + const reference = sampleMetrics(mockFont(0.5), sample); + const partial = scoreAdvances( + reference, + sampleMetrics(partialFont(0.5, [0x41]), sample), + sample, + ); + const full = scoreAdvances( + reference, + sampleMetrics(mockFont(0.7), sample), + sample, + ); + expect(partial.tier).toBe("visual_only"); + expect(full.tier).toBe("visual_only"); + + const report = renderReport([ + { sourceId: "partial-src", file: "partial.otf", score: partial }, + { sourceId: "full-src", file: "full.otf", score: full }, + ]); + const lines = report.split("\n"); + expect(lines[1]).toContain("full-src"); + expect(lines[1]).toContain("3/3"); + expect(lines[2]).toContain("partial-src"); + expect(lines[2]).toContain("1/3"); + }); + test("can limit the rendered table to the top rows", () => { const reference = sampleMetrics(mockFont(0.5), [0x41]); const close = scoreAdvances( @@ -570,11 +614,15 @@ describe("collectCandidates (GitHub tree sources)", () => { const candidates = collectCandidates(source, cacheDir); expect(candidates.map((c) => c.file)).toEqual(names); - const reference = sampleMetrics(parseFont(syntheticFont())); + const reference = sampleMetrics( + parseFont(syntheticFont()), + SYNTHETIC_SAMPLE, + ); for (const candidate of candidates) { const score = scoreAdvances( reference, - sampleMetrics(parseFont(candidate.bytes)), + sampleMetrics(parseFont(candidate.bytes), SYNTHETIC_SAMPLE), + SYNTHETIC_SAMPLE, ); expect(score.tier).toBe("metric_safe"); expect(score.meanDelta).toBe(0); @@ -649,8 +697,9 @@ describe("collectCandidates (archive sources)", () => { "Example-Regular.ttf", ]); const score = scoreAdvances( - sampleMetrics(parseFont(syntheticFont())), - sampleMetrics(parseFont(candidates[0].bytes)), + sampleMetrics(parseFont(syntheticFont()), SYNTHETIC_SAMPLE), + sampleMetrics(parseFont(candidates[0].bytes), SYNTHETIC_SAMPLE), + SYNTHETIC_SAMPLE, ); expect(score.tier).toBe("metric_safe"); } finally { diff --git a/tools/corpus/src/report.ts b/tools/corpus/src/report.ts index 6fa75c8..004bcf0 100644 --- a/tools/corpus/src/report.ts +++ b/tools/corpus/src/report.ts @@ -34,6 +34,12 @@ export function renderReport( const ranked = [...rows].sort((a, b) => { const tierDiff = TIER_RANK[a.score.tier] - TIER_RANK[b.score.tier]; if (tierDiff !== 0) return tierDiff; + const aCoverage = + a.score.total === 0 ? 0 : a.score.compared / a.score.total; + const bCoverage = + b.score.total === 0 ? 0 : b.score.compared / b.score.total; + const coverageDiff = bCoverage - aCoverage; + if (coverageDiff !== 0) return coverageDiff; const aMean = Number.isNaN(a.score.meanDelta) ? Infinity : a.score.meanDelta; diff --git a/tools/corpus/src/score.ts b/tools/corpus/src/score.ts index 48790f6..fa0c348 100644 --- a/tools/corpus/src/score.ts +++ b/tools/corpus/src/score.ts @@ -116,7 +116,8 @@ function normalizeScoreOptions( /** * Score one candidate against the reference. The tier can use a narrower text sample while the report * still surfaces full-sample outliers. Both inputs are normalized advance maps (codepoint -> - * advance/unitsPerEm); only codepoints present in both are compared. + * advance/unitsPerEm). A metric tier requires full tier-sample coverage: matching one shared glyph + * does not prove a font is a usable fallback. */ export function scoreAdvances( reference: ReadonlyMap, @@ -145,7 +146,7 @@ export function scoreAdvances( over1Percent: report.over1Percent, over2_5Percent: report.over2_5Percent, tier: - tierMetrics.compared === 0 + tierMetrics.compared !== tierMetrics.total ? "visual_only" : classifyTier( tierMetrics.meanDelta, From d7f005e76ab34265c204d092ff8b42f53f90529e Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Mon, 8 Jun 2026 19:17:19 -0300 Subject: [PATCH 3/3] fix(fallbacks): rename Latin basis --- packages/fallbacks/README.md | 2 +- packages/fallbacks/fallbacks.test.ts | 4 ++-- packages/fallbacks/records.json | 24 ++++++++++++------------ packages/fallbacks/src/data.ts | 24 ++++++++++++------------ packages/fallbacks/src/index.ts | 1 + packages/fallbacks/src/types.ts | 6 +++--- 6 files changed, 31 insertions(+), 30 deletions(-) diff --git a/packages/fallbacks/README.md b/packages/fallbacks/README.md index bc6aff2..7ecb06e 100644 --- a/packages/fallbacks/README.md +++ b/packages/fallbacks/README.md @@ -71,7 +71,7 @@ Some fallbacks are face-scoped. Use `getRenderableFallbackForFace`, or respect t - `verdict` - measured fidelity, such as `metric_safe`, `near_metric`, `cell_width_only`, or `visual_only`. - `lineBreakSafe` - true when advances preserve line breaks. - `glyphExceptions` - named glyphs that can reflow. -- `advance.basis` - sample/model used for mean and max deltas, such as `latin_core`, `latin_text`, or `monospace_cell`. +- `advance.basis` - sample/model used for mean and max deltas, such as `latin_full`, `latin_text`, or `monospace_cell`. - `generic` - CSS generic family for last-resort fallback. - `evidenceId` - stable id for the reviewed evidence row. diff --git a/packages/fallbacks/fallbacks.test.ts b/packages/fallbacks/fallbacks.test.ts index b734724..e3896e7 100644 --- a/packages/fallbacks/fallbacks.test.ts +++ b/packages/fallbacks/fallbacks.test.ts @@ -326,7 +326,7 @@ describe("generic CSS family metadata", () => { describe("advance measurement basis", () => { test("every measured row states which sample/model produced its deltas", () => { - const BASES = new Set(["latin_core", "latin_text", "monospace_cell"]); + const BASES = new Set(["latin_full", "latin_text", "monospace_cell"]); for (const row of SUBSTITUTION_EVIDENCE) { if (!row.advance) continue; expect( @@ -344,7 +344,7 @@ describe("advance measurement basis", () => { expect( SUBSTITUTION_EVIDENCE.find((row) => row.evidenceId === "calibri")?.advance ?.basis, - ).toBe("latin_core"); + ).toBe("latin_full"); }); }); diff --git a/packages/fallbacks/records.json b/packages/fallbacks/records.json index 89c6d6e..839d504 100644 --- a/packages/fallbacks/records.json +++ b/packages/fallbacks/records.json @@ -24,7 +24,7 @@ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, @@ -57,7 +57,7 @@ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0.0002378, "maxDelta": 0.2310758 }, @@ -99,7 +99,7 @@ "measurementRefs": ["arial__liberation-sans#analytic_advance#2026-06-03"], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, @@ -129,7 +129,7 @@ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, @@ -159,7 +159,7 @@ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, @@ -196,7 +196,7 @@ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0.0000197, "maxDelta": 0.0183727 }, @@ -249,7 +249,7 @@ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0.5 }, @@ -415,7 +415,7 @@ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0.1005, "maxDelta": 0.1419 }, @@ -586,7 +586,7 @@ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, @@ -614,7 +614,7 @@ "measurementRefs": ["calibri-light__carlito#analytic_advance#2026-06-05"], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0.0148, "maxDelta": 0.066 }, @@ -644,7 +644,7 @@ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0.4915590863952334 }, @@ -685,7 +685,7 @@ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, diff --git a/packages/fallbacks/src/data.ts b/packages/fallbacks/src/data.ts index d6fd986..91fc927 100644 --- a/packages/fallbacks/src/data.ts +++ b/packages/fallbacks/src/data.ts @@ -27,7 +27,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, @@ -60,7 +60,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0.0002378, "maxDelta": 0.2310758 }, @@ -104,7 +104,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, @@ -134,7 +134,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, @@ -164,7 +164,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, @@ -201,7 +201,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0.0000197, "maxDelta": 0.0183727 }, @@ -254,7 +254,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0.5 }, @@ -428,7 +428,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0.1005, "maxDelta": 0.1419 }, @@ -607,7 +607,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, @@ -637,7 +637,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0.0148, "maxDelta": 0.066 }, @@ -667,7 +667,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0.4915590863952334 }, @@ -708,7 +708,7 @@ export const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[] = [ ], "exportRule": "preserve_original_name", "advance": { - "basis": "latin_core", + "basis": "latin_full", "meanDelta": 0, "maxDelta": 0 }, diff --git a/packages/fallbacks/src/index.ts b/packages/fallbacks/src/index.ts index 7a2c85f..b72d0b0 100644 --- a/packages/fallbacks/src/index.ts +++ b/packages/fallbacks/src/index.ts @@ -15,6 +15,7 @@ export { type RenderableFallbackOptions, } from "./fallbacks.js"; export type { + AdvanceBasis, AdvanceDelta, CssGeneric, FaceCoverage, diff --git a/packages/fallbacks/src/types.ts b/packages/fallbacks/src/types.ts index 104fb0a..8233e1a 100644 --- a/packages/fallbacks/src/types.ts +++ b/packages/fallbacks/src/types.ts @@ -34,13 +34,13 @@ export type FaceSlot = "regular" | "bold" | "italic" | "boldItalic"; export type CssGeneric = "serif" | "sans-serif" | "monospace"; /** Which advance sample/model produced the row's mean and max deltas. */ -export type AdvanceBasis = "latin_core" | "latin_text" | "monospace_cell"; +export type AdvanceBasis = "latin_full" | "latin_text" | "monospace_cell"; /** Advance-width divergence vs the licensed reference font, as fractions (0 = identical advances). */ export interface AdvanceDelta { /** - * Measurement basis for the deltas. `latin_core` uses the reviewed Latin sample including - * punctuation/symbols, `latin_text` uses text-carrying Latin codepoints, and `monospace_cell` is a + * Measurement basis for the deltas. `latin_full` uses the reviewed Latin sample including + * punctuation and symbols, `latin_text` uses text-carrying Latin codepoints, and `monospace_cell` is a * cell-width measurement for monospace rows. */ basis: AdvanceBasis;