Fix overshoot of oval-shaped 0, and open 6/9 (#1455).

This commit is contained in:
be5invis 2022-12-06 18:18:23 -08:00
parent 9764a3b199
commit e7d2d8c6cb
6 changed files with 42 additions and 23 deletions

View file

@ -1 +1,2 @@
* Fix metrics of ASCII single quotes under Aile (#1454).
* Fix overshoot of oval-shaped `0`, and open `6`/`9` (#1455).

View file

@ -6,6 +6,7 @@ import { Point } from "../../support/geometry/point.mjs";
import { Transform } from "../../support/geometry/transform.mjs";
///////////////////////////////////////////////////////////////////////////////////////////////////
function regulateGlyphStore(cache, skew, glyphStore) {
const compositeMemo = new Map();
for (const g of glyphStore.glyphs()) {
@ -18,19 +19,20 @@ function regulateGlyphStore(cache, skew, glyphStore) {
if (!compositeMemo.get(g)) flattenSimpleGlyph(cache, skew, g);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
function memoSet(memo, g, v) {
memo.set(g, v);
return v;
}
function regulateCompositeGlyph(glyphStore, memo, g) {
if (memo.has(g)) return memo.get(g);
let refs = g.geometry.asReferences();
if (!refs) return memoSet(memo, g, false);
for (const sr of refs) {
const gn = glyphStore.queryNameOf(sr.glyph);
if (!gn) return memoSet(memo, g, false);
}
// De-doppelganger
while (refs.length === 1 && regulateCompositeGlyph(glyphStore, memo, refs[0].glyph)) {
const sr = refs[0];
@ -41,8 +43,10 @@ function regulateCompositeGlyph(glyphStore, memo, g) {
}
refs = g.geometry.asReferences();
}
return memoSet(memo, g, true);
}
function flattenSimpleGlyph(cache, skew, g) {
const ck = Geom.hashGeometry(g.geometry);
const cached = cache.getGF(ck);
@ -51,19 +55,32 @@ function flattenSimpleGlyph(cache, skew, g) {
g.includeContours(CurveUtil.repToShape(cached), 0, 0);
cache.refreshGF(ck);
} else {
const tfBack = g.gizmo ? g.gizmo.inverse() : new Transform(1, -skew, 0, 1, 0, 0);
const tfForward = g.gizmo ? g.gizmo : new Transform(1, +skew, 0, 1, 0, 0);
const g1 = new Geom.TransformedGeometry(
new SimplifyGeometry(new Geom.TransformedGeometry(g.geometry, tfBack)),
tfForward
);
const cs = g1.asContours();
let gSimplified;
if (skew) {
const tfBack = g.gizmo ? g.gizmo.inverse() : new Transform(1, -skew, 0, 1, 0, 0);
const tfForward = g.gizmo ? g.gizmo : new Transform(1, +skew, 0, 1, 0, 0);
gSimplified = new Geom.TransformedGeometry(
new SimplifyGeometry(new Geom.TransformedGeometry(g.geometry, tfBack)),
tfForward
);
} else {
gSimplified = new SimplifyGeometry(g.geometry);
}
const cs = gSimplified.asContours();
g.clearGeometry();
g.includeContours(cs, 0, 0);
if (ck) cache.saveGF(ck, CurveUtil.shapeToRep(cs));
}
}
function memoSet(memo, g, v) {
memo.set(g, v);
return v;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class SimplifyGeometry extends Geom.GeometryBase {
constructor(g) {
super();

View file

@ -151,14 +151,14 @@ glyph-block CommonShapes : begin
define [RoundStrokeTerminalAt x y r] : CircleRing (y + r) (y - r) (x - HVContrast * r) (x + HVContrast * r) true
glyph-block-export OShapeT
define [OShapeT sink u d l r _width _ada _adb] : glyph-proc
define [OShapeT sink u d l r _width _ada _adb] : begin
local middle : (l + r) / 2
local width : fallback _width Stroke
local ada : fallback _ada SmallArchDepthA
local adb : fallback _adb SmallArchDepthB
local mc : CorrectionOMidX * width
if (u - d > ada + adb) : then : begin
include : sink
return : sink
widths width 0
g4 (middle - mc) (u - O)
archv
@ -174,7 +174,7 @@ glyph-block CommonShapes : begin
: else : begin
local ymiddlea : mix d u (adb / (ada + adb))
local ymiddleb : mix d u (ada / (ada + adb))
include : sink
return : sink
widths width 0
g4 (middle - mc) (u - O)
archv

View file

@ -12,11 +12,11 @@ glyph-block Digits-Zero : begin
define [OvalShapeT sink t b l r] : let [m : mix l r 0.5] : sink
widths.rhs
g4 (m - CorrectionOMidS) t
g4 (m - CorrectionOMidS) (t - O)
archv
g4 r [YSmoothMidR t b SmallArchDepthA SmallArchDepthB]
arcvh
g4 (m + CorrectionOMidS) b
g4 (m + CorrectionOMidS) (b + O)
archv
g4 l [YSmoothMidL t b SmallArchDepthA SmallArchDepthB]
arcvh

View file

@ -31,7 +31,7 @@ glyph-block Digits-Six : begin
archv
g4.up.mid (SB + OX) (ymiddlea + Stroke * 0.3) [widths.rhs coFine]
quadControls 0 0.85
g4 ([mix SB RightSB 0.85] - 0.25 * Stroke * HVContrast) (charTop - O) [widths.rhs]
g4 ([mix SB RightSB 0.85] - 0.25 * Stroke * HVContrast) (charTop - 0.75 * O) [widths.rhs]
glyph-block-export ClosedContourNineShape
define [ClosedContourNineShape top] : glyph-proc

View file

@ -125,19 +125,20 @@ export class DiSpiroGeometry extends GeometryBase {
asContours() {
if (this.m_cachedContours) return this.m_cachedContours;
const expandResult = this.expand();
const lhs = [...expandResult.lhs];
const rhs = [...expandResult.rhs];
const lhs = [...expandResult.lhsUntransformed];
const rhs = [...expandResult.rhsUntransformed];
let rawGeometry;
if (this.m_closed) {
rawGeometry = new CombineGeometry([
new SpiroGeometry(Transform.Id(), true, lhs.slice(0, -1)),
new SpiroGeometry(Transform.Id(), true, rhs.reverse().slice(0, -1))
new SpiroGeometry(this.m_gizmo, true, lhs),
new SpiroGeometry(this.m_gizmo, true, rhs.reverse())
]);
} else {
lhs[0].type = lhs[lhs.length - 1].type = "corner";
rhs[0].type = rhs[rhs.length - 1].type = "corner";
const allKnots = lhs.concat(rhs.reverse());
rawGeometry = new SpiroGeometry(Transform.Id(), true, allKnots);
rawGeometry = new SpiroGeometry(this.m_gizmo, true, allKnots);
}
this.m_cachedContours = rawGeometry.asContours();
return this.m_cachedContours;