Reduce closures
This commit is contained in:
parent
1f0be761a2
commit
f8a104d550
4 changed files with 148 additions and 108 deletions
|
@ -3,32 +3,44 @@
|
||||||
const TypoGeom = require("typo-geom");
|
const TypoGeom = require("typo-geom");
|
||||||
const { BooleanGeometry, TransformedGeometry } = require("../support/geometry/index");
|
const { BooleanGeometry, TransformedGeometry } = require("../support/geometry/index");
|
||||||
|
|
||||||
exports.SetupBuilders = function ({ Glyph, GlobalTransform }) {
|
exports.SetupBuilders = function (bindings) {
|
||||||
function impl(operator, operands) {
|
const union = (...operands) =>
|
||||||
return function () {
|
new BooleImpl(bindings, TypoGeom.Boolean.ClipType.ctUnion, operands);
|
||||||
const operandGeometries = [];
|
const intersection = (...operands) =>
|
||||||
const forwardGizmo = this.gizmo || GlobalTransform;
|
new BooleImpl(bindings, TypoGeom.Boolean.ClipType.ctIntersection, operands);
|
||||||
const backwardGizmo = forwardGizmo.inverse();
|
const difference = (...operands) =>
|
||||||
for (const operand of operands) {
|
new BooleImpl(bindings, TypoGeom.Boolean.ClipType.ctDifference, operands);
|
||||||
const g1 = new Glyph();
|
|
||||||
g1.gizmo = forwardGizmo;
|
|
||||||
g1.include(operand);
|
|
||||||
operandGeometries.push(new TransformedGeometry(g1.geometry, backwardGizmo));
|
|
||||||
}
|
|
||||||
return this.includeGeometry(
|
|
||||||
new TransformedGeometry(
|
|
||||||
new BooleanGeometry(operator, operandGeometries),
|
|
||||||
forwardGizmo
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const union = (...operands) => impl(TypoGeom.Boolean.ClipType.ctUnion, operands);
|
|
||||||
const intersection = (...operands) => impl(TypoGeom.Boolean.ClipType.ctIntersection, operands);
|
|
||||||
const difference = (...operands) => impl(TypoGeom.Boolean.ClipType.ctDifference, operands);
|
|
||||||
return {
|
return {
|
||||||
union: union,
|
union: union,
|
||||||
intersection: intersection,
|
intersection: intersection,
|
||||||
difference: difference
|
difference: difference
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class BooleImpl {
|
||||||
|
constructor(bindings, operator, operands) {
|
||||||
|
this.bindings = bindings;
|
||||||
|
this.operator = operator;
|
||||||
|
this.operands = operands;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyToGlyph(glyph) {
|
||||||
|
const operandGeometries = [];
|
||||||
|
const forwardGizmo = glyph.gizmo || this.bindings.GlobalTransform;
|
||||||
|
const backwardGizmo = forwardGizmo.inverse();
|
||||||
|
for (const operand of this.operands) {
|
||||||
|
const g1 = new this.bindings.Glyph();
|
||||||
|
g1.gizmo = forwardGizmo;
|
||||||
|
g1.include(operand);
|
||||||
|
operandGeometries.push(new TransformedGeometry(g1.geometry, backwardGizmo));
|
||||||
|
}
|
||||||
|
return glyph.includeGeometry(
|
||||||
|
new TransformedGeometry(
|
||||||
|
new BooleanGeometry(this.operator, operandGeometries),
|
||||||
|
forwardGizmo
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -222,95 +222,15 @@ exports.SetupBuilders = function (bindings) {
|
||||||
arcvh.superness = function (s) {
|
arcvh.superness = function (s) {
|
||||||
return arcvh(DEFAULT_STEPS, s);
|
return arcvh(DEFAULT_STEPS, s);
|
||||||
};
|
};
|
||||||
function flattenImpl(sink, knots) {
|
|
||||||
for (const p of knots) {
|
|
||||||
if (p instanceof Array) flattenImpl(sink, p);
|
|
||||||
else sink.push(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function nCyclic(p, n) {
|
|
||||||
return (p + n + n) % n;
|
|
||||||
}
|
|
||||||
function flatten(s, knots0) {
|
|
||||||
let knots = [];
|
|
||||||
flattenImpl(knots, knots0);
|
|
||||||
let unwrapped = false;
|
|
||||||
for (let j = 0; j < knots.length; j = j + 1)
|
|
||||||
if (knots[j] && knots[j].type === "interpolate") {
|
|
||||||
const kBefore = knots[nCyclic(j - 1, knots.length)];
|
|
||||||
const kAfter = knots[nCyclic(j + 1, knots.length)];
|
|
||||||
knots[j] = knots[j].blender(kBefore, kAfter, knots[j]);
|
|
||||||
unwrapped = true;
|
|
||||||
}
|
|
||||||
if (unwrapped) return flatten(s, knots);
|
|
||||||
return knots;
|
|
||||||
}
|
|
||||||
function dropTailKnot(knots) {
|
|
||||||
let last = knots[knots.length - 1];
|
|
||||||
if (last && (last.type === "close" || last.type === "end")) {
|
|
||||||
knots.length = knots.length - 1;
|
|
||||||
return last.type === "close";
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function prepareSpiroKnots(_knots, s) {
|
|
||||||
let knots = [..._knots];
|
|
||||||
while (knots[0] && knots[0] instanceof Function) {
|
|
||||||
knots[0].call(s);
|
|
||||||
knots.splice(0, 1);
|
|
||||||
}
|
|
||||||
const closed = dropTailKnot(knots);
|
|
||||||
knots = flatten(s, knots);
|
|
||||||
return { knots, closed };
|
|
||||||
}
|
|
||||||
|
|
||||||
class DiSpiroProxy {
|
|
||||||
constructor(closed, collector, origKnots) {
|
|
||||||
this.geometry = new DiSpiroGeometry(
|
|
||||||
collector.gizmo,
|
|
||||||
collector.contrast,
|
|
||||||
closed,
|
|
||||||
collector.controlKnots
|
|
||||||
);
|
|
||||||
this.m_origKnots = origKnots;
|
|
||||||
}
|
|
||||||
|
|
||||||
get knots() {
|
|
||||||
return this.m_origKnots;
|
|
||||||
}
|
|
||||||
get lhsKnots() {
|
|
||||||
return this.geometry.expand().lhs;
|
|
||||||
}
|
|
||||||
get rhsKnots() {
|
|
||||||
return this.geometry.expand().rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function dispiro(...args) {
|
function dispiro(...args) {
|
||||||
return function () {
|
return new DispiroImpl(bindings, args);
|
||||||
const gizmo = this.gizmo || GlobalTransform;
|
|
||||||
const collector = new BiKnotCollector(gizmo, Contrast);
|
|
||||||
const { knots, closed } = prepareSpiroKnots(args, collector);
|
|
||||||
for (const knot of knots) {
|
|
||||||
collector.pushKnot(knot.type, knot.x, knot.y);
|
|
||||||
if (knot.af) knot.af.call(collector);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dsp = new DiSpiroProxy(closed, collector, knots);
|
|
||||||
this.includeGeometry(dsp.geometry);
|
|
||||||
return dsp;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function spiroOutline(...args) {
|
function spiroOutline(...args) {
|
||||||
return function () {
|
return new SpiroOutlineImpl(bindings, args);
|
||||||
const gizmo = this.gizmo || GlobalTransform;
|
|
||||||
const g = new CurveUtil.BezToContoursSink(gizmo);
|
|
||||||
const { knots, closed } = prepareSpiroKnots(args, g);
|
|
||||||
return this.includeGeometry(new SpiroGeometry(gizmo, closed, knots));
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
g4,
|
g4,
|
||||||
g2,
|
g2,
|
||||||
|
@ -335,3 +255,108 @@ exports.SetupBuilders = function (bindings) {
|
||||||
"spiro-outline": spiroOutline
|
"spiro-outline": spiroOutline
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class DispiroImpl {
|
||||||
|
constructor(bindings, args) {
|
||||||
|
this.bindings = bindings;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
applyToGlyph(glyph) {
|
||||||
|
const gizmo = glyph.gizmo || this.bindings.GlobalTransform;
|
||||||
|
const collector = new BiKnotCollector(gizmo, this.bindings.Contrast);
|
||||||
|
const { knots, closed } = prepareSpiroKnots(this.args, collector);
|
||||||
|
for (const knot of knots) {
|
||||||
|
collector.pushKnot(knot.type, knot.x, knot.y);
|
||||||
|
if (knot.af) knot.af.call(collector);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dsp = new DiSpiroProxy(closed, collector, knots);
|
||||||
|
glyph.includeGeometry(dsp.geometry);
|
||||||
|
return dsp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SpiroOutlineImpl {
|
||||||
|
constructor(bindings, args) {
|
||||||
|
this.bindings = bindings;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyToGlyph(glyph) {
|
||||||
|
const gizmo = glyph.gizmo || this.bindings.GlobalTransform;
|
||||||
|
const g = new CurveUtil.BezToContoursSink(gizmo);
|
||||||
|
const { knots, closed } = prepareSpiroKnots(this.args, g);
|
||||||
|
return glyph.includeGeometry(new SpiroGeometry(gizmo, closed, knots));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiSpiroProxy {
|
||||||
|
constructor(closed, collector, origKnots) {
|
||||||
|
this.geometry = new DiSpiroGeometry(
|
||||||
|
collector.gizmo,
|
||||||
|
collector.contrast,
|
||||||
|
closed,
|
||||||
|
collector.controlKnots
|
||||||
|
);
|
||||||
|
this.m_origKnots = origKnots;
|
||||||
|
}
|
||||||
|
|
||||||
|
get knots() {
|
||||||
|
return this.m_origKnots;
|
||||||
|
}
|
||||||
|
get lhsKnots() {
|
||||||
|
return this.geometry.expand().lhs;
|
||||||
|
}
|
||||||
|
get rhsKnots() {
|
||||||
|
return this.geometry.expand().rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareSpiroKnots(_knots, s) {
|
||||||
|
let knots = [..._knots];
|
||||||
|
while (knots[0] && knots[0] instanceof Function) {
|
||||||
|
knots[0].call(s);
|
||||||
|
knots.splice(0, 1);
|
||||||
|
}
|
||||||
|
const closed = dropTailKnot(knots);
|
||||||
|
knots = flatten(s, knots);
|
||||||
|
return { knots, closed };
|
||||||
|
}
|
||||||
|
|
||||||
|
function dropTailKnot(knots) {
|
||||||
|
let last = knots[knots.length - 1];
|
||||||
|
if (last && (last.type === "close" || last.type === "end")) {
|
||||||
|
knots.length = knots.length - 1;
|
||||||
|
return last.type === "close";
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function flatten(s, knots0) {
|
||||||
|
let knots = [];
|
||||||
|
flattenImpl(knots, knots0);
|
||||||
|
let unwrapped = false;
|
||||||
|
for (let j = 0; j < knots.length; j = j + 1)
|
||||||
|
if (knots[j] && knots[j].type === "interpolate") {
|
||||||
|
const kBefore = knots[nCyclic(j - 1, knots.length)];
|
||||||
|
const kAfter = knots[nCyclic(j + 1, knots.length)];
|
||||||
|
knots[j] = knots[j].blender(kBefore, kAfter, knots[j]);
|
||||||
|
unwrapped = true;
|
||||||
|
}
|
||||||
|
if (unwrapped) return flatten(s, knots);
|
||||||
|
return knots;
|
||||||
|
}
|
||||||
|
|
||||||
|
function flattenImpl(sink, knots) {
|
||||||
|
for (const p of knots) {
|
||||||
|
if (p instanceof Array) flattenImpl(sink, p);
|
||||||
|
else sink.push(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function nCyclic(p, n) {
|
||||||
|
return (p + n + n) % n;
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,9 @@ exports.GlyphStore = class GlyphStore {
|
||||||
this.encodingBackward = new Map();
|
this.encodingBackward = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get size() {
|
||||||
|
return this.nameForward.size;
|
||||||
|
}
|
||||||
glyphs() {
|
glyphs() {
|
||||||
return this.nameForward.values();
|
return this.nameForward.values();
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,10 +63,10 @@ exports.Glyph = class Glyph {
|
||||||
include(component, copyAnchors, copyWidth) {
|
include(component, copyAnchors, copyWidth) {
|
||||||
if (!component) {
|
if (!component) {
|
||||||
throw new Error("Unreachable: Attempt to include a Null or Undefined");
|
throw new Error("Unreachable: Attempt to include a Null or Undefined");
|
||||||
} else if (component instanceof Function) {
|
|
||||||
return component.call(this, copyAnchors, copyWidth);
|
|
||||||
} else if (component.applyToGlyph instanceof Function) {
|
} else if (component.applyToGlyph instanceof Function) {
|
||||||
return component.applyToGlyph(this, copyAnchors, copyWidth);
|
return component.applyToGlyph(this, copyAnchors, copyWidth);
|
||||||
|
} else if (component instanceof Function) {
|
||||||
|
return component.call(this, copyAnchors, copyWidth);
|
||||||
} else if (component instanceof Transform) {
|
} else if (component instanceof Transform) {
|
||||||
return this.applyTransform(component, copyAnchors);
|
return this.applyTransform(component, copyAnchors);
|
||||||
} else if (component instanceof Glyph) {
|
} else if (component instanceof Glyph) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue