Fixup more broken geometries. (#2276)

This commit is contained in:
Belleve 2024-04-02 18:14:21 -10:00 committed by GitHub
parent 6923d74c0f
commit dd7d055302
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 136 additions and 101 deletions

View file

@ -12,7 +12,8 @@ glyph-block Letter-Latin-C : begin
glyph-block-import Mark-Shared-Metrics : markStroke
glyph-block-import Letter-Shared : CreateDependentComposite CreateTurnedLetter
glyph-block-import Letter-Shared-Shapes : SerifFrame CurlyTail DToothlessRise
glyph-block-import Letter-Shared-Shapes : SerifedArcStart SerifedArcEnd InwardSlabArcStart
glyph-block-import Letter-Shared-Shapes : SerifedArcStart SerifedArcEnd
glyph-block-import Letter-Shared-Shapes : InwardSlabArcStart InwardSlabArcEnd
glyph-block-import Letter-Shared-Shapes : ArcStartSerif ArcEndSerif
glyph-block-import Letter-Shared-Shapes : LetterBarOverlay PalatalHook RetroflexHook TopHook
glyph-block-import Letter-Shared-Shapes : ArcStartSerifWidth ArcStartSerifDepth
@ -28,10 +29,7 @@ glyph-block Letter-Latin-C : begin
widths.lhs sw
match st
[Just SLAB-CLASSICAL] : SerifedArcStart.RtlLhs (df.rightSB - offset) df.middle top sw [fallback hook Hook] origBar
[Just SLAB-INWARD] : list
g4 (df.rightSB - offset) (top - DToothlessRise)
g4 (df.middle - CorrectionOMidX * sw) (top - O - offset)
archv
[Just SLAB-INWARD] : InwardSlabArcStart.RtlLhs (df.rightSB - offset) df.middle top sw
[Just FLAT-CONNECTION] : list
flat (df.width - offset) (top - offset)
curl (df.middle - CorrectionOMidX * sw) (top - offset)
@ -45,10 +43,7 @@ glyph-block Letter-Latin-C : begin
match sb
[Just SLAB-CLASSICAL] : SerifedArcEnd.LtrLhs (df.rightSB - offset) df.middle bot sw [fallback hook Hook] origBar
[Just SLAB-INWARD] : list
arcvh
g4 (df.middle + CorrectionOMidX * sw) (bot + O + offset)
g4 (df.rightSB - offset) (bot + DToothlessRise)
[Just SLAB-INWARD] : InwardSlabArcEnd.LtrLhs (df.rightSB - offset) df.middle bot sw
[Just FLAT-CONNECTION] : list
arcvh
flat (df.middle + CorrectionOMidX * sw) (bot + O + offset)
@ -61,10 +56,7 @@ glyph-block Letter-Latin-C : begin
widths.rhs sw
match st
[Just SLAB-CLASSICAL] : SerifedArcStart.LtrRhs (df.leftSB + offset) df.middle top sw [fallback hook Hook] origBar
[Just SLAB-INWARD] : list
g4 (df.leftSB + offset) (top - DToothlessRise)
g4 (df.middle - CorrectionOMidX * sw) (top - O - offset)
archv
[Just SLAB-INWARD] : InwardSlabArcStart.LtrRhs (df.leftSB + offset) df.middle top sw
[Just FLAT-CONNECTION] : list
flat (0 + offset) (top - offset)
curl (df.middle - CorrectionOMidX * sw) (top - offset)
@ -78,10 +70,7 @@ glyph-block Letter-Latin-C : begin
match sb
[Just SLAB-CLASSICAL] : SerifedArcEnd.RtlRhs (df.leftSB + offset) df.middle bot sw [fallback hook Hook]
[Just SLAB-INWARD] : list
arcvh
g4 (df.middle + CorrectionOMidX * sw) (bot + O + offset)
g4 (df.leftSB + offset) (bot + DToothlessRise)
[Just SLAB-INWARD] : InwardSlabArcEnd.RtlRhs (df.leftSB + offset) df.middle bot sw
[Just FLAT-CONNECTION] : list
arcvh
flat (df.middle + CorrectionOMidX * sw) (bot + O + offset)

View file

@ -13,7 +13,7 @@ glyph-block Letter-Latin-Lower-A : begin
glyph-block-import Letter-Shared : CreateTurnedLetter
glyph-block-import Letter-Shared-Shapes : SerifFrame OBarLeft OBarRight ArcStartSerif
glyph-block-import Letter-Shared-Shapes : RightwardTailedBar InvRightwardTailedBar
glyph-block-import Letter-Shared-Shapes : DToothlessRise DMBlend RetroflexHook
glyph-block-import Letter-Shared-Shapes : DToothlessRise DMBlend RetroflexHook InwardSlabArcStart
glyph-block-export DoubleStorey DoubleStoreyConfig
define DoubleStorey : namespace
@ -33,9 +33,7 @@ glyph-block Letter-Latin-Lower-A : begin
1 : list
g4 df.leftSB (XH - AHook)
hookstart (XH - O) (sw -- stroke)
2 : list
g4 df.leftSB (XH - DToothlessRise)
g4 (df.middle - CorrectionOMidX * stroke) (XH - O)
2 : InwardSlabArcStart.LtrRhs df.leftSB df.middle XH stroke
flat df.rightSB (XH - [ADoubleStoreySmoothB df])
[if isMask corner curl] df.rightSB y0 [heading Downward]
if [not isMask] {} {[corner df.leftSB y0]}

View file

@ -153,21 +153,36 @@ glyph-block Letter-Latin-Lower-M : begin
define [EarlessCornerDoubleArchSmallMShape df top lbot mbot rbot _mid] : glyph-proc
local mid : fallback _mid df.middle
include : dispiro
widths.rhs df.mvs
g4 df.leftSB (top - DToothlessRise)
g4.right.mid [mix df.leftSB (mid + [HSwToV : 0.5 * df.mvs]) 0.5] (top - O) [heading Rightward]
g4 (mid + [HSwToV : 0.5 * df.mvs]) (top - DToothlessRise)
include : dispiro
widths.rhs df.mvs
g4 (mid - [HSwToV : 0.5 * df.mvs]) (top - DToothlessRise)
g4.right.mid [mix df.rightSB (mid - [HSwToV : 0.5 * df.mvs]) 0.5] (top - O) [heading Rightward]
archv
flat df.rightSB (top - [SmallMSmooth df]) [heading Downward]
curl df.rightSB rbot [heading Downward]
define [leftKnots sink offset] : begin
local xMidBarRightSide : mid + [HSwToV : 0.5 * df.mvs]
local xArchMid : [mix df.leftSB xMidBarRightSide 0.5] - CorrectionOMidX * df.mvs
return : sink
widths.rhs df.mvs
[if (sink == dispiro) g2 corner] (df.leftSB - offset) (top - DToothlessRise)
g2.right.mid (xArchMid - offset) (top - O)
archv
flat (xMidBarRightSide - offset) (top - [SmallMSmooth df]) [heading Downward]
[if (sink == dispiro) curl corner] (xMidBarRightSide - offset) mbot [heading Downward]
if (sink == spiro-outline) { [corner (df.leftSB - offset) 0 ] } { }
define [rightKnots sink] : begin
local xMidBarLeftSide : mid - [HSwToV : 0.5 * df.mvs]
local xArchMid : [mix df.rightSB xMidBarLeftSide 0.5] - CorrectionOMidX * df.mvs
return : sink
widths.rhs df.mvs
g2 [mix xArchMid xMidBarLeftSide 2] (top - 2 * DToothlessRise)
g2 xMidBarLeftSide (top - DToothlessRise)
g2.right.mid xArchMid (top - O)
archv
flat df.rightSB (top - [SmallMSmooth df]) [heading Downward]
curl df.rightSB rbot [heading Downward]
include : leftKnots dispiro 0
include : difference [rightKnots dispiro] [leftKnots spiro-outline 0.1]
include : tagged 'barL' : VBar.l df.leftSB lbot (top - DToothlessRise) df.mvs
include : tagged 'barM' : VBar.m mid mbot (top - DToothlessRise) df.mvs
# include : tagged 'barM' : VBar.m mid mbot (top - DToothlessRise) df.mvs
define [EarlessRoundedDoubleArchSmallMShape df top lbot mbot rbot _mid] : glyph-proc
local mid : fallback _mid df.middle
@ -198,7 +213,7 @@ glyph-block Letter-Latin-Lower-M : begin
include : dispiro
widths.rhs df.mvs
g4 df.leftSB (top - DToothlessRise)
g4 (mid - CorrectionOMidS) (top - O)
g4 (mid - CorrectionOMidX * df.mvs) (top - O)
archv
flat df.rightSB [Math.max (top - [SmallMSmooth df]) (rbot + 0.1)]
curl df.rightSB rbot [heading Downward]

View file

@ -13,6 +13,7 @@ glyph-block Letter-Latin-S : begin
glyph-block-import Letter-Shared-Shapes : DToothlessRise FlatHookDepth
glyph-block-import Letter-Shared-Shapes : ArcStartSerifWidth ArcStartSerifDepth
glyph-block-import Letter-Shared-Shapes : SerifedArcStart SerifedArcEnd
glyph-block-import Letter-Shared-Shapes : InwardSlabArcStart InwardSlabArcEnd
glyph-block-import Letter-Shared-Shapes : ArcStartSerif ArcEndSerif
glyph-block-import Letter-Shared-Shapes : PalatalHook RetroflexHook CyrDescender CurlyTail
@ -48,10 +49,7 @@ glyph-block Letter-Latin-S : begin
return : dispiro
match st
[Just SLAB-CLASSICAL] : SerifedArcStart.RtlLhs df.rightSB df.middle top stroke Hook
[Just SLAB-INWARD] : list
g4 df.rightSB (top - DToothlessRise) [widths.lhs stroke]
g4 (df.middle - CorrectionOMidX * stroke) (top - O)
archv
[Just SLAB-INWARD] : InwardSlabArcStart.RtlLhs df.rightSB df.middle top stroke Hook
__ : list
g4 df.rightSB (top - Hook) [widths.lhs stroke]
hookstart (top - O) (sw -- stroke) (swItalicAdj -- Stroke)
@ -62,10 +60,7 @@ glyph-block Letter-Latin-S : begin
match sb
[Just SLAB-CLASSICAL] : SerifedArcEnd.RtlRhs df.leftSB df.middle bot stroke Hook
[Just SLAB-INWARD] : list
arcvh
g4 (df.middle + CorrectionOMidX * stroke) (bot + O)
g4 df.leftSB (bot + DToothlessRise)
[Just SLAB-INWARD] : InwardSlabArcEnd.RtlRhs df.leftSB df.middle bot stroke Hook
__ : list
hookend (bot + O) (sw -- stroke) (swItalicAdj -- Stroke)
g4 (df.leftSB + SOBot) (bot + Hook)
@ -75,10 +70,7 @@ glyph-block Letter-Latin-S : begin
return : dispiro
match st
[Just SLAB-CLASSICAL] : SerifedArcStart.LtrRhs df.leftSB df.middle CAP stroke Hook
[Just SLAB-INWARD] : list
g4 df.leftSB (CAP - DToothlessRise) [widths.rhs stroke]
g4 (df.middle - CorrectionOMidX * stroke) (CAP - O)
archv
[Just SLAB-INWARD] : InwardSlabArcStart.LtrRhs df.leftSB df.middle CAP stroke Hook
__ : list
g4 df.leftSB (CAP - Hook) [widths.rhs stroke]
hookstart (CAP - O) (sw -- stroke) (swItalicAdj -- Stroke)
@ -87,10 +79,7 @@ glyph-block Letter-Latin-S : begin
g4 (df.leftSB + SOBot) archDepth [widths.lhs stroke]
match sb
[Just SLAB-CLASSICAL] : SerifedArcEnd.LtrLhs df.rightSB df.middle 0 stroke Hook
[Just SLAB-INWARD] : list
arcvh
g4 (df.middle + CorrectionOMidX * stroke) O
g4 df.rightSB DToothlessRise
[Just SLAB-INWARD] : InwardSlabArcEnd.LtrLhs df.rightSB df.middle 0 stroke Hook
__ : list
hookend O (sw -- stroke) (swItalicAdj -- Stroke)
g4 (df.rightSB + OX - SOBot) Hook
@ -102,10 +91,7 @@ glyph-block Letter-Latin-S : begin
return : dispiro
match st
[Just SLAB-CLASSICAL] : SerifedArcStart.RtlLhs df.rightSB df.middle XH stroke SHook
[Just SLAB-INWARD] : list
g4 df.rightSB (XH - DToothlessRise) [widths.lhs stroke]
g4 (df.middle - CorrectionOMidX * stroke) (XH - O)
archv
[Just SLAB-INWARD] : InwardSlabArcStart.RtlLhs df.rightSB df.middle XH stroke SHook
__ : list
g4 (df.rightSB + OX) (XH - SHook) [widths.lhs stroke]
hookstart (XH - O) (sw -- stroke) (swItalicAdj -- Stroke)
@ -119,10 +105,7 @@ glyph-block Letter-Latin-S : begin
arcvh
SCurlyTail df stroke
[Just SLAB-CLASSICAL] : SerifedArcEnd.RtlRhs df.leftSB df.middle 0 stroke SHook
[Just SLAB-INWARD] : list
arcvh
g4 (df.middle + CorrectionOMidX * stroke) O
g4 df.leftSB DToothlessRise
[Just SLAB-INWARD] : InwardSlabArcEnd.RtlRhs df.leftSB df.middle 0 stroke SHook
__ : list
hookend O (sw -- stroke) (swItalicAdj -- Stroke)
g4 (df.leftSB - OX + SOBot) SHook
@ -153,10 +136,7 @@ glyph-block Letter-Latin-S : begin
return : dispiro
match st
[Just SLAB-CLASSICAL] : SerifedArcStart.RtlLhs df.rightSB df.middle top stroke Hook
[Just SLAB-INWARD] : list
g4 df.rightSB (top - DToothlessRise) [widths.lhs stroke]
g4 (df.middle - CorrectionOMidX * stroke) (top - O)
archv
[Just SLAB-INWARD] : InwardSlabArcStart.RtlLhs df.rightSB df.middle top stroke Hook
__ : list
g4 df.rightSB (top - Hook) [widths.lhs stroke]
hookstart (top - O) (sw -- stroke) (swItalicAdj -- Stroke)
@ -172,10 +152,7 @@ glyph-block Letter-Latin-S : begin
return : dispiro
match st
[Just SLAB-CLASSICAL] : SerifedArcStart.LtrRhs df.leftSB df.middle XH stroke SHook
[Just SLAB-INWARD] : list
g4 df.leftSB (XH - DToothlessRise) [widths.rhs stroke]
g4 (df.middle - CorrectionOMidX * stroke) (XH - O)
archv
[Just SLAB-INWARD] : InwardSlabArcStart.LtrRhs df.leftSB df.middle XH stroke SHook
__ : list
g4 (df.leftSB - OX) (XH - SHook) [widths.rhs stroke]
hookstart (XH - O) (sw -- stroke) (swItalicAdj -- Stroke)
@ -184,10 +161,7 @@ glyph-block Letter-Latin-S : begin
g4 (df.leftSB - OX + SOBot) (archDepth) [widths.lhs stroke]
match sb
[Just SLAB-CLASSICAL] : SerifedArcEnd.LtrLhs df.rightSB df.middle 0 stroke SHook
[Just SLAB-INWARD] : list
arcvh
g4 (df.middle + CorrectionOMidX * stroke) O
g4 df.rightSB DToothlessRise
[Just SLAB-INWARD] : InwardSlabArcEnd.LtrLhs df.rightSB df.middle 0 stroke SHook
__ : list
hookend O (sw -- stroke) (swItalicAdj -- Stroke)
g4 (df.rightSB + OX - SOBot) SHook

View file

@ -562,30 +562,30 @@ glyph-block Letter-Shared-Shapes : begin
glyph-block-export InwardSlabArcStart
define InwardSlabArcStart : namespace
export : define [RtlLhs sx cx cy sw hook] : begin
export : define [RtlLhs sx cx cy sw _hook] : begin
return : list
g4 sx (cy - DToothlessRise) [widths.lhs sw]
g4 (cx - CorrectionOMidX * sw) (cy - O)
g2 sx (cy - DToothlessRise) [widths.lhs sw]
g2.left.mid (cx - CorrectionOMidX * sw) (cy - O)
archv
export : define [LtrRhs sx cx cy sw hook] : begin
export : define [LtrRhs sx cx cy sw _hook] : begin
return : list
g4 sx (cy - DToothlessRise) [widths.rhs sw]
g4 (cx - CorrectionOMidX * sw) (cy - O)
g2 sx (cy - DToothlessRise) [widths.rhs sw]
g2.right.mid (cx - CorrectionOMidX * sw) (cy - O)
archv
glyph-block-export InwardSlabArcEnd
define InwardSlabArcEnd : namespace
export : define [RtlRhs sx cx cy sw hook] : begin
export : define [RtlRhs sx cx cy sw _hook] : begin
return : list
arcvh
g4 (cx + CorrectionOMidX * sw) (cy + O)
g4 sx (cy + DToothlessRise) [widths.rhs sw]
export : define [LtrLhs sx cx cy sw hook] : begin
g2.left.mid (cx + CorrectionOMidX * sw) (cy + O)
g2 sx (cy + DToothlessRise) [widths.rhs sw]
export : define [LtrLhs sx cx cy sw _hook] : begin
return : list
arcvh
g4 (cx + CorrectionOMidX * sw) (cy + O)
g4 sx (cy + DToothlessRise) [widths.lhs sw]
g2.right.mid (cx + CorrectionOMidX * sw) (cy + O)
g2 sx (cy + DToothlessRise) [widths.lhs sw]
glyph-block-export ArcStartSerifWidth
define [ArcStartSerifWidth stroke] : clamp (stroke * 0.875) stroke VJutStroke

View file

@ -38,6 +38,6 @@ function flattenSimpleGlyph(cache, skew, g) {
g.includeContours(cs);
} catch (e) {
console.error("Detected broken geometry when processing", g._m_identifier);
throw e;
g.clearGeometry();
}
}

View file

@ -1,10 +1,11 @@
import fs from "fs";
import { setTimeout } from "node:timers/promises";
import zlib from "zlib";
import * as CurveUtil from "@iosevka/geometry/curve-util";
import { encode, decode } from "@msgpack/msgpack";
const Edition = 40;
const Edition = 41;
const MAX_AGE = 16;
class GfEntry {
constructor(age, value) {
@ -78,12 +79,22 @@ class Cache {
export async function load(path, version, freshAgeKey) {
let cache = new Cache(freshAgeKey);
if (path && fs.existsSync(path)) {
try {
const buf = zlib.gunzipSync(await fs.promises.readFile(path));
cache.loadRep(version, decode(buf));
} catch (e) {
console.error("Error loading cache. Treat as empty.");
console.error(e);
let loadAttempt = 0;
while (loadAttempt < 3) {
try {
const buf = zlib.gunzipSync(await fs.promises.readFile(path));
cache.loadRep(version, decode(buf));
loadAttempt += 1;
break;
} catch (e) {
if (loadAttempt < 2) {
await setTimeout(500);
} else {
console.error("Error loading cache. Treat as empty.");
console.error(e);
}
loadAttempt += 1;
}
}
}
return cache;

View file

@ -136,17 +136,28 @@ export class BezToContoursSink {
this.lastContour = [];
}
moveTo(x, y) {
if (!isFinite(x) || !isFinite(y)) throw new Error("Invalid coordinates detected in moveTo");
this.endShape();
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y));
}
lineTo(x, y) {
if (!isFinite(x) || !isFinite(y)) throw new Error("Invalid coordinates detected in lineTo");
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y));
}
curveTo(xc, yc, x, y) {
if (!isFinite(xc) || !isFinite(yc) || !isFinite(x) || !isFinite(y))
throw new Error("Invalid coordinates detected in curveTo");
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Quadratic, xc, yc));
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y));
}
cubicTo(x1, y1, x2, y2, x, y) {
if (!isFinite(x1) || !isFinite(y1))
throw new Error("Invalid coordinates detected in cubicTo");
if (!isFinite(x2) || !isFinite(y2))
throw new Error("Invalid coordinates detected in cubicTo");
if (!isFinite(x) || !isFinite(y))
throw new Error("Invalid coordinates detected in cubicTo");
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.CubicStart, x1, y1));
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.CubicEnd, x2, y2));
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y));

View file

@ -50,9 +50,11 @@ class SpiroSimplifier {
flushArcs() {
if (!this.m_ongoingArcs.length) return;
if (this.m_ongoingArcs.length === 1) {
this.combinedArcs.push(this.m_ongoingArcs[0]);
const arc = this.m_ongoingArcs[0];
if (arc.arcLength > 1e-6) this.combinedArcs.push(arc);
} else {
this.combinedArcs.push(new SpiroSequenceArc(this.m_ongoingArcs));
const combined = new SpiroSequenceArc(this.m_ongoingArcs);
if (combined.totalLength > 1e-6) this.combinedArcs.push(combined);
}
this.m_ongoingArcs = [];
}
@ -60,6 +62,16 @@ class SpiroSimplifier {
class SpiroSequenceArc {
constructor(segments) {
// Filter out zero-length segments
let rear = 0;
for (let j = 0; j < segments.length; j++) {
if (segments[j].arcLength > 1e-6) {
segments[rear++] = segments[j];
}
}
segments.length = rear;
// Compute total length and stops
let totalLength = 0;
let stops = [];
for (let j = 0; j < segments.length; j++) {
@ -69,6 +81,7 @@ class SpiroSequenceArc {
for (let j = 0; j < segments.length; j++) {
stops[j] = stops[j] / totalLength;
}
this.totalLength = totalLength;
this.m_segments = segments;
this.m_stops = stops;
}

View file

@ -53,7 +53,7 @@ build.setJournal(`${BUILD}/.verda-build-journal`);
build.setSelfTracking();
///////////////////////////////////////////////////////////
////// Oracles //////
////// Environment //////
///////////////////////////////////////////////////////////
const Version = computed(`env::version`, async target => {
@ -71,16 +71,40 @@ const CheckTtfAutoHintExists = oracle(`oracle:check-ttfautohint-exists`, async t
});
const Dependencies = computed("env::dependencies", async target => {
const [pjf] = await target.need(sfu`package.json`);
const pj = JSON.parse(await FS.promises.readFile(pjf.full, "utf-8"));
let subGoals = [];
for (const pkgName in pj.dependencies) {
subGoals.push(InstalledVersion(pkgName, pj.dependencies[pkgName]));
const [packageJsons] = await target.need(AllPackageJsons);
const subGoals = [];
for (const pjf of packageJsons) {
subGoals.push(DependenciesFor(pjf));
}
const [actual] = await target.need(subGoals);
return actual;
return await target.need(subGoals);
});
const AllPackageJsons = computed("env::all-package-jsons", async target => {
const [ppj, tpj] = await target.need(PackagesPackagesJsons, ToolPackagesJsons);
return [`package.json`, ...ppj, ...tpj];
});
const PackagesPackagesJsons = computed("env::packages-packages-jsons", target =>
FileList({ under: "packages", pattern: "*/package.json" })(target),
);
const ToolPackagesJsons = computed("env::tool-packages-jsons", target =>
FileList({ under: "tools", pattern: "*/package.json" })(target),
);
const DependenciesFor = computed.make(
pakcageJsonPath => `env::dependencies-for::${pakcageJsonPath}`,
async (target, pakcageJsonPath) => {
const [pjf] = await target.need(sfu(pakcageJsonPath));
const pj = JSON.parse(await FS.promises.readFile(pjf.full, "utf-8"));
let subGoals = [];
for (const pkgName in pj.dependencies) {
if (/^@iosevka/.test(pkgName)) continue;
subGoals.push(InstalledVersion(pkgName, pj.dependencies[pkgName]));
}
const [actual] = await target.need(subGoals);
return actual;
},
);
const InstalledVersion = computed.make(
(pkg, required) => `env::installed-version::${pkg}::${required}`,
async (target, pkg, required) => {