This commit is contained in:
be5invis 2021-05-25 18:57:19 -07:00
parent 79cffe6a18
commit be43dc99eb
7 changed files with 102 additions and 33 deletions

View file

@ -102,7 +102,7 @@
- Fix incorrect mapping of Greek Small Reversed Lunate Sigma Symbol (`U+037B`) and Greek Capital Reversed Lunate Sigma Symbol (`U+03FD`) (#1036). - Fix incorrect mapping of Greek Small Reversed Lunate Sigma Symbol (`U+037B`) and Greek Capital Reversed Lunate Sigma Symbol (`U+03FD`) (#1036).
- Fix incorrect shape of Symbol For Device Control One (`U+2411`) (#1037). - Fix incorrect shape of Symbol For Device Control One (`U+2411`) (#1037).
- Fix incorrect glyph shape mapping of Up Right Diagonal Ellipsis (`U+22F0`) and Down Right Diagonal Ellipsis (`U+22F1`) (#1039). - Fix incorrect glyph shape mapping of Up Right Diagonal Ellipsis (`U+22F0`) and Down Right Diagonal Ellipsis (`U+22F1`) (#1039).
- Fix missing dot on Modifier Letter Small I With Stroke (`U+1DA4`) (#1043). - Fix missing dot on Latin Small Letter I With Stroke (`U+0268`) and Modifier Letter Small I With Stroke (`U+1DA4`) (#1043, #1066).
- Fix incorrect slope of Circled Italic Latin Capital C (`U+1F12B`) and Circled Italic Latin Capital R (`U+1F12C`) (#1051). - Fix incorrect slope of Circled Italic Latin Capital C (`U+1F12B`) and Circled Italic Latin Capital R (`U+1F12C`) (#1051).
* Geometry refinements: * Geometry refinements:
- Balance stroke width of curly W/w in bold weights (#1011). - Balance stroke width of curly W/w in bold weights (#1011).

View file

@ -4,7 +4,7 @@ const fs = require("fs-extra");
const zlib = require("zlib"); const zlib = require("zlib");
const { encode, decode } = require("@msgpack/msgpack"); const { encode, decode } = require("@msgpack/msgpack");
const Edition = 3; const Edition = 4;
const MAX_AGE = 5; const MAX_AGE = 5;
class GfEntry { class GfEntry {

View file

@ -5,7 +5,6 @@ const Geom = require("../../support/geometry");
const Point = require("../../support/point"); const Point = require("../../support/point");
const Transform = require("../../support/transform"); const Transform = require("../../support/transform");
const CurveUtil = require("../../support/curve-util"); const CurveUtil = require("../../support/curve-util");
const util = require("util");
module.exports = finalizeGlyphs; module.exports = finalizeGlyphs;
function finalizeGlyphs(cache, para, glyphStore) { function finalizeGlyphs(cache, para, glyphStore) {
@ -17,22 +16,44 @@ function finalizeGlyphs(cache, para, glyphStore) {
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
function regulateGlyphStore(cache, skew, glyphStore) { function regulateGlyphStore(cache, skew, glyphStore) {
const compositeMemo = new Map();
for (const g of glyphStore.glyphs()) { for (const g of glyphStore.glyphs()) {
if (g.geometry.isEmpty()) continue; if (g.geometry.isEmpty()) continue;
if (!regulateCompositeGlyph(glyphStore, g)) flattenSimpleGlyph(cache, skew, g); if (!regulateCompositeGlyph(glyphStore, compositeMemo, g)) {
flattenSimpleGlyph(cache, skew, g);
}
} }
} }
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
function regulateCompositeGlyph(glyphStore, g) { function memoSet(memo, g, v) {
const refs = g.geometry.asReferences(); memo.set(g, v);
if (!refs) return false; 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) { for (const sr of refs) {
const gn = glyphStore.queryNameOf(sr.glyph); const gn = glyphStore.queryNameOf(sr.glyph);
if (!gn || sr.glyph.autoRefPriority < 0) return false; if (!gn || sr.glyph.autoRefPriority < 0) return memoSet(memo, g, false);
} }
return true;
// De-doppelganger
while (refs.length === 1 && regulateCompositeGlyph(glyphStore, memo, refs[0].glyph)) {
const sr = refs[0];
const targetRefs = sr.glyph.geometry.asReferences();
g.clearGeometry();
for (const tr of targetRefs) {
g.includeGeometry(new Geom.ReferenceGeometry(tr.glyph, tr.x + sr.x, tr.y + sr.y));
}
refs = g.geometry.asReferences();
}
return memoSet(memo, g, true);
} }
function flattenSimpleGlyph(cache, skew, g) { function flattenSimpleGlyph(cache, skew, g) {
@ -92,7 +113,7 @@ class SimplifyGeometry extends Geom.GeometryBase {
return this.m_geom.measureComplexity(); return this.m_geom.measureComplexity();
} }
toShapeStringOrNull() { toShapeStringOrNull() {
const sTarget = this.m_geom.toShapeStringOrNull(); const sTarget = this.m_geom.unwrapShapeIdentity().toShapeStringOrNull();
if (!sTarget) return null; if (!sTarget) return null;
return `SimplifyGeometry{${sTarget}}`; return `SimplifyGeometry{${sTarget}}`;
} }

View file

@ -1,19 +1,22 @@
import 'typo-geom' as TypoGeom import 'typo-geom' as TypoGeom
import '../support/curve-util' as CurveUtil import '../support/curve-util' as CurveUtil
import '../support/geometry' as [object BooleanGeometry] import '../support/geometry' as [object BooleanGeometry TransformedGeometry]
export : define [SetupBuilders args] : begin export : define [SetupBuilders args] : begin
define [object Glyph GlobalTransform] args define [object Glyph GlobalTransform] args
define [impl operator operands] : begin define [impl operator operands] : begin
return : function [] : begin return : function [] : begin
local operandGeometries {} local operandGeometries {}
local forwardGizmo : this.gizmo || GlobalTransform
local backwardGizmo : forwardGizmo.inverse
foreach operand [items-of operands] : begin foreach operand [items-of operands] : begin
local g1 : new Glyph local g1 : new Glyph
set g1.gizmo : this.gizmo || GlobalTransform set g1.gizmo forwardGizmo
g1.include operand g1.include operand
operandGeometries.push g1.geometry operandGeometries.push : new TransformedGeometry g1.geometry backwardGizmo
this.includeGeometry : new BooleanGeometry operator operandGeometries define geomPureBoolian : new BooleanGeometry operator operandGeometries
this.includeGeometry : new TransformedGeometry geomPureBoolian forwardGizmo
define [union] : impl TypoGeom.Boolean.ClipType.ctUnion [{}.slice.call arguments 0] define [union] : impl TypoGeom.Boolean.ClipType.ctUnion [{}.slice.call arguments 0]
define [intersection] : impl TypoGeom.Boolean.ClipType.ctIntersection [{}.slice.call arguments 0] define [intersection] : impl TypoGeom.Boolean.ClipType.ctIntersection [{}.slice.call arguments 0]

View file

@ -14,6 +14,9 @@ class GeometryBase {
asReferences() { asReferences() {
throw new Error("Unimplemented"); throw new Error("Unimplemented");
} }
unwrapShapeIdentity() {
return this;
}
filterTag(fn) { filterTag(fn) {
return this; return this;
} }
@ -100,6 +103,9 @@ class ReferenceGeometry extends GeometryBase {
measureComplexity() { measureComplexity() {
return this.m_glyph.geometry.measureComplexity(); return this.m_glyph.geometry.measureComplexity();
} }
unwrapShapeIdentity() {
return this.unwrap().unwrapShapeIdentity();
}
toShapeStringOrNull() { toShapeStringOrNull() {
let sTarget = this.m_glyph.geometry.toShapeStringOrNull(); let sTarget = this.m_glyph.geometry.toShapeStringOrNull();
if (!sTarget) return null; if (!sTarget) return null;
@ -129,6 +135,9 @@ class TaggedGeometry extends GeometryBase {
measureComplexity() { measureComplexity() {
return this.m_geom.measureComplexity(); return this.m_geom.measureComplexity();
} }
unwrapShapeIdentity() {
return this.m_geom.unwrapShapeIdentity();
}
toShapeStringOrNull() { toShapeStringOrNull() {
return this.m_geom.toShapeStringOrNull(); return this.m_geom.toShapeStringOrNull();
} }
@ -170,6 +179,26 @@ class TransformedGeometry extends GeometryBase {
measureComplexity() { measureComplexity() {
return this.m_geom.measureComplexity(); return this.m_geom.measureComplexity();
} }
unwrapShapeIdentity() {
const unwrapped = this.m_geom.unwrapShapeIdentity();
if (Transform.isIdentity(this.m_transform)) {
return unwrapped;
} else if (
unwrapped instanceof TransformedGeometry &&
Transform.isTranslate(this.m_transform) &&
Transform.isTranslate(unwrapped.m_transform)
) {
return new TransformedGeometry(
unwrapped.m_geom,
Transform.Translate(
this.m_transform.x + unwrapped.m_transform.x,
this.m_transform.y + unwrapped.m_transform.y
)
);
} else {
return new TransformedGeometry(unwrapped, this.m_transform);
}
}
toShapeStringOrNull() { toShapeStringOrNull() {
const sTarget = this.m_geom.toShapeStringOrNull(); const sTarget = this.m_geom.toShapeStringOrNull();
if (!sTarget) return null; if (!sTarget) return null;
@ -231,6 +260,19 @@ class CombineGeometry extends GeometryBase {
let s = 0; let s = 0;
for (const part of this.m_parts) s += part.measureComplexity(); for (const part of this.m_parts) s += part.measureComplexity();
} }
unwrapShapeIdentity() {
let parts = [];
for (const part of this.m_parts) {
const unwrapped = part.unwrapShapeIdentity();
if (unwrapped instanceof CombineGeometry) {
for (const p of unwrapped.m_parts) parts.push(p);
} else {
parts.push(unwrapped);
}
}
return new CombineGeometry(parts);
}
toShapeStringOrNull() { toShapeStringOrNull() {
let sParts = []; let sParts = [];
for (const item of this.m_parts) { for (const item of this.m_parts) {
@ -255,8 +297,10 @@ class BooleanGeometry extends GeometryBase {
return this.m_resolved; return this.m_resolved;
} }
asContoursImpl() { asContoursImpl() {
if (this.m_operands.length === 0) return [];
let arcs = CurveUtil.convertShapeToArcs(this.m_operands[0].asContours()); let arcs = CurveUtil.convertShapeToArcs(this.m_operands[0].asContours());
if (this.m_operands.length < 2) { if (this.m_operands.length === 1) {
arcs = TypoGeom.Boolean.removeOverlap( arcs = TypoGeom.Boolean.removeOverlap(
arcs, arcs,
TypoGeom.Boolean.PolyFillType.pftNonZero, TypoGeom.Boolean.PolyFillType.pftNonZero,
@ -296,6 +340,16 @@ class BooleanGeometry extends GeometryBase {
let s = 0; let s = 0;
for (const operand of this.m_operands) s += operand.measureComplexity(); for (const operand of this.m_operands) s += operand.measureComplexity();
} }
unwrapShapeIdentity() {
if (this.m_operands.length === 0) return new CombineGeometry([]);
if (this.m_operands.length === 1) return this.m_operands[0].unwrapShapeIdentity();
let operands = [];
for (const operand of this.m_operands) {
operands.push(operand.unwrapShapeIdentity());
}
return new BooleanGeometry(this.m_operator, operands);
}
toShapeStringOrNull() { toShapeStringOrNull() {
let sParts = []; let sParts = [];
for (const item of this.m_operands) { for (const item of this.m_operands) {

View file

@ -131,26 +131,14 @@ module.exports = class Glyph {
tryBecomeMirrorOf(dst, rankSet) { tryBecomeMirrorOf(dst, rankSet) {
if (rankSet.has(this) || rankSet.has(dst)) return; if (rankSet.has(this) || rankSet.has(dst)) return;
const csThis = this.geometry.asContours(); const csThis = this.geometry.unwrapShapeIdentity().toShapeStringOrNull();
const csDst = dst.geometry.asContours(); const csDst = dst.geometry.unwrapShapeIdentity().toShapeStringOrNull();
if (csThis.length !== csDst.length) return; if (csThis && csDst && csThis === csDst) {
for (let j = 0; j < csThis.length; j++) {
const c1 = csThis[j],
c2 = csDst[j];
if (c1.length !== c2.length) return;
}
for (let j = 0; j < csThis.length; j++) {
const c1 = csThis[j],
c2 = csDst[j];
for (let k = 0; k < c1.length; k++) {
const z1 = c1[k],
z2 = c2[k];
if (z1.x !== z2.x || z1.y !== z2.y || z1.type !== z2.type) return;
}
}
this.geometry = new Geom.CombineGeometry([new Geom.ReferenceGeometry(dst, 0, 0)]); this.geometry = new Geom.CombineGeometry([new Geom.ReferenceGeometry(dst, 0, 0)]);
rankSet.add(this); rankSet.add(this);
} }
}
clearGeometry() { clearGeometry() {
this.geometry = new Geom.CombineGeometry(); this.geometry = new Geom.CombineGeometry();
} }

View file

@ -58,4 +58,7 @@ module.exports = class Transform {
static isTranslate(tfm) { static isTranslate(tfm) {
return tfm.xx === 1 && tfm.yy === 1 && tfm.xy === 0 && tfm.yx === 0; return tfm.xx === 1 && tfm.yy === 1 && tfm.xy === 0 && tfm.yx === 0;
} }
static isIdentity(tfm) {
return this.isTranslate(tfm) && tfm.x === 0 && tfm.y === 0;
}
}; };