From dad21a56ee49c8fca3c8f37487b9082aadfff0a1 Mon Sep 17 00:00:00 2001 From: be5invis Date: Wed, 7 Jul 2021 20:08:06 -0700 Subject: [PATCH] Migrate kits to JS --- .gitignore | 1 - font-src/gen/caching/index.js | 2 +- font-src/glyphs/index.ptl | 8 +- font-src/glyphs/letter/cyrillic/de.ptl | 2 +- font-src/glyphs/letter/greek/lower-alpha.ptl | 4 +- font-src/glyphs/letter/greek/lower-gamma.ptl | 8 +- font-src/glyphs/letter/greek/lower-nu.ptl | 4 +- font-src/glyphs/letter/greek/lower-zeta.ptl | 2 +- font-src/glyphs/letter/latin-ext/eth.ptl | 2 +- .../glyphs/letter/latin-ext/rams-horn.ptl | 4 +- .../glyphs/letter/latin-ext/upper-ae-oe.ptl | 4 +- font-src/glyphs/letter/latin/k.ptl | 10 +- font-src/glyphs/letter/latin/lower-y.ptl | 4 +- font-src/glyphs/letter/latin/upper-r.ptl | 4 +- font-src/glyphs/letter/latin/upper-y.ptl | 2 +- font-src/glyphs/letter/latin/v.ptl | 10 +- font-src/glyphs/letter/latin/w.ptl | 6 +- font-src/glyphs/letter/latin/x.ptl | 2 +- font-src/glyphs/letter/shared.ptl | 2 +- font-src/glyphs/marks/index.ptl | 14 +- font-src/glyphs/number/6.ptl | 2 +- font-src/glyphs/symbol/letter.ptl | 2 +- font-src/glyphs/symbol/pictograph/heart.ptl | 4 +- .../glyphs/symbol/punctuation/brackets.ptl | 12 +- .../glyphs/symbol/punctuation/guillemet.ptl | 4 +- font-src/glyphs/symbol/punctuation/small.ptl | 8 +- font-src/glyphs/symbol/punctuation/ties.ptl | 4 +- font-src/kits/boole-kit.js | 34 ++ font-src/kits/boole-kit.ptl | 25 -- font-src/kits/spiro-kit.js | 354 ++++++++++++++++++ font-src/kits/spiro-kit.ptl | 226 ----------- font-src/meta/macros.ptl | 4 +- 32 files changed, 455 insertions(+), 319 deletions(-) create mode 100644 font-src/kits/boole-kit.js delete mode 100644 font-src/kits/boole-kit.ptl create mode 100644 font-src/kits/spiro-kit.js delete mode 100644 font-src/kits/spiro-kit.ptl diff --git a/.gitignore b/.gitignore index f135c7fb1..32e0843e7 100644 --- a/.gitignore +++ b/.gitignore @@ -43,7 +43,6 @@ release-archives/ testdrive/iosevka* # Generated scripts -font-src/kits/**/*.js font-src/meta/**/*.js font-src/otl/**/*.js font-src/glyphs/**/*.js diff --git a/font-src/gen/caching/index.js b/font-src/gen/caching/index.js index 15a952e2d..10e8404d1 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 = 9; +const Edition = 10; const MAX_AGE = 5; class GfEntry { diff --git a/font-src/glyphs/index.ptl b/font-src/glyphs/index.ptl index b2c332718..44e8d95d5 100644 --- a/font-src/glyphs/index.ptl +++ b/font-src/glyphs/index.ptl @@ -4,7 +4,7 @@ import '../support/glyph-block' as GlyphBlock import '../support/point' as Point import '../support/anchor' as Anchor import '../support/gr' as Gr -import '../kits/spiro-kit' as spirokit +import '../kits/spiro-kit' as SpiroKit import '../kits/boole-kit' as BooleKit import [ DesignParameters ] from "../meta/aesthetics" @@ -105,8 +105,8 @@ export all : define [buildGlyphs para recursive recursiveCodes] : begin ### Spiro constructions # Basic knots - define spirofns : spirokit.SetupBuilders : object GlobalTransform Contrast Stroke Glyph para [superness DesignParameters.superness] - define booleFns : BooleKit.SetupBuilders : object GlobalTransform Glyph + define SpiroFns : SpiroKit.SetupBuilders : object GlobalTransform Contrast Stroke [Superness DesignParameters.superness] + define BooleFns : BooleKit.SetupBuilders : object GlobalTransform Glyph # Meta define [tagged tag component] : function [ca cw] : begin @@ -117,7 +117,7 @@ export all : define [buildGlyphs para recursive recursiveCodes] : begin return ret # IDKY, but wrapping "metrics" prevents Node.js on Arch modifying it. - define $$Capture$$ : object [metrics : Object.create metrics] $NamedParameterPair$ $donothing$ para recursive recursiveCodes glyphStore $createAndSaveGlyphImpl$ spirofns booleFns MarkSet AS_BASE ALSO_METRICS pickHash buildGlyphs tagged DivFrame fontMetrics $assignUnicodeImpl$ $defineGlyphBlockImpl$ + define $$Capture$$ : object [metrics : Object.create metrics] $NamedParameterPair$ $donothing$ para recursive recursiveCodes glyphStore $createAndSaveGlyphImpl$ SpiroFns BooleFns MarkSet AS_BASE ALSO_METRICS pickHash buildGlyphs tagged DivFrame fontMetrics $assignUnicodeImpl$ $defineGlyphBlockImpl$ ### HERE WE GO run-glyph-module './common/shapes.js' diff --git a/font-src/glyphs/letter/cyrillic/de.ptl b/font-src/glyphs/letter/cyrillic/de.ptl index ecbbe84ef..93cb0542c 100644 --- a/font-src/glyphs/letter/cyrillic/de.ptl +++ b/font-src/glyphs/letter/cyrillic/de.ptl @@ -60,5 +60,5 @@ glyph-block Letter-Cyrillic-De : begin archv flat (RightSB - OX) SmallSmoothA curl (RightSB - OX) (XH - SmallSmoothB) - quadcontrols 0 0.8 + quadControls 0 0.8 g4 (SB + Stroke * 1.1) CAP diff --git a/font-src/glyphs/letter/greek/lower-alpha.ptl b/font-src/glyphs/letter/greek/lower-alpha.ptl index 32317ae7e..280ecd244 100644 --- a/font-src/glyphs/letter/greek/lower-alpha.ptl +++ b/font-src/glyphs/letter/greek/lower-alpha.ptl @@ -23,14 +23,14 @@ glyph-block Letter-Greek-Lower-Alpha : begin include : dispiro widths.rhs fine g4 (RightSB - OX * 1.75) XH [heading Downward] - bezcontrols k1 k2 k3 1 6 + bezControls k1 k2 k3 1 6 g4.left.mid (middle + CorrectionOMidS) O [widths 0 Stroke] archv flat (SB + OX * 2) SmallSmoothB curl (SB + OX * 2) (XH - SmallSmoothA) arcvh g4.right.mid (middle - CorrectionOMidS) (XH - O) [widths 0 Stroke] - bezcontrols (1 - k3) 0 (1 - k1) (1 - k2) 6 + bezControls (1 - k3) 0 (1 - k1) (1 - k2) 6 g4 (RightSB - OX * 2) 0 [widths.heading 0 fine Downward] set-base-anchor 'overlay' (middle - OX) (XH * OverlayPos) diff --git a/font-src/glyphs/letter/greek/lower-gamma.ptl b/font-src/glyphs/letter/greek/lower-gamma.ptl index 8cd0a5fbd..95f18cf63 100644 --- a/font-src/glyphs/letter/greek/lower-gamma.ptl +++ b/font-src/glyphs/letter/greek/lower-gamma.ptl @@ -18,7 +18,7 @@ glyph-block Letter-Greek-Lower-Gamma : begin local xStart : SB + 0.4 * Stroke * HVContrast include : dispiro g4 xStart (XH - O) [widths.rhs] - bezcontrols 0.33 0.17 1 0.62 6 important + bezControls 0.33 0.17 1 0.62 6 important flat xMid 0 curl xMid Descender [heading Downward] @@ -26,7 +26,7 @@ glyph-block Letter-Greek-Lower-Gamma : begin widths.rhs flat RightSB XH [heading Downward] curl RightSB (XH * 0.9) [heading Downward] - quadcontrols 0 0.3 6 + quadControls 0 0.3 6 g4 xMid 0 [widths.rhs : Stroke * 0.9] create-glyph 'mathbb/grek/gamma' 0x213D : glyph-proc @@ -42,7 +42,7 @@ glyph-block Letter-Greek-Lower-Gamma : begin foreach {ob ot} [items-of {{ 0 (cor - 1) } { (-1) (-1) }}] : include : dispiro g4 (xStart + ot * BBD) XH [widths.rhs.heading BBS Downward] - bezcontrols 0.33 0.17 1 0.62 6 important + bezControls 0.33 0.17 1 0.62 6 important flat (xMid + ob * BBD) 0 curl (xMid + ob * BBD) Descender [heading Downward] @@ -50,5 +50,5 @@ glyph-block Letter-Greek-Lower-Gamma : begin widths.rhs BBS flat RightSB XH [heading Downward] curl RightSB (XH * 0.9) [heading Downward] - quadcontrols 0 0.3 6 + quadControls 0 0.3 6 g4 xMid 0 [widths.rhs : BBS * 0.9] \ No newline at end of file diff --git a/font-src/glyphs/letter/greek/lower-nu.ptl b/font-src/glyphs/letter/greek/lower-nu.ptl index 456ac602d..368403e4d 100644 --- a/font-src/glyphs/letter/greek/lower-nu.ptl +++ b/font-src/glyphs/letter/greek/lower-nu.ptl @@ -14,11 +14,11 @@ glyph-block Letter-Greek-Lower-Nu : begin local xmid : Middle + HalfStroke * 0.75 include : dispiro g4 (SB + 0.4 * Stroke * HVContrast) (XH - O) [widths.rhs] - bezcontrols 0.33 0.2 1 0.76 6 important + bezControls 0.33 0.2 1 0.76 6 important g4.down.end xmid 0 [heading Downward] include : dispiro widths.rhs flat RightSB XH [heading Downward] curl RightSB (XH * 0.9) [heading Downward] - quadcontrols 0 0.3 6 + quadControls 0 0.3 6 g4 xmid 0 diff --git a/font-src/glyphs/letter/greek/lower-zeta.ptl b/font-src/glyphs/letter/greek/lower-zeta.ptl index 3dc0add19..5f525e15f 100644 --- a/font-src/glyphs/letter/greek/lower-zeta.ptl +++ b/font-src/glyphs/letter/greek/lower-zeta.ptl @@ -14,7 +14,7 @@ glyph-block Letter-Greek-Lower-Zeta : begin include : HBar SB (RightSB + O) (CAP - HalfStroke) include : dispiro g4 (RightSB + O) (CAP - Stroke) [widths.rhs] - bezcontrols 0.7 0.35 1 0.64 12 + bezControls 0.7 0.35 1 0.64 12 g4.down.mid (SB + Stroke * HVContrast) [mix 0 CAP (0.54 * SmallSmoothB / (SmallSmoothA + SmallSmoothB))] arcvh 16 g2 [mix SB RightSB 0.55] Stroke [heading Rightward] diff --git a/font-src/glyphs/letter/latin-ext/eth.ptl b/font-src/glyphs/letter/latin-ext/eth.ptl index 850dbdf88..30670d101 100644 --- a/font-src/glyphs/letter/latin-ext/eth.ptl +++ b/font-src/glyphs/letter/latin-ext/eth.ptl @@ -18,7 +18,7 @@ glyph-block Letter-Latin-Eth : begin include : dispiro widths.lhs g4.up.start (RightSB - OX) ymiddlea - quadcontrols 0 0.8 + quadControls 0 0.8 g4 (SB + Stroke * 1.1) CAP include : dispiro diff --git a/font-src/glyphs/letter/latin-ext/rams-horn.ptl b/font-src/glyphs/letter/latin-ext/rams-horn.ptl index 8cd063400..c54151bf4 100644 --- a/font-src/glyphs/letter/latin-ext/rams-horn.ptl +++ b/font-src/glyphs/letter/latin-ext/rams-horn.ptl @@ -17,13 +17,13 @@ glyph-block Letter-Latin-Rams-Horn : begin include : dispiro widths.center g4 (SB + HalfStroke * HVContrast + O) top [heading Downward] - quadcontrols 1 0.7 16 + quadControls 1 0.7 16 g4 (Middle + d - hf) (bottom + d * (1 - TanSlope * 0.5)) [widths hf hf] arcvh g4 (Middle + CorrectionOMidX * hf * 2) (bottom + hf) archv g4 (Middle - d + hf) (bottom + d * (1 + TanSlope * 0.5)) - quadcontrols 0 0.3 16 + quadControls 0 0.3 16 g4 (RightSB - HalfStroke * HVContrast - O) top [widths.heading HalfStroke HalfStroke Upward] create-glyph 'latingamma' 0x263 : glyph-proc diff --git a/font-src/glyphs/letter/latin-ext/upper-ae-oe.ptl b/font-src/glyphs/letter/latin-ext/upper-ae-oe.ptl index 2e790ddf7..3ba09ac5a 100644 --- a/font-src/glyphs/letter/latin-ext/upper-ae-oe.ptl +++ b/font-src/glyphs/letter/latin-ext/upper-ae-oe.ptl @@ -29,7 +29,7 @@ glyph-block Letter-Latin-Upper-AE-OE : begin widths.rhs sw flat df.leftSB 0 [heading Upward] curl df.leftSB (top * 0.1) [heading Upward] - quadcontrols 0 0.3 6 unimportant + quadControls 0 0.3 6 unimportant g4 (eleft - HalfStroke) top [widths.rhs fine] include : spiro-outline @@ -40,7 +40,7 @@ glyph-block Letter-Latin-Upper-AE-OE : begin WithTransform [Translate (-O) 0] : spiro-outline corner df.leftSB 0 [heading Upward] curl df.leftSB (top * 0.1) [heading Upward] - quadcontrols 0 0.3 6 unimportant + quadControls 0 0.3 6 unimportant corner (eleft - HalfStroke) top [widths.rhs fine] corner eleft top corner eleft 0 diff --git a/font-src/glyphs/letter/latin/k.ptl b/font-src/glyphs/letter/latin/k.ptl index d16033583..ac0fa637c 100644 --- a/font-src/glyphs/letter/latin/k.ptl +++ b/font-src/glyphs/letter/latin/k.ptl @@ -138,23 +138,23 @@ glyph-block Letter-Latin-K : begin if fHookTop dispiro straight.left.start (kshRight + [if [maskBit slab 1] SideJut 0] - TanSlope * stroke) (top - stroke) [widths.rhs stroke] - bezcontrols 0.5 0 0.5 0.65 8 : object : blend + bezControls 0.5 0 0.5 0.65 8 : object : blend function [t] : widths.rhs : mix stroke fine t g4 xAttach1 yAttach1 [widths.rhs fine] dispiro g4.down.start (kshRight) top [widths.rhs.heading (stroke * kDiag) Downward] - bezcontrols 0 0.2 0.5 0.65 8 + bezControls 0 0.2 0.5 0.65 8 g4 xAttach1 yAttach1 [widths.rhs fine] include : difference dispiro widths.center g4.up.start (kshRight - O - stroke / 2 * HVContrast) 0 [heading Upward] - quadcontrols 0 0.25 8 + quadControls 0 0.25 8 g4 xAttach2 yAttach2 [widths.center fine] if fHookTop spiro-outline straight.left.start (kshRight + [if [maskBit slab 1] SideJut 0] - TanSlope * stroke) (top - stroke + 0.1) - bezcontrols 0.5 0 0.5 0.65 8 + bezControls 0.5 0 0.5 0.65 8 corner (xAttach1 - 0.1) yAttach1 corner (-Width) yAttach1 corner (-Width) (top * 2) @@ -162,7 +162,7 @@ glyph-block Letter-Latin-K : begin corner (2 * Width) (top - stroke + 0.1) spiro-outline corner.down.start (kshRight - 1) top - bezcontrols 0 0.2 0.5 0.65 8 + bezControls 0 0.2 0.5 0.65 8 corner (kshLeft + stroke) (yAttach1 + 1) corner kshLeft 0 corner kshLeft top diff --git a/font-src/glyphs/letter/latin/lower-y.ptl b/font-src/glyphs/letter/latin/lower-y.ptl index 902c9ced9..9df27c5a7 100644 --- a/font-src/glyphs/letter/latin/lower-y.ptl +++ b/font-src/glyphs/letter/latin/lower-y.ptl @@ -60,7 +60,7 @@ glyph-block Letter-Latin-Lower-Y : begin : else : return : list flat x top [widths.heading hl hr Downward] curl x (top - ds) [widths.heading hl hr Downward] - quadcontrols 0 dpy1 16 + quadControls 0 dpy1 16 define [yBaseKnots top bottom shrink hooktop] : begin local {ds ds2} : CalcDS top bottom @@ -86,7 +86,7 @@ glyph-block Letter-Latin-Lower-Y : begin curl [Math.min (yrstrokel - slabysize - 0.1) (yrstrokel - Stroke - yBottomJut)] bottom true : list ConnectZ 1 - quadcontrols 1 (1 - dpy2) 16 + quadControls 1 (1 - dpy2) 16 flat yrstrokel (bottom + ds2) [widths.heading 0 Stroke Downward] curl yrstrokel bottom [widths.heading 0 Stroke Downward] diff --git a/font-src/glyphs/letter/latin/upper-r.ptl b/font-src/glyphs/letter/latin/upper-r.ptl index 371ccf3f9..923cdd7ed 100644 --- a/font-src/glyphs/letter/latin/upper-r.ptl +++ b/font-src/glyphs/letter/latin/upper-r.ptl @@ -42,7 +42,7 @@ glyph-block Letter-Latin-Upper-R : begin dispiro widths.center sw g4.up.start xRightBottom bottom [heading Upward] - quadcontrols 0 0.4 8 + quadControls 0 0.4 8 g4 left top if slab : begin include : RightwardBottomSerif right bottom (SideJut + Jut / 8) @@ -85,7 +85,7 @@ glyph-block Letter-Latin-Upper-R : begin dispiro widths.center sw g4.up.start xLeftBottom bottom [heading Upward] - quadcontrols 0 0.4 8 + quadControls 0 0.4 8 g4 right top if slab : begin include : LeftwardBottomSerif left bottom (SideJut + Jut / 8) diff --git a/font-src/glyphs/letter/latin/upper-y.ptl b/font-src/glyphs/letter/latin/upper-y.ptl index 7d0d860db..ac0b3622a 100644 --- a/font-src/glyphs/letter/latin/upper-y.ptl +++ b/font-src/glyphs/letter/latin/upper-y.ptl @@ -52,7 +52,7 @@ glyph-block Letter-Latin-Upper-Y : begin widths.rhs straight.left.start (RightSB + HookX / 3) (CAP - Stroke) g4 (RightSB - HookX / 3) (CAP - Hook) - quadcontrols 0.55 0.7 32 unimportant + quadControls 0.55 0.7 32 unimportant g4 (Middle + Stroke / 2 * HVContrast) cross diff --git a/font-src/glyphs/letter/latin/v.ptl b/font-src/glyphs/letter/latin/v.ptl index 41f1ccace..b6d503cf6 100644 --- a/font-src/glyphs/letter/latin/v.ptl +++ b/font-src/glyphs/letter/latin/v.ptl @@ -51,10 +51,10 @@ glyph-block Letter-Latin-V : begin include : spiro-outline flat vxStartL top curl vxStartL [VShapeTopFlat top] - quadcontrols 0 VCurviness 9 unimportant + quadControls 0 VCurviness 9 unimportant corner vxEndL 0 corner vxEndR 0 - quadcontrols 1 (1 - VCurviness) 9 unimportant + quadControls 1 (1 - VCurviness) 9 unimportant flat vxStartR [VShapeTopFlat top] curl vxStartR top @@ -90,13 +90,13 @@ glyph-block Letter-Latin-V : begin widths.lhs sw flat df.leftSB top [heading Downward] curl df.leftSB [VShapeTopFlat top] [heading Downward] - quadcontrols 0 VCurviness 9 unimportant + quadControls 0 VCurviness 9 unimportant g4 (df.middle - cornerHW) 0 [widths.lhs fine] include : tagged 'strokeUp' : dispiro widths.rhs sw flat df.rightSB top [heading Downward] curl df.rightSB [VShapeTopFlat top] [heading Downward] - quadcontrols 0 VCurviness 9 unimportant + quadControls 0 VCurviness 9 unimportant g4 (df.middle + cornerHW) 0 [widths.rhs fine] #bottom cap @@ -128,7 +128,7 @@ glyph-block Letter-Latin-V : begin widths.rhs straight.left.start (RightSB + HookX / 3) (top - Stroke) g4 (RightSB - HookX / 3) (top - HalfStroke - Hook) - quadcontrols 0.4 0.75 64 unimportant + quadControls 0.4 0.75 64 unimportant g4 (Middle + VCornerHalfWidth) 0 [widths.rhs VShapeFine] define [VSerifs top] : let [sf : SerifFrame top 0 SB RightSB] : begin diff --git a/font-src/glyphs/letter/latin/w.ptl b/font-src/glyphs/letter/latin/w.ptl index 436ee87a7..b912373fa 100644 --- a/font-src/glyphs/letter/latin/w.ptl +++ b/font-src/glyphs/letter/latin/w.ptl @@ -136,7 +136,7 @@ glyph-block Letter-Latin-W : begin widths.lhs dim.strokeOuter flat df.leftSB top [heading Downward] curl df.leftSB (top * (1 - dim.curlyStraightSegLength)) [heading Downward] - quadcontrols 0 0.3 6 unimportant + quadControls 0 0.3 6 unimportant g4 (dim.xBot1 - 0.5 * HVContrast * dim.wCoCr) 0 [widths.lhs.heading dim.fineOuterCr Downward] local kTopShift : match bodyType @@ -174,7 +174,7 @@ glyph-block Letter-Latin-W : begin widths.rhs dim.strokeOuter flat df.rightSB top [heading Downward] curl df.rightSB (top * (1 - dim.curlyStraightSegLength)) [heading Downward] - quadcontrols 0 0.3 6 unimportant + quadControls 0 0.3 6 unimportant g4 (dim.xBot2 + 0.5 * HVContrast * dim.wCoCr) 0 [widths.rhs.heading dim.fineOuterCr Downward] local oSlabPos : if bodyType (O * 2) 0 @@ -201,7 +201,7 @@ glyph-block Letter-Latin-W : begin include : dispiro widths.rhs dim.strokeOuter straight.down.start df.rightSB (top - Hook) [heading Downward] - quadcontrols 0 0.3 6 unimportant + quadControls 0 0.3 6 unimportant g4 (dim.xBot2 + 0.5 * HVContrast * dim.wCoCr) 0 [widths.rhs.heading dim.fineOuterCr Downward] include : VerticalHook (df.rightSB - 0.5 * dim.strokeOuter * HVContrast) (top - Hook) (HookX * 0.65) (-Hook + 0.5 * dim.strokeOuter) dim.strokeOuter diff --git a/font-src/glyphs/letter/latin/x.ptl b/font-src/glyphs/letter/latin/x.ptl index 1b6b570e5..4f5e0b464 100644 --- a/font-src/glyphs/letter/latin/x.ptl +++ b/font-src/glyphs/letter/latin/x.ptl @@ -37,7 +37,7 @@ glyph-block Letter-Latin-X : begin widths.center flat leftx lefty [heading [if (lefty < righty) Upward Downward]] curl leftx turnyleft [heading [if (lefty < righty) Upward Downward]] - quadcontrols 0 ((cyleft - turnyleft) / (straightyleft - turnyleft)) 24 + quadControls 0 ((cyleft - turnyleft) / (straightyleft - turnyleft)) 24 flat straightxleft straightyleft curl rightx righty diff --git a/font-src/glyphs/letter/shared.ptl b/font-src/glyphs/letter/shared.ptl index 552eddaf4..7827954f7 100644 --- a/font-src/glyphs/letter/shared.ptl +++ b/font-src/glyphs/letter/shared.ptl @@ -141,7 +141,7 @@ glyph-block Letter-Shared-Shapes : begin g4 right (wide + rinner - O / 2) [widths.heading 0 fine {.x (-HVContrast) .y ((wide - fine) / (wide + rinner * 2 - O))}] arcvh 8 g4.left.mid mid (wide + rinner * 2 - O) [heading Leftward] - quadcontrols ((x1 - mid) / (x2 - mid)) 0 8 + quadControls ((x1 - mid) / (x2 - mid)) 0 8 g4 x2 y2 glyph-block-export ShoulderMidKnotLhs diff --git a/font-src/glyphs/marks/index.ptl b/font-src/glyphs/marks/index.ptl index 41713b8b9..f52099f81 100644 --- a/font-src/glyphs/marks/index.ptl +++ b/font-src/glyphs/marks/index.ptl @@ -475,7 +475,7 @@ glyph-block Marks : begin include : dispiro widths.rhs : Math.min radius (markFine * [linreg 16 2 90 1.75 (markHalfStroke * 2)]) straight.down.start (markMiddle + radius) (aboveMarkTop - radius + commaOvershoot) - quadcontrols 0 0.6 + quadControls 0 0.6 g4 [mix markMiddle (markMiddle - radius) 0.2] (aboveMarkBot - radius - commaOvershoot2) include : ApparentTranslate 0 (DotRadius * 0.3) @@ -503,7 +503,7 @@ glyph-block Marks : begin include : dispiro widths.lhs : Math.min radius (markFine * [linreg 16 2 90 1.75 (markHalfStroke * 2)]) straight.down.start (markMiddle - radius) (aboveMarkTop - radius + commaOvershoot) - quadcontrols 0 0.6 + quadControls 0 0.6 g4 [mix markMiddle (markMiddle + radius) 0.2] (aboveMarkBot - radius - commaOvershoot2) include : ApparentTranslate 0 (DotRadius * 0.3) @@ -1170,7 +1170,7 @@ glyph-block Marks : begin g4 (startX - radius) (startY + radius) [widths.rhs (hornFine / 2)] archv g4 startX startY [widths.rhs hornFine] - quadcontrols 0 0.75 16 : object : blend : lambda [t] + quadControls 0 0.75 16 : object : blend : lambda [t] widths.rhs [mix hornFine hornStroke t] g4 (attX - overshootX - HalfStroke * HVContrast) (attY - overshootY - Stroke) [widths.rhs hornStroke] @@ -1353,9 +1353,9 @@ glyph-block Marks : begin include : dispiro widths.center (markHalfStroke * 2) g4 tieLeft aboveTieBottom - quadcontrols 0.5 1 + quadControls 0.5 1 g4.right.mid 0 aboveTieTop [heading Rightward] - quadcontrols 0.5 0 + quadControls 0.5 0 g4 tieRight aboveTieBottom create-glyph 'turnTieAbove' 0x35D : glyph-proc @@ -1365,9 +1365,9 @@ glyph-block Marks : begin include : dispiro widths.center (markHalfStroke * 2) g4 tieLeft aboveTieTop - quadcontrols 0.5 1 + quadControls 0.5 1 g4.right.mid 0 aboveTieBottom [heading Rightward] - quadcontrols 0.5 0 + quadControls 0.5 0 g4 tieRight aboveTieTop create-glyph 'tieBelow' 0x35C : glyph-proc diff --git a/font-src/glyphs/number/6.ptl b/font-src/glyphs/number/6.ptl index 53d0c0d97..cb267ba25 100644 --- a/font-src/glyphs/number/6.ptl +++ b/font-src/glyphs/number/6.ptl @@ -31,7 +31,7 @@ glyph-block Digits-Six : begin g4.left.mid (Middle + CorrectionOMidS) (O) archv g4.up.mid (SB + OX) (ymiddlea + Stroke * 0.3) [widths.rhs coFine] - quadcontrols 0 0.85 + quadControls 0 0.85 g4 ([mix SB RightSB 0.85] - 0.25 * Stroke * HVContrast) (charTop - O) [widths.rhs] glyph-block-export ClosedContourNineShape diff --git a/font-src/glyphs/symbol/letter.ptl b/font-src/glyphs/symbol/letter.ptl index 26f9b2af3..b7d959f53 100644 --- a/font-src/glyphs/symbol/letter.ptl +++ b/font-src/glyphs/symbol/letter.ptl @@ -95,7 +95,7 @@ glyph-block Symbol-Letter : begin include : dispiro widths.center fine g2 left [mix 0 CAP 0.33] - quadcontrols 1 0.6 + quadControls 1 0.6 g2 right [mix 0 CAP 0.8] arcvh g2 [mix middle right 0.5] (CAP - O - fine / 2) diff --git a/font-src/glyphs/symbol/pictograph/heart.ptl b/font-src/glyphs/symbol/pictograph/heart.ptl index 8f1094c56..87ad4e1e2 100644 --- a/font-src/glyphs/symbol/pictograph/heart.ptl +++ b/font-src/glyphs/symbol/pictograph/heart.ptl @@ -17,7 +17,7 @@ glyph-block Symbol-Pictograph-Heart : begin local y3 : heart.mixY 0.75 return : spiro-outline corner heart.xMid (heart.bottom + sw * tip) - quadcontrols 1 (2 / 3) + quadControls 1 (2 / 3) g4 (heart.right - O - sw) y2 arcvh g4 [heart.mixXMidRight 0.5] (heart.top - sw * tip / 1.75) @@ -31,7 +31,7 @@ glyph-block Symbol-Pictograph-Heart : begin g4 [heart.mixXMidLeft 0.5] (heart.top - sw * tip / 1.75) archv g4 (heart.left + O + sw) y2 - quadcontrols 0 (1 / 3) + quadControls 0 (1 / 3) close for-width-kinds WideWidth1 : begin diff --git a/font-src/glyphs/symbol/punctuation/brackets.ptl b/font-src/glyphs/symbol/punctuation/brackets.ptl index e57022998..9105ac449 100644 --- a/font-src/glyphs/symbol/punctuation/brackets.ptl +++ b/font-src/glyphs/symbol/punctuation/brackets.ptl @@ -25,15 +25,15 @@ glyph-block Symbol-Punctuation-Brackets : begin define [ParenShape] : params [sw [dp DesignParameters]] : let [dim : ParenDim 0 dp] : dispiro widths.lhs sw g4 dim.inside dim.top - quadcontrols 1 (1 - dp.parenCurliness) + quadControls 1 (1 - dp.parenCurliness) g4 dim.outside dim.mid - quadcontrols 0 dp.parenCurliness + quadControls 0 dp.parenCurliness g4 dim.inside dim.bottom define [ParenUpperShape sw] : let [dim : ParenDim 0] : dispiro widths.lhs sw g4 dim.inside dim.top - quadcontrols 1 (1 - DesignParameters.parenCurliness) + quadControls 1 (1 - DesignParameters.parenCurliness) g4.down.end dim.outside MosaicBottom [heading Downward] define [ParenExtensionShape sw] : let [dim : ParenDim 0] : dispiro @@ -44,14 +44,14 @@ glyph-block Symbol-Punctuation-Brackets : begin define [ParenLowerShape sw] : let [dim : ParenDim 0] : dispiro widths.lhs sw g4.down.start dim.outside MosaicTop [heading Downward] - quadcontrols 0 DesignParameters.parenCurliness + quadControls 0 DesignParameters.parenCurliness g4 dim.inside dim.bottom define [ParenShapeMask delta] : let [dim : ParenDim delta] : spiro-outline corner dim.inside dim.top - quadcontrols 1 (1 - DesignParameters.parenCurliness) + quadControls 1 (1 - DesignParameters.parenCurliness) g4 dim.outside dim.mid - quadcontrols 0 DesignParameters.parenCurliness + quadControls 0 DesignParameters.parenCurliness corner dim.inside dim.bottom create-glyph'parenLeft.normal' : glyph-proc diff --git a/font-src/glyphs/symbol/punctuation/guillemet.ptl b/font-src/glyphs/symbol/punctuation/guillemet.ptl index ef606a845..514f08fca 100644 --- a/font-src/glyphs/symbol/punctuation/guillemet.ptl +++ b/font-src/glyphs/symbol/punctuation/guillemet.ptl @@ -21,13 +21,13 @@ glyph-block Symbol-Punctuation-Guillemet : begin include : dispiro widths.center sw g4 [mix Middle RightSB extension] top - quadcontrols 0.4 0.75 + quadControls 0.4 0.75 g4 [mix Middle SB extension] [mix top bot 0.5] [widths.center.heading (cor * sw) Leftward] include : dispiro widths.center (sw * cor) g4 [mix Middle SB extension] [mix top bot 0.5] [heading Rightward] - quadcontrols (1 - 0.4) (1 - 0.75) + quadControls (1 - 0.4) (1 - 0.75) g4 [mix Middle RightSB extension] bot [widths.center sw] include : Translate (-(RightSB - SB) * 0.05) 0 diff --git a/font-src/glyphs/symbol/punctuation/small.ptl b/font-src/glyphs/symbol/punctuation/small.ptl index 7a5c83b17..19e2a25a8 100644 --- a/font-src/glyphs/symbol/punctuation/small.ptl +++ b/font-src/glyphs/symbol/punctuation/small.ptl @@ -60,7 +60,7 @@ glyph-block Symbol-Punctuation-Small : begin g4 0 (r + ro) archv g4 ro r [widths.rhs sw] - quadcontrols (0 + TanSlope / 2) (0.5 - TanSlope * r / Descender) 12 + quadControls (0 + TanSlope / 2) (0.5 - TanSlope * r / Descender) 12 g4 (-commaOverflow + Descender * TanSlope) Descender [widths.rhs swEnd] create-glyph 'comma.square' : glyph-proc @@ -76,7 +76,7 @@ glyph-block Symbol-Punctuation-Small : begin SquareAt 0 r r dispiro straight.down.mid r 0 [widths.rhs sw] - quadcontrols (0 + TanSlope / 2) (0.5 - TanSlope * r / Descender) 12 + quadControls (0 + TanSlope / 2) (0.5 - TanSlope * r / Descender) 12 g4 (-commaOverflow + Descender * TanSlope) Descender [widths.rhs swEnd] @@ -111,7 +111,7 @@ glyph-block Symbol-Punctuation-Small : begin g4 0 (r + ro) archv g4 (-ro) r [widths.lhs sw] - quadcontrols (0 - TanSlope / 2) (0.5 - TanSlope * r / Descender) 12 + quadControls (0 - TanSlope / 2) (0.5 - TanSlope * r / Descender) 12 g4 (commaOverflow + Descender * TanSlope) Descender [widths.lhs swEnd] create-glyph 'invertComma.square' : glyph-proc @@ -127,7 +127,7 @@ glyph-block Symbol-Punctuation-Small : begin SquareAt 0 r r dispiro straight.down.mid (-r) 0 [widths.lhs sw] - quadcontrols (0 - TanSlope / 2) (0.5 - TanSlope * r / Descender) 12 + quadControls (0 - TanSlope / 2) (0.5 - TanSlope * r / Descender) 12 g4 (commaOverflow + Descender * TanSlope) Descender [widths.lhs swEnd] select-variant 'comma' ',' (follow -- 'punctuationDot') diff --git a/font-src/glyphs/symbol/punctuation/ties.ptl b/font-src/glyphs/symbol/punctuation/ties.ptl index 67666a36f..2e2bff224 100644 --- a/font-src/glyphs/symbol/punctuation/ties.ptl +++ b/font-src/glyphs/symbol/punctuation/ties.ptl @@ -13,9 +13,9 @@ glyph-block Symbol-Punctuation-Ties : begin define [TieShape y k] : dispiro widths.[if (k>0) 'rhs' 'lhs'] OperatorStroke g4 (SB + OX) y - quadcontrols 0.5 1 + quadControls 0.5 1 g4.right.mid Middle (y - k * Descender / 3) [heading Rightward] - quadcontrols 0.5 0 + quadControls 0.5 0 g4 (RightSB - OX) y create-glyph "overTie" 0x2040 : TieShape CAP 1 diff --git a/font-src/kits/boole-kit.js b/font-src/kits/boole-kit.js new file mode 100644 index 000000000..e38c08df5 --- /dev/null +++ b/font-src/kits/boole-kit.js @@ -0,0 +1,34 @@ +"use strict"; + +const TypoGeom = require("typo-geom"); +const { BooleanGeometry, TransformedGeometry } = require("../support/geometry"); + +exports.SetupBuilders = function ({ Glyph, GlobalTransform }) { + function impl(operator, operands) { + return function () { + const operandGeometries = []; + const forwardGizmo = this.gizmo || GlobalTransform; + const backwardGizmo = forwardGizmo.inverse(); + for (const operand of 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 { + union: union, + intersection: intersection, + difference: difference + }; +}; diff --git a/font-src/kits/boole-kit.ptl b/font-src/kits/boole-kit.ptl deleted file mode 100644 index 7a39501ba..000000000 --- a/font-src/kits/boole-kit.ptl +++ /dev/null @@ -1,25 +0,0 @@ -import 'typo-geom' as TypoGeom -import '../support/curve-util' as CurveUtil -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 forwardGizmo - g1.include operand - operandGeometries.push : new TransformedGeometry g1.geometry backwardGizmo - - 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] - define [difference] : impl TypoGeom.Boolean.ClipType.ctDifference [{}.slice.call arguments 0] - - return [object union intersection difference] diff --git a/font-src/kits/spiro-kit.js b/font-src/kits/spiro-kit.js new file mode 100644 index 000000000..f1d7e59ae --- /dev/null +++ b/font-src/kits/spiro-kit.js @@ -0,0 +1,354 @@ +"use strict"; + +const SpiroJs = require("spiro"); +const CurveUtil = require("../support/curve-util"); +const Transform = require("../support/transform"); +const { SpiroExpansionContext1, SpiroExpansionContext2 } = require("../support/spiro-expand"); +const { fallback, mix, bez2, bez3 } = require("../support/utils"); +const { SpiroGeometry, CombineGeometry } = require("../support/geometry"); + +exports.SetupBuilders = function (bindings) { + const { Contrast, GlobalTransform, Stroke, Superness } = bindings; + const g4 = (x, y, f) => ({ x, y, type: "g4", af: f }); + const g2 = (x, y, f) => ({ x, y, type: "g2", af: f }); + const corner = (x, y, f) => ({ x, y, type: "corner", af: f }); + const flat = (x, y, f) => ({ x, y, type: "left", af: f }); + const curl = (x, y, f) => ({ x, y, type: "right", af: f }); + const close = f => ({ type: "close", af: f }); + const end = f => ({ type: "end", af: f }); + + const straight = { l: flat, r: curl }; + { + let directions = [ + { name: "up", x: 0, y: 1 }, + { name: "down", x: 0, y: -1 }, + { name: "left", x: -1, y: 0 }, + { name: "right", x: 1, y: 0 } + ]; + let adhesions = [ + { name: "start", l: 0, r: 0.01 }, + { name: "mid", l: -0.005, r: 0.005 }, + { name: "end", l: -0.01, r: 0 } + ]; + let knotTypes = [ + [g4, g4, g4], + [g2, g2, g2], + [corner, corner, corner], + [straight, flat, curl] + ]; + for (const [sink, kl, kr] of knotTypes) { + for (const d of directions) { + sink[d.name] = {}; + for (const a of adhesions) { + sink[d.name][a.name] = (x, y, af) => [ + kl(x + d.x * a.l, y + d.y * a.l, af), + kr(x + d.x * a.r, y + d.y * a.r, af) + ]; + } + } + } + } + + function widths(l, r) { + return function () { + return this.setWidth ? this.setWidth(l, r) : void 0; + }; + } + widths.lhs = function (w) { + return widths(fallback(w, Stroke), 0); + }; + widths.rhs = function (w) { + return widths(0, fallback(w, Stroke)); + }; + widths.center = function (w) { + return widths(fallback(w, Stroke) / 2, fallback(w, Stroke) / 2); + }; + + function heading(d) { + return function () { + return this.headsTo ? this.headsTo(d) : void 0; + }; + } + widths.heading = function (l, r, d) { + return function () { + if (this.setWidth) this.setWidth(l, r); + return this.headsTo ? this.headsTo(d) : void 0; + }; + }; + widths.lhs.heading = function (w, d) { + return function () { + if (this.setWidth) this.setWidth(fallback(w, Stroke), 0); + return this.headsTo ? this.headsTo(d) : void 0; + }; + }; + widths.rhs.heading = function (w, d) { + return function () { + if (this.setWidth) this.setWidth(0, fallback(w, Stroke)); + return this.headsTo ? this.headsTo(d) : void 0; + }; + }; + widths.center.heading = function (w, d) { + return function () { + if (this.setWidth) this.setWidth(fallback(w, Stroke) / 2, fallback(w, Stroke) / 2); + return this.headsTo ? this.headsTo(d) : void 0; + }; + }; + + function disableContrast() { + return function () { + return (this.contrast = 1); + }; + } + function unimportant() { + return this.setUnimportant ? this.setUnimportant() : void 0; + } + function important() { + return void 0; + } + function afInterpolate(before, after, args) { + return g4( + mix(before.x, after.x, args.rx), + mix(before.y, after.y, args.ry), + fallback(args.raf, unimportant) + ); + } + function afInterpolateG2(before, after, args) { + return g2( + mix(before.x, after.x, args.rx), + mix(before.y, after.y, args.ry), + fallback(args.raf, unimportant) + ); + } + function afInterpolateThem(before, after, args) { + let innerKnots = []; + for (const [rx, ry, rt] of args.rs) { + innerKnots.push( + fallback(args.ty, g2)( + mix(before.x, after.x, rx), + mix(before.y, after.y, ry), + args.raf && args.raf.blend && rt !== void 0 + ? args.raf.blend(rt) + : args.raf + ? args.raf + : unimportant + ) + ); + } + return innerKnots; + } + function afInterpolateSNeck(before, after, args) { + return [ + g2( + mix(before.x, after.x, 1 / 2 - args.px / 6), + mix(before.y, after.y, 1 / 2 - args.py / 6), + widths(args.sw * args.ps, args.sw * (1 - args.ps)) + ), + g2( + mix(before.x, after.x, 1 / 2 + args.px / 6), + mix(before.y, after.y, 1 / 2 + args.py / 6), + widths(args.sw * (1 - args.ps), args.sw * args.ps) + ) + ]; + } + function alsoThru(rx, ry, raf) { + return { type: "interpolate", rx, ry, raf, af: afInterpolate }; + } + alsoThru.g2 = function (rx, ry, raf) { + return { type: "interpolate", rx, ry, raf, af: afInterpolateG2 }; + }; + alsoThru.sNeck = function (px, py, sw, ps) { + return { type: "interpolate", px, py, sw, ps, af: afInterpolateSNeck }; + }; + function alsoThruThem(es, raf, ty) { + return { type: "interpolate", rs: es, raf, ty, af: afInterpolateThem }; + } + function bezControlsImpl(x1, y1, x2, y2, samples, raf, ty) { + let rs = []; + for (let j = 1; j < samples; j = j + 1) + rs.push([ + bez3(0, x1, x2, 1, j / samples), + bez3(0, y1, y2, 1, j / samples), + j / samples + ]); + return alsoThruThem(rs, raf); + } + function bezControls(x1, y1, x2, y2, _samples, raf) { + return bezControlsImpl(x1, y1, x2, y2, fallback(_samples, 3), raf); + } + function quadControls(x1, y1, _samples, raf) { + return bezControlsImpl( + (x1 * 2) / 3, + (y1 * 2) / 3, + mix(1, x1, 2 / 3), + mix(1, y1, 2 / 3), + fallback(_samples, 3), + raf + ); + } + + let DEFAULT_STEPS = 6; + + let [buildHV, buildVH] = (function (cache) { + function build(samples, _superness) { + const superness = fallback(_superness, Superness); + let hv = []; + let vh = []; + for (let j = 1; j < samples; j = j + 1) { + const theta = (((j + 1) / (samples + 2)) * Math.PI) / 2; + const c = Math.pow(Math.cos(theta), 2 / superness); + const s = Math.pow(Math.sin(theta), 2 / superness); + hv.push([s, 1 - c]); + vh.push([1 - c, s]); + } + return { hv, vh: vh }; + } + function buildHVImpl(samples, _superness) { + if (_superness) return build(samples, _superness).hv; + if (!cache[samples]) cache[samples] = build(samples, _superness); + return cache[samples].hv; + } + function buildVHImpl(samples, _superness) { + if (_superness) return build(samples, _superness).vh; + if (!cache[samples]) cache[samples] = build(samples, _superness); + return cache[samples].vh; + } + return [buildHVImpl, buildVHImpl]; + })([]); + + function archv(samples, superness) { + return alsoThruThem(buildHV(fallback(samples, DEFAULT_STEPS), superness)); + } + archv.superness = function (s) { + return archv(DEFAULT_STEPS, s); + }; + function arcvh(samples, superness) { + return alsoThruThem(buildVH(fallback(samples, DEFAULT_STEPS), superness)); + } + arcvh.superness = function (s) { + return arcvh(DEFAULT_STEPS, s); + }; + function complexThru(...a) { + return { + type: "interpolate", + af: function (before, after, args) { + let ks = []; + for (const knot of a) ks.push(knot.af.call(this, before, after, knot)); + return ks; + } + }; + } + 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].af.call(s, 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 }; + } + function iterateNormals(s, closed) { + let knotsP2 = s.getPass2Knots(closed, fallback(s.contrast, Contrast)); + let s2 = new SpiroExpansionContext2(s.controlKnots, s.gizmo); + return SpiroJs.spiroToArcsOnContext(knotsP2, closed, s2); + } + function dispiro(...args) { + return function () { + let s = new SpiroExpansionContext1(this.gizmo || GlobalTransform); + let { knots, closed } = prepareSpiroKnots([].slice.call(args, 0), s); + for (const knot of knots) { + const ty = knot.type; + const af = knot.af; + knot.af = function () { + this.setType(ty); + return af ? af.apply(this, args) : void 0; + }; + } + + SpiroJs.spiroToArcsOnContext(knots, closed, s); + iterateNormals(s, closed); + iterateNormals(s, closed); + const { lhs, rhs } = s.expand(fallback(s.contrast, Contrast)); + + if (closed) { + this.includeGeometry( + new CombineGeometry([ + new SpiroGeometry(lhs.slice(0, -1), closed, Transform.Id()), + new SpiroGeometry(rhs.reverse().slice(0, -1), closed, Transform.Id()) + ]) + ); + } else { + lhs[0].type = lhs[lhs.length - 1].type = "corner"; + rhs[0].type = rhs[rhs.length - 1].type = "corner"; + const allKnots = lhs.concat(rhs.reverse()); + this.includeGeometry(new SpiroGeometry(allKnots, true, Transform.Id())); + } + return { knots, lhsKnots: lhs, rhsKnots: rhs }; + }; + } + + function spiroOutline(...args) { + return function () { + const gizmo = this.gizmo || GlobalTransform; + const g = new CurveUtil.BezToContoursSink(gizmo); + const { knots, closed } = prepareSpiroKnots(args, g); + return this.includeGeometry(new SpiroGeometry(knots, closed, gizmo)); + }; + } + return { + g4, + g2, + corner, + flat, + curl, + close, + end, + straight, + widths, + heading, + "disable-contrast": disableContrast, + unimportant, + important, + alsoThru, + alsoThruThem, + bezControls, + quadControls, + archv, + arcvh, + complexThru, + dispiro, + "spiro-outline": spiroOutline + }; +}; diff --git a/font-src/kits/spiro-kit.ptl b/font-src/kits/spiro-kit.ptl deleted file mode 100644 index 0533b001a..000000000 --- a/font-src/kits/spiro-kit.ptl +++ /dev/null @@ -1,226 +0,0 @@ -import 'spiro' as SpiroJs -import '../support/curve-util' as CurveUtil -import '../support/transform' as Transform -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 - - define [g4 x y f] {.x x .y y .type 'g4' .af f} - define [g2 x y f] {.x x .y y .type 'g2' .af f} - define [corner x y f] {.x x .y y .type 'corner' .af f} - define [flat x y f] {.x x .y y .type 'left' .af f} - define [curl x y f] {.x x .y y .type 'right' .af f} - define [close f] {.type 'close' .af f} - define [end f] {.type 'end' .af f} - - define straight {.l flat .r curl} - - #directional bi-knots - let - directions : list - * {.name 'up' .x 0 .y 1} - * {.name 'down' .x 0 .y (-1)} - * {.name 'left' .x (-1) .y 0} - * {.name 'right' .x 1 .y 0} - adhensions : list - * {.name 'start' .l 0 .r 0.01} - * {.name 'mid' .l (-0.005) .r 0.005} - * {.name 'end' .l (-0.01) .r 0} - knotTypes : list - * {g4 g4 g4} - * {g2 g2 g2} - * {corner corner corner} - * {straight flat curl} - foreach [_kt : items-of knotTypes] : let [{ sink kl kr } _kt] : begin - foreach [_d : items-of directions] : let [d _d] : begin - set sink.(d.name) {.} - foreach [adh : items-of adhensions] : let [a adh] : begin - set sink.(d.name).(a.name) : lambda [x y af] : list - kl (x + d.x * a.l) (y + d.y * a.l) af - kr (x + d.x * a.r) (y + d.y * a.r) af - - # Aux functions - define [widths l r] : lambda [] : if this.setWidth : this.setWidth l r - define [widths.lhs w] : widths [fallback w Stroke] 0 - define [widths.rhs w] : widths 0 [fallback w Stroke] - define [widths.center w] : widths ([fallback w Stroke] / 2) ([fallback w Stroke] / 2) - - # Gizmo handler - define [disable-contrast] : lambda [] : set this.contrast 1 - - define [heading d] : lambda [] : if (this.headsTo) : this.headsTo d - define [widths.heading l r d] : lambda [] : begin - if this.setWidth : this.setWidth l r - if this.headsTo : this.headsTo d - define [widths.lhs.heading w d] : lambda [] : begin - if this.setWidth : this.setWidth [fallback w Stroke] 0 - if this.headsTo : this.headsTo d - define [widths.rhs.heading w d] : lambda [] : begin - if this.setWidth : this.setWidth 0 [fallback w Stroke] - if this.headsTo : this.headsTo d - define [widths.center.heading w d] : lambda [] : begin - if this.setWidth : this.setWidth ([fallback w Stroke] / 2) ([fallback w Stroke] / 2) - if this.headsTo : this.headsTo d - define [unimportant] : if this.setUnimportant : this.setUnimportant - define [important] nothing - - # Interpolation pesudoknots - define [afInterpolate before after args] : g4 - mix before.x after.x args.rx - mix before.y after.y args.ry - fallback args.raf unimportant - define [afInterpolateG2 before after args] : g2 - mix before.x after.x args.rx - mix before.y after.y args.ry - fallback args.raf unimportant - define [afInterpolateThem before after args] : begin - local innerKnots {} - foreach {rx ry rt} [items-of args.rs] : innerKnots.push : [fallback args.ty g2] - mix before.x after.x rx - mix before.y after.y ry - piecewise - (args.raf && args.raf.blend && (rt != nothing)) [args.raf.blend rt] - args.raf args.raf - true unimportant - return innerKnots - define [afInterpolateSNeck before after args] : list - g2 - mix before.x after.x (1 / 2 - args.px / 6) - mix before.y after.y (1 / 2 - args.py / 6) - widths (args.sw * args.ps) (args.sw * (1 - args.ps)) - g2 - mix before.x after.x (1 / 2 + args.px / 6) - mix before.y after.y (1 / 2 + args.py / 6) - widths (args.sw * (1 - args.ps)) (args.sw * args.ps) - - define [alsoThru rx ry raf] {.type 'interpolate' .rx rx .ry ry .raf raf .af afInterpolate} - set alsoThru.g2 : lambda [rx ry raf] {.type 'interpolate' .rx rx .ry ry .raf raf .af afInterpolateG2} - set alsoThru.sNeck : lambda [px py sw ps] {.type 'interpolate' .px px .py py .sw sw .ps ps .af afInterpolateSNeck} - define [alsoThruThem rs raf ty] {.type 'interpolate' .rs rs .raf raf .ty ty .af afInterpolateThem} - define [bezControlsImpl x1 y1 x2 y2 samples raf ty] : begin - local rs {} - foreach j [range 1 samples] : rs.push : list - bez3 0 x1 x2 1 (j / samples) - bez3 0 y1 y2 1 (j / samples) - j / samples - alsoThruThem rs raf - define [bezcontrols x1 y1 x2 y2 _samples raf] - bezControlsImpl x1 y1 x2 y2 [fallback _samples 3] raf - define [quadcontrols x1 y1 _samples raf] - bezControlsImpl (x1 * 2 / 3) (y1 * 2 / 3) [mix 1 x1 (2 / 3)] [mix 1 y1 (2 / 3)] [fallback _samples 3] raf - - define DEFAULT_STEPS 6 - define {jhv, jvh} : let [cache {}] : begin - local [build samples _superness] : begin - local superness : fallback _superness args.superness - local hv {} - local vh {} - foreach [j : range 1 samples] : begin - local theta : (j + 1) / (samples + 2) * Math.PI / 2 - local c : Math.pow [Math.cos theta] (2 / superness) - local s : Math.pow [Math.sin theta] (2 / superness) - hv.push { s (1 - c) } - vh.push { (1 - c) s } - return {.hv hv .vh vh} - local [hv samples _superness] : begin - if (_superness) : return [build samples _superness].hv - if (!cache.(samples)) : set cache.(samples) : build samples _superness - return cache.(samples).hv - local [vh samples _superness] : begin - if (_superness) : return [build samples _superness].vh - if (!cache.(samples)) : set cache.(samples) : build samples _superness - return cache.(samples).vh - list hv vh - define [archv samples superness] : alsoThruThem [jhv [fallback samples DEFAULT_STEPS] superness] - set archv.superness : lambda [s] : archv DEFAULT_STEPS s - define [arcvh samples superness] : alsoThruThem [jvh [fallback samples DEFAULT_STEPS] superness] - set arcvh.superness : lambda [s] : arcvh DEFAULT_STEPS s - - define [complexThru] : begin - local a : {}.slice.call arguments - return {.type 'interpolate' .af [lambda [before after args] : begin \\ - local ks {} - foreach knot [items-of a] : ks.push [knot.af.call this before after knot] - return ks - ]} - - - define [flattenImpl sink knots] : begin - foreach p [items-of knots] : piecewise - (p <@ Array) : flattenImpl sink p - true : sink.push p - define [nCyclic p n] : (p + n + n) % n - define [flatten s knots0] : begin - local knots : list - flattenImpl knots knots0 - - # Unwrap interpolation knots - local unwrapped false - foreach j [range 0 knots.length] : if (knots.(j) && knots.(j).type === 'interpolate') : begin - local kBefore knots.[nCyclic (j - 1) knots.length] - local kAfter knots.[nCyclic (j + 1) knots.length] - set knots.(j) : knots.(j).af.call s kBefore kAfter knots.(j) - set unwrapped true - - if unwrapped : return : flatten s knots - return knots - - define [dropTailKnot knots] : begin - define last knots.(knots.length - 1) - if (last && (last.type === 'close' || last.type === 'end')) : begin - set knots.length : knots.length - 1 - return : last.type === 'close' - - define [prepareSpiroKnots _knots s] : begin - local knots _knots - while (knots.0 && knots.0 <@ Function) : begin [knots.0.call s] [knots.splice 0 1] - define closed : dropTailKnot knots - set knots : flatten s knots - return { .knots knots .closed closed } - - define [iterateNormals s closed] : begin - local knotsP2 : s.getPass2Knots closed [fallback s.contrast Contrast] - local s2 : new SpiroExpansionContext2 s.controlKnots s.gizmo - SpiroJs.spiroToArcsOnContext knotsP2 closed s2 - - define [dispiro] : let [args : {}.slice.call arguments 0] : lambda [] : begin - define CLOSED true - local s : new SpiroExpansionContext1 (this.gizmo || GlobalTransform) - local { .knots knots .closed closed } : prepareSpiroKnots [{}.slice.call args 0] s - foreach knot [items-of knots] : let [ty knot.type] [af knot.af] : begin - set knot.af : lambda [] : begin - this.setType ty - if af : af.apply this args - - SpiroJs.spiroToArcsOnContext knots closed s - iterateNormals s closed - iterateNormals s closed - local {.lhs lhs .rhs rhs} : s.expand [fallback s.contrast Contrast] - - if closed : then - 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 - lhs.0.type = lhs.(lhs.length - 1).type = 'corner' - rhs.0.type = rhs.(rhs.length - 1).type = 'corner' - define allKnots : lhs.concat : rhs.reverse - this.includeGeometry : new SpiroGeometry allKnots CLOSED [Transform.Id] - - return { .knots knots .lhsKnots lhs .rhsKnots rhs } - - define [spiro-outline] : let [k : {}.slice.call arguments 0] : lambda [] : begin - local gizmo : this.gizmo || GlobalTransform - local g : new CurveUtil.BezToContoursSink gizmo - local { .knots knots .closed closed } : prepareSpiroKnots k g - this.includeGeometry : new SpiroGeometry knots closed gizmo - - return [object - g4 g2 corner flat curl close end straight - widths disable-contrast heading unimportant important - alsoThru alsoThruThem bezcontrols quadcontrols archv arcvh complexThru - dispiro spiro-outline] diff --git a/font-src/meta/macros.ptl b/font-src/meta/macros.ptl index ab9bafe6c..f75854c10 100644 --- a/font-src/meta/macros.ptl +++ b/font-src/meta/macros.ptl @@ -221,8 +221,8 @@ define-macro glyph-block : syntax-rules adviceGlottalStopSmooth shoulderMidSlope StrokeWidthBlend SmoothAOf SmoothBOf SmoothAdjust MidJutSide MidJutCenter compositeBaseAnchors YSmoothMidR YSmoothMidL] define spiroFnImports `[g4 g2 corner flat curl close end straight widths - disable-contrast heading unimportant important alsoThru alsoThruThem bezcontrols - quadcontrols archv arcvh complexThru dispiro spiro-outline] + disable-contrast heading unimportant important alsoThru alsoThruThem bezControls + quadControls archv arcvh complexThru dispiro spiro-outline] define booleFnImports `[union intersection difference] dirty `[$GlyphBlocks$.push : lambda [$Capture_Ext$] : begin \\