* Fix rounding errors caused by glyph cross references (#2545) * Do it in simpler way
This commit is contained in:
parent
1b7ad7cab9
commit
35de3aa463
6 changed files with 50 additions and 51 deletions
|
@ -9,6 +9,7 @@
|
|||
* Optimize glyph for Cyrillic Lower Dzze (`U+A689`) under italics.
|
||||
* Optimize glyphs for Volapük Ae/Oe/Ue (`U+A79A`..`U+A79F`).
|
||||
* Optimize glyph for Latin Lower Dezh Digraph with Palatal Hook (`U+1DF12`).
|
||||
* Fix misalignments of square brackets under certain size caused by rounding errors (#2545).
|
||||
* Add characters:
|
||||
- WAVY LINE (`U+2307`).
|
||||
- SYMMETRY (`U+232F`).
|
||||
|
|
|
@ -9,17 +9,18 @@ export : define [calculateMetrics para] : begin
|
|||
define HalfUPM : UPM / 2
|
||||
|
||||
# Key metrics
|
||||
define Width : Math.round para.width
|
||||
define SB para.sb
|
||||
define CAP para.cap
|
||||
define XH para.xHeight
|
||||
define Ascender para.ascender
|
||||
define Descender : fallback para.descender (XH - Ascender)
|
||||
define Contrast : fallback para.contrast 1
|
||||
define Width : Math.round para.width
|
||||
define SB : Math.round para.sb
|
||||
define CAP : Math.round para.cap
|
||||
define XH : Math.round para.xHeight
|
||||
define Ascender : Math.round para.ascender
|
||||
define Descender : Math.round : fallback para.descender (XH - Ascender)
|
||||
|
||||
# Key metrics for symbols
|
||||
define SymbolMid para.symbolMid
|
||||
define ParenTop : SymbolMid + para.parenSize / 2
|
||||
define ParenBot : SymbolMid - para.parenSize / 2
|
||||
define SymbolMid : Math.round para.symbolMid
|
||||
define halfParenSize : Math.ceil (para.parenSize / 2)
|
||||
define ParenTop : SymbolMid + halfParenSize
|
||||
define ParenBot : SymbolMid - halfParenSize
|
||||
|
||||
define OperTop : SymbolMid + para.operSize * (Width - SB * 2)
|
||||
define OperBot : SymbolMid - para.operSize * (Width - SB * 2)
|
||||
|
@ -32,6 +33,7 @@ export : define [calculateMetrics para] : begin
|
|||
define BgOpTop : SymbolMid + para.bgopSize * (Width - SB * 2)
|
||||
define BgOpBot : SymbolMid - para.bgopSize * (Width - SB * 2)
|
||||
|
||||
define Contrast : fallback para.contrast 1
|
||||
|
||||
# Transform constructors
|
||||
define [Italify angle shift] : begin
|
||||
|
|
|
@ -162,11 +162,12 @@ glyph-block Symbol-Punctuation-Brackets : begin
|
|||
|
||||
export : define [Mask] : Rect MosaicTop MosaicBottom (-Width) (2 * Width)
|
||||
|
||||
export : define [Shape top bottom barLeft ext] : glyph-proc
|
||||
export : define [Shape top bottom barLeft ext] : begin
|
||||
local hDim : HDim barLeft ext
|
||||
include : HBar.b hDim.l hDim.r bottom
|
||||
include : HBar.t hDim.l hDim.r top
|
||||
include : VBar.l hDim.l bottom top
|
||||
return : union
|
||||
HBar.b hDim.l hDim.r bottom
|
||||
HBar.t hDim.l hDim.r top
|
||||
VBar.l hDim.l bottom top
|
||||
|
||||
do "Bracket Glyphs"
|
||||
create-glyph 'bracketLeft' '[' : Bracket.Shape ParenTop ParenBot
|
||||
|
|
|
@ -12,9 +12,16 @@ export function finalizeGlyphs(cache, para, glyphStore) {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function regulateGlyphStore(cache, para, skew, glyphStore) {
|
||||
const simplifiedResultMap = new Map();
|
||||
for (const g of glyphStore.glyphs()) {
|
||||
if (!(g.geometry.measureComplexity() & Geom.CPLX_NON_EMPTY)) continue;
|
||||
if (!g.geometry.toReferences()) flattenSimpleGlyph(cache, para, skew, g);
|
||||
if (!g.geometry.toReferences()) {
|
||||
simplifiedResultMap.set(g, flattenSimpleGlyph(cache, para, skew, g));
|
||||
}
|
||||
}
|
||||
for (const [g, sr] of simplifiedResultMap) {
|
||||
g.gizmo = Transform.Id();
|
||||
g.geometry = new Geom.ContourSetGeometry(sr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,14 +29,13 @@ function flattenSimpleGlyph(cache, para, skew, g) {
|
|||
try {
|
||||
if (!g.gizmo) throw new TypeError("No gizmo");
|
||||
const gSimplified = Geom.SimplifyGeometry.wrapWithGizmo(g.geometry, g.gizmo);
|
||||
const cs = gSimplified.toContours({ cache });
|
||||
g.clearGeometry();
|
||||
g.includeContours(cs);
|
||||
return gSimplified.toContours({ cache });
|
||||
} catch (e) {
|
||||
console.error("Detected broken geometry when processing", g._m_identifier);
|
||||
console.error(e);
|
||||
console.error(
|
||||
`${para.naming.family} ${para.naming.weight} ${para.naming.width} ${para.naming.slope}`,
|
||||
);
|
||||
g.clearGeometry();
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import zlib from "zlib";
|
|||
import * as CurveUtil from "@iosevka/geometry/curve-util";
|
||||
import { encode, decode } from "@msgpack/msgpack";
|
||||
|
||||
const Edition = 46;
|
||||
const Edition = 50;
|
||||
const MAX_AGE = 16;
|
||||
class GfEntry {
|
||||
constructor(age, value) {
|
||||
|
|
|
@ -102,16 +102,7 @@ export class CachedGeometry extends GeometryBase {
|
|||
}
|
||||
}
|
||||
|
||||
export class SpiroGeometry extends CachedGeometry {
|
||||
constructor(gizmo, closed, knots) {
|
||||
super();
|
||||
this.m_knots = knots;
|
||||
this.m_closed = closed;
|
||||
this.m_gizmo = gizmo;
|
||||
}
|
||||
toContoursImpl() {
|
||||
return spiroToOutlineWithSimplification(this.m_knots, this.m_closed, this.m_gizmo);
|
||||
}
|
||||
class SimpleGeometry extends CachedGeometry {
|
||||
toReferences() {
|
||||
return null;
|
||||
}
|
||||
|
@ -121,6 +112,19 @@ export class SpiroGeometry extends CachedGeometry {
|
|||
filterTag(fn) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export class SpiroGeometry extends SimpleGeometry {
|
||||
constructor(gizmo, closed, knots) {
|
||||
super();
|
||||
this.m_knots = knots;
|
||||
this.m_closed = closed;
|
||||
this.m_gizmo = gizmo;
|
||||
}
|
||||
toContoursImpl() {
|
||||
return spiroToOutlineWithSimplification(this.m_knots, this.m_closed, this.m_gizmo);
|
||||
}
|
||||
|
||||
measureComplexity() {
|
||||
let cplx = CPLX_NON_EMPTY | CPLX_NON_SIMPLE;
|
||||
for (const z of this.m_knots) {
|
||||
|
@ -140,7 +144,7 @@ export class SpiroGeometry extends CachedGeometry {
|
|||
}
|
||||
}
|
||||
|
||||
export class SpiroPenGeometry extends CachedGeometry {
|
||||
export class SpiroPenGeometry extends SimpleGeometry {
|
||||
constructor(gizmo, penProfile, closed, knots) {
|
||||
super();
|
||||
this.m_gizmo = gizmo;
|
||||
|
@ -177,16 +181,6 @@ export class SpiroPenGeometry extends CachedGeometry {
|
|||
return ctx.contours;
|
||||
}
|
||||
|
||||
toReferences() {
|
||||
return null;
|
||||
}
|
||||
getDependencies() {
|
||||
return null;
|
||||
}
|
||||
filterTag(fn) {
|
||||
return this;
|
||||
}
|
||||
|
||||
measureComplexity() {
|
||||
let cplx = CPLX_NON_EMPTY | CPLX_NON_SIMPLE;
|
||||
for (const z of this.m_penProfile) {
|
||||
|
@ -217,7 +211,7 @@ export class SpiroPenGeometry extends CachedGeometry {
|
|||
}
|
||||
}
|
||||
|
||||
export class DiSpiroGeometry extends CachedGeometry {
|
||||
export class DiSpiroGeometry extends SimpleGeometry {
|
||||
constructor(gizmo, contrast, closed, biKnots) {
|
||||
super();
|
||||
this.m_biKnots = biKnots; // untransformed
|
||||
|
@ -261,15 +255,7 @@ export class DiSpiroGeometry extends CachedGeometry {
|
|||
}
|
||||
return expander.expand();
|
||||
}
|
||||
toReferences() {
|
||||
return null;
|
||||
}
|
||||
getDependencies() {
|
||||
return null;
|
||||
}
|
||||
filterTag(fn) {
|
||||
return this;
|
||||
}
|
||||
|
||||
measureComplexity() {
|
||||
let cplx = CPLX_NON_EMPTY | CPLX_NON_SIMPLE;
|
||||
for (const z of this.m_biKnots) {
|
||||
|
@ -298,12 +284,14 @@ export class ReferenceGeometry extends GeometryBase {
|
|||
this.m_x = x || 0;
|
||||
this.m_y = y || 0;
|
||||
}
|
||||
|
||||
unwrap() {
|
||||
return TransformedGeometry.create(
|
||||
Transform.Translate(this.m_x, this.m_y),
|
||||
this.m_glyph.geometry,
|
||||
);
|
||||
}
|
||||
|
||||
toContours(ctx) {
|
||||
return this.unwrap().toContours(ctx);
|
||||
}
|
||||
|
@ -557,6 +545,7 @@ export class BooleanGeometry extends CachedGeometry {
|
|||
if (i > 0) sink.push({ type: "operator", operator: this.m_operator });
|
||||
}
|
||||
}
|
||||
|
||||
toReferences() {
|
||||
return null;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue