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 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).
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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}}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue