diff --git a/font-src/gen/caching/index.js b/font-src/gen/caching/index.js index 7891754a3..62da13a87 100644 --- a/font-src/gen/caching/index.js +++ b/font-src/gen/caching/index.js @@ -4,7 +4,7 @@ const fs = require("fs-extra"); const zlib = require("zlib"); const { encode, decode } = require("@msgpack/msgpack"); -const Edition = 7; +const Edition = 8; const MAX_AGE = 5; class GfEntry { diff --git a/font-src/kits/spiro-kit.ptl b/font-src/kits/spiro-kit.ptl index 96dbd6051..58c1d0ea8 100644 --- a/font-src/kits/spiro-kit.ptl +++ b/font-src/kits/spiro-kit.ptl @@ -1,8 +1,9 @@ import 'spiro' as SpiroJs -import [SpiroExpansionContext1 SpiroExpansionContext2] from '../support/spiro-expand' import '../support/curve-util' as CurveUtil import '../support/transform' as Transform -import '../support/utils' as [object fallback mix bez2 bez3] +import [SpiroExpansionContext1 SpiroExpansionContext2] from '../support/spiro-expand' +import [fallback mix bez2 bez3] from '../support/utils' +import [SpiroGeometry CombineGeometry] from "../support/geometry" export : define [SetupBuilders args] : begin define [object para Glyph Contrast GlobalTransform Stroke] args @@ -182,9 +183,6 @@ export : define [SetupBuilders args] : begin set knots : flatten s knots return { .knots knots .closed closed } - define [convertSpiroToBezier knots closed ctx] : begin - return : SpiroJs.spiroToBezierOnContext knots closed ctx CurveUtil.SPIRO_PRECISION - define [iterateNormals s closed] : begin local knotsP2 : s.getPass2Knots closed [fallback s.contrast Contrast] local s2 : new SpiroExpansionContext2 s.controlKnots s.gizmo @@ -205,30 +203,23 @@ export : define [SetupBuilders args] : begin local {.lhs lhs .rhs rhs} : s.expand [fallback s.contrast Contrast] if closed : then - local g : new CurveUtil.BezToContoursSink - # CurveUtil.BezToContoursSink::beginShape won't clear the contours - # We will get two contours at last - convertSpiroToBezier [lhs.slice 0 (-1)] CLOSED g - convertSpiroToBezier [rhs.reverse :.slice 0 (-1)] CLOSED g - set g.contours { [g.contours.0.concat g.contours.1] } + this.includeGeometry : new CombineGeometry : list + new SpiroGeometry [lhs.slice 0 (-1)] closed [Transform.Id] + new SpiroGeometry [rhs.reverse :.slice 0 (-1)] closed [Transform.Id] + : else : begin - local g : new CurveUtil.BezToContoursSink lhs.0.type = lhs.(lhs.length - 1).type = 'corner' rhs.0.type = rhs.(rhs.length - 1).type = 'corner' - convertSpiroToBezier [lhs.concat : rhs.reverse] CLOSED g + define allKnots : lhs.concat : rhs.reverse + this.includeGeometry : new SpiroGeometry allKnots CLOSED [Transform.Id] - set g.knots knots - set g.lhsKnots lhs - set g.rhsKnots rhs - this.includeContours g.contours 0 0 - return g + return { .knots knots .lhsKnots lhs .rhsKnots rhs } define [spiro-outline] : let [k : {}.slice.call arguments 0] : lambda [] : begin - local g : new CurveUtil.BezToContoursSink (this.gizmo || GlobalTransform) + local gizmo : this.gizmo || GlobalTransform + local g : new CurveUtil.BezToContoursSink gizmo local { .knots knots .closed closed } : prepareSpiroKnots k g - convertSpiroToBezier knots closed g - this.includeContours g.contours 0 0 - return g + this.includeGeometry : new SpiroGeometry knots closed gizmo return [object g4 g2 corner flat curl close end straight diff --git a/font-src/support/geometry.js b/font-src/support/geometry.js index 609531b7c..5a394ef17 100644 --- a/font-src/support/geometry.js +++ b/font-src/support/geometry.js @@ -2,6 +2,7 @@ const crypto = require("crypto"); const TypoGeom = require("typo-geom"); +const SpiroJs = require("spiro"); const Point = require("./point"); const Transform = require("./transform"); @@ -70,6 +71,55 @@ class ContourGeometry extends GeometryBase { } } +class SpiroGeometry extends GeometryBase { + constructor(knots, closed, gizmo) { + super(); + this.m_knots = []; + for (const k of knots) { + this.m_knots.push({ type: k.type, x: k.x, y: k.y }); + } + this.m_closed = closed; + this.m_gizmo = gizmo; + this.m_cachedContours = null; + } + asContours() { + if (this.m_cachedContours) return this.m_cachedContours; + const s = new CurveUtil.BezToContoursSink(this.m_gizmo); + SpiroJs.spiroToBezierOnContext(this.m_knots, this.m_closed, s, CurveUtil.SPIRO_PRECISION); + this.m_cachedContours = s.contours; + return this.m_cachedContours; + } + asReferences() { + return null; + } + filterTag(fn) { + return this; + } + isEmpty() { + return !this.m_knots.length; + } + measureComplexity() { + for (const z of this.m_knots) { + if (!isFinite(z.x) || !isFinite(z.y)) return 0xffff; + } + return this.m_knots.length; + } + toShapeStringOrNull() { + let s = "SpiroGeometry{{"; + for (const k of this.m_knots) { + s += `(${k.type};${formatN(k.x)};${formatN(k.y)})`; + } + s += "};"; + s += `${this.m_closed};`; + s += + `;{${formatN(this.m_gizmo.xx)},${formatN(this.m_gizmo.xy)},` + + `${formatN(this.m_gizmo.yx)},${formatN(this.m_gizmo.yy)},` + + `${formatN(this.m_gizmo.x)},${formatN(this.m_gizmo.y)}}`; + s += "}"; + return s; + } +} + class ReferenceGeometry extends GeometryBase { constructor(glyph, x, y) { super(); @@ -380,6 +430,7 @@ function formatN(x) { } exports.GeometryBase = GeometryBase; +exports.SpiroGeometry = SpiroGeometry; exports.ContourGeometry = ContourGeometry; exports.ReferenceGeometry = ReferenceGeometry; exports.TaggedGeometry = TaggedGeometry;