Migrate kits to JS

This commit is contained in:
be5invis 2021-07-07 20:08:06 -07:00
parent 774f2a457f
commit dad21a56ee
32 changed files with 455 additions and 319 deletions

1
.gitignore vendored
View file

@ -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

View file

@ -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 {

View file

@ -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'

View file

@ -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

View file

@ -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)

View file

@ -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]

View file

@ -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

View file

@ -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]

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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]

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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')

View file

@ -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

View file

@ -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
};
};

View file

@ -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]

354
font-src/kits/spiro-kit.js Normal file
View file

@ -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
};
};

View file

@ -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]

View file

@ -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 \\