Optimize
This commit is contained in:
parent
79cffe6a18
commit
be43dc99eb
7 changed files with 102 additions and 33 deletions
|
@ -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 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 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).
|
||||
* Geometry refinements:
|
||||
- Balance stroke width of curly W/w in bold weights (#1011).
|
||||
|
|
|
@ -4,7 +4,7 @@ const fs = require("fs-extra");
|
|||
const zlib = require("zlib");
|
||||
const { encode, decode } = require("@msgpack/msgpack");
|
||||
|
||||
const Edition = 3;
|
||||
const Edition = 4;
|
||||
const MAX_AGE = 5;
|
||||
|
||||
class GfEntry {
|
||||
|
|
|
@ -5,7 +5,6 @@ const Geom = require("../../support/geometry");
|
|||
const Point = require("../../support/point");
|
||||
const Transform = require("../../support/transform");
|
||||
const CurveUtil = require("../../support/curve-util");
|
||||
const util = require("util");
|
||||
|
||||
module.exports = finalizeGlyphs;
|
||||
function finalizeGlyphs(cache, para, glyphStore) {
|
||||
|
@ -17,22 +16,44 @@ function finalizeGlyphs(cache, para, glyphStore) {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function regulateGlyphStore(cache, skew, glyphStore) {
|
||||
const compositeMemo = new Map();
|
||||
for (const g of glyphStore.glyphs()) {
|
||||
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) {
|
||||
const refs = g.geometry.asReferences();
|
||||
if (!refs) return false;
|
||||
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 || 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) {
|
||||
|
@ -92,7 +113,7 @@ class SimplifyGeometry extends Geom.GeometryBase {
|
|||
return this.m_geom.measureComplexity();
|
||||
}
|
||||
toShapeStringOrNull() {
|
||||
const sTarget = this.m_geom.toShapeStringOrNull();
|
||||
const sTarget = this.m_geom.unwrapShapeIdentity().toShapeStringOrNull();
|
||||
if (!sTarget) return null;
|
||||
return `SimplifyGeometry{${sTarget}}`;
|
||||
}
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
import 'typo-geom' as TypoGeom
|
||||
import '../support/curve-util' as CurveUtil
|
||||
import '../support/geometry' as [object BooleanGeometry]
|
||||
import '../support/geometry' as [object BooleanGeometry TransformedGeometry]
|
||||
|
||||
export : define [SetupBuilders args] : begin
|
||||
define [object Glyph GlobalTransform] args
|
||||
define [impl operator operands] : begin
|
||||
return : function [] : begin
|
||||
local operandGeometries {}
|
||||
local forwardGizmo : this.gizmo || GlobalTransform
|
||||
local backwardGizmo : forwardGizmo.inverse
|
||||
foreach operand [items-of operands] : begin
|
||||
local g1 : new Glyph
|
||||
set g1.gizmo : this.gizmo || GlobalTransform
|
||||
set g1.gizmo forwardGizmo
|
||||
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 [intersection] : impl TypoGeom.Boolean.ClipType.ctIntersection [{}.slice.call arguments 0]
|
||||
|
|
|
@ -14,6 +14,9 @@ class GeometryBase {
|
|||
asReferences() {
|
||||
throw new Error("Unimplemented");
|
||||
}
|
||||
unwrapShapeIdentity() {
|
||||
return this;
|
||||
}
|
||||
filterTag(fn) {
|
||||
return this;
|
||||
}
|
||||
|
@ -100,6 +103,9 @@ class ReferenceGeometry extends GeometryBase {
|
|||
measureComplexity() {
|
||||
return this.m_glyph.geometry.measureComplexity();
|
||||
}
|
||||
unwrapShapeIdentity() {
|
||||
return this.unwrap().unwrapShapeIdentity();
|
||||
}
|
||||
toShapeStringOrNull() {
|
||||
let sTarget = this.m_glyph.geometry.toShapeStringOrNull();
|
||||
if (!sTarget) return null;
|
||||
|
@ -129,6 +135,9 @@ class TaggedGeometry extends GeometryBase {
|
|||
measureComplexity() {
|
||||
return this.m_geom.measureComplexity();
|
||||
}
|
||||
unwrapShapeIdentity() {
|
||||
return this.m_geom.unwrapShapeIdentity();
|
||||
}
|
||||
toShapeStringOrNull() {
|
||||
return this.m_geom.toShapeStringOrNull();
|
||||
}
|
||||
|
@ -170,6 +179,26 @@ class TransformedGeometry extends GeometryBase {
|
|||
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() {
|
||||
const sTarget = this.m_geom.toShapeStringOrNull();
|
||||
if (!sTarget) return null;
|
||||
|
@ -231,6 +260,19 @@ class CombineGeometry extends GeometryBase {
|
|||
let s = 0;
|
||||
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() {
|
||||
let sParts = [];
|
||||
for (const item of this.m_parts) {
|
||||
|
@ -255,8 +297,10 @@ class BooleanGeometry extends GeometryBase {
|
|||
return this.m_resolved;
|
||||
}
|
||||
asContoursImpl() {
|
||||
if (this.m_operands.length === 0) return [];
|
||||
|
||||
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.PolyFillType.pftNonZero,
|
||||
|
@ -296,6 +340,16 @@ class BooleanGeometry extends GeometryBase {
|
|||
let s = 0;
|
||||
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() {
|
||||
let sParts = [];
|
||||
for (const item of this.m_operands) {
|
||||
|
|
|
@ -131,26 +131,14 @@ module.exports = class Glyph {
|
|||
|
||||
tryBecomeMirrorOf(dst, rankSet) {
|
||||
if (rankSet.has(this) || rankSet.has(dst)) return;
|
||||
const csThis = this.geometry.asContours();
|
||||
const csDst = dst.geometry.asContours();
|
||||
if (csThis.length !== csDst.length) return;
|
||||
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;
|
||||
}
|
||||
}
|
||||
const csThis = this.geometry.unwrapShapeIdentity().toShapeStringOrNull();
|
||||
const csDst = dst.geometry.unwrapShapeIdentity().toShapeStringOrNull();
|
||||
if (csThis && csDst && csThis === csDst) {
|
||||
this.geometry = new Geom.CombineGeometry([new Geom.ReferenceGeometry(dst, 0, 0)]);
|
||||
rankSet.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
clearGeometry() {
|
||||
this.geometry = new Geom.CombineGeometry();
|
||||
}
|
||||
|
|
|
@ -58,4 +58,7 @@ module.exports = class Transform {
|
|||
static isTranslate(tfm) {
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue