From dc9d7f3ac25d605de250ffee49069061c80a2761 Mon Sep 17 00:00:00 2001 From: Belleve Date: Thu, 1 Aug 2024 00:30:22 -1000 Subject: [PATCH] Add fraktur A and K (#2450) --- changes/31.1.0.md | 2 + .../font-glyphs/src/letter-like/fraktur.ptl | 405 +----------------- .../src/letter-like/fraktur/common.ptl | 140 ++++++ .../src/letter-like/fraktur/lower-e.ptl | 27 ++ .../src/letter-like/fraktur/lower-o.ptl | 25 ++ .../src/letter-like/fraktur/upper-a.ptl | 35 ++ .../src/letter-like/fraktur/upper-ceg.ptl | 92 ++++ .../src/letter-like/fraktur/upper-hkr.ptl | 102 +++++ .../src/letter-like/fraktur/upper-ij.ptl | 46 ++ .../src/letter-like/fraktur/upper-z.ptl | 36 ++ packages/font-glyphs/src/meta/macros.ptl | 2 +- .../font-kits/src/derived-coordinates.mjs | 53 ++- packages/geometry/src/box.mjs | 14 + 13 files changed, 584 insertions(+), 395 deletions(-) create mode 100644 packages/font-glyphs/src/letter-like/fraktur/common.ptl create mode 100644 packages/font-glyphs/src/letter-like/fraktur/lower-e.ptl create mode 100644 packages/font-glyphs/src/letter-like/fraktur/lower-o.ptl create mode 100644 packages/font-glyphs/src/letter-like/fraktur/upper-a.ptl create mode 100644 packages/font-glyphs/src/letter-like/fraktur/upper-ceg.ptl create mode 100644 packages/font-glyphs/src/letter-like/fraktur/upper-hkr.ptl create mode 100644 packages/font-glyphs/src/letter-like/fraktur/upper-ij.ptl create mode 100644 packages/font-glyphs/src/letter-like/fraktur/upper-z.ptl diff --git a/changes/31.1.0.md b/changes/31.1.0.md index 237f0389e..29bcbff80 100644 --- a/changes/31.1.0.md +++ b/changes/31.1.0.md @@ -10,8 +10,10 @@ - LATIN SMALL LETTER BLACKLETTER E (`U+AB32`) (#2443). - LATIN SMALL LETTER BLACKLETTER O (`U+AB3D`) (#2443). - LATIN SMALL LETTER BLACKLETTER O WITH STROKE (`U+AB3E`) (#2443). + - MATHEMATICAL FRAKTUR CAPITAL A (`U+1D504`) (#444). - MATHEMATICAL FRAKTUR CAPITAL E (`U+1D508`) (#444). - MATHEMATICAL FRAKTUR CAPITAL G (`U+1D50A`) (#444). - MATHEMATICAL FRAKTUR CAPITAL J (`U+1D50D`) (#444). + - MATHEMATICAL FRAKTUR CAPITAL K (`U+1D50E`) (#444). - MATHEMATICAL FRAKTUR SMALL E (`U+1D522`) (#444). - MATHEMATICAL FRAKTUR SMALL O (`U+1D52C`) (#444). diff --git a/packages/font-glyphs/src/letter-like/fraktur.ptl b/packages/font-glyphs/src/letter-like/fraktur.ptl index e7e8a8b5f..177ac9c9b 100644 --- a/packages/font-glyphs/src/letter-like/fraktur.ptl +++ b/packages/font-glyphs/src/letter-like/fraktur.ptl @@ -1,395 +1,14 @@ -###### Fraktur letterforms -### -### This file is used to define the letterforms of the Fraktur style. -### For simplicity, the letters here will *NOT* support any variants. -### - $$include '../meta/macros.ptl' -import [mix fallback] from "@iosevka/util" -import [SpiroPenGeometry] from "@iosevka/geometry" -import [Vec2] from "@iosevka/geometry/point" -import [Box] from "@iosevka/geometry/box" -import [Interpolator] from "@iosevka/geometry/spiro-control" -import [PenKnotCollector] from "@iosevka/geometry/spiro-pen-expand" - -glyph-module - -glyph-block LetterLike-Fraktur-Shared : begin - - # [fraktur-stroke profile ...] will construct a Fraktur stroke from a pen profile and a list - # of control knots. The knots will form a (usually open) spiro path, then the result will be - # the area that the pen tip covers when moving along the path. - glyph-block-export fraktur-stroke - define [fraktur-stroke profile __knots] : begin - local knots : {}.slice.call arguments 1 - return : new FrakturImpl profile knots - - class FrakturImpl - public [new profile knots] : begin - this.profile = profile - this.knots = knots - - public [applyToGlyph glyph] : begin - local defaultProfile : this.profile.getPenShape glyph.gizmo - local collector : new PenKnotCollector glyph.gizmo defaultProfile - local c : spiro-collect collector this.knots - - local geom : new SpiroPenGeometry - begin glyph.gizmo - begin defaultProfile - begin collector.closed - begin collector.knots - - glyph.includeGeometry geom - return collector.knots - - # Directive to change the profile - glyph-block-export change-profile - define [change-profile newProfile] : function : begin - this.setProfile : newProfile.getPenShape this.gizmo - - # A pen profile describes a virtual flat-tip pen. We use a 45-degree arrangement to - # simplify the math. - class FrakturProfile - public [new thick thin] : begin - # .thick is the half length of the flat tip, projected to the X/Y axis - this.thick = 0.25 * [Math.sqrt 2] * thick - # .thin is the half width of the thin tip, projected to the X/Y axis - this.thin = 0.25 * [Math.sqrt 2] * thin - - public [getPenShape gizmo] : begin - local thickTf : gizmo.applyOffsetXY this.thick this.thick - list - new Vec2 (thickTf.x - this.thin) (thickTf.y + this.thin) - new Vec2 (thickTf.x + this.thin) (thickTf.y + this.thin) - new Vec2 (thickTf.x + this.thin) (thickTf.y - this.thin) - new Vec2 (-thickTf.x + this.thin) (-thickTf.y - this.thin) - new Vec2 (-thickTf.x - this.thin) (-thickTf.y - this.thin) - new Vec2 (-thickTf.x - this.thin) (-thickTf.y + this.thin) - - public [box u d l r] : new Box [this.yt u] [this.yb d] [this.xl l] [this.xr r] - - public [xl x] : x + this.thick - public [xr x] : x - this.thick - public [xp l r p] : mix [this.xl l] [this.xr r] p - - public [yb y] : y + this.thick - public [yt y] : y - this.thick - public [yp b t p] : mix [this.yb b] [this.yt t] p - - # Connection to another profile's pen tip position - public [connL otherProfile x] : x - otherProfile.thick + this.thick - public [connR otherProfile x] : x + otherProfile.thick - this.thick - public [connB otherProfile y] : y - otherProfile.thick + this.thick - public [connT otherProfile y] : y + otherProfile.thick - this.thick - - # Stroke widths - define frakThin : 1.0 * [AdviceStroke 12] - define frakThick : 1.0 * Stroke - define frakFine : 1.0 * [AdviceStroke 4] # For decoration - - glyph-block-export S - define S : new FrakturProfile frakThick (0.875 * frakThin) - - glyph-block-export F - define F : new FrakturProfile frakFine (0.875 * frakThin) - - glyph-block-export T - define T : new FrakturProfile frakThin (0.875 * frakThin) - - # Key metrics - glyph-block-export DecoSizeX DecoSizeY FHook Wave.DepthY Wave.DepthX LbFootRise - define DecoSizeX : 0.15 * (RightSB - SB) - define DecoSizeY : 0.08 * (RightSB - SB) - define FHook : 0.4 * SHook - 0.25 * S.thick - define LbFootRise : 0.375 * SHook + 0.375 * S.thick - - glyph-block-export SlopeA SlopeB - define SlopeA : 0.875 * DecoSizeY / DecoSizeX - define SlopeB : 0.875 * -[mix SlopeA 1.0 0.5] - - # Wave blenders - glyph-block-export Wave - define Wave : namespace - export : define DepthY : 0.4 * SHook - 0.25 * S.thick - export : define DepthX : 0.375 * SHook + 0.125 * S.thick - - export : define [vc waveDepth] : Interpolator vcWaveBlender [object waveDepth] - define [vcWaveBlender before after args] : begin - local [object waveDepth] args - return : list - g2 (before.x + 0.5 * waveDepth) [mix before.y after.y 0.375] - g2 (after.x - 0.5 * waveDepth) [mix before.y after.y 0.625] - - export : define [h] : Interpolator hWaveBlender [object h] - define [hWaveBlender before after] : begin - return : list - g2 [mix before.x after.x 0.375] after.y - g2 [mix before.x after.x 0.625] before.y - - glyph-block-export PHexTop - define PHexTop : 0.5 + 0.5 * ([Math.max DecoSizeX frakThin] / (RightSB - SB)) - glyph-block-export PHexBot - define PHexBot : 1 - PHexTop - -glyph-block LetterLike-Fraktur : begin - glyph-block-import Common-Derivatives - glyph-block-import CommonShapes - glyph-block-import LetterLike-Fraktur-Shared : S F T fraktur-stroke change-profile - glyph-block-import LetterLike-Fraktur-Shared : DecoSizeX DecoSizeY SlopeA SlopeB - glyph-block-import LetterLike-Fraktur-Shared : Wave LbFootRise FHook PHexTop PHexBot - - - define [LtDecorativeWave sx sy ey] : fraktur-stroke F - g2.ld.start sx sy - ~~~ [Wave.vc (-Wave.DepthX)] - g2.ld.end pre@ (ey - 2 * S.thick) - - do "C, E, and G" - define flex-params [FrakCTopAndCenterStroke] : glyph-proc - local-parameter : top -- [S.yt CAP] - local-parameter : bot -- [S.yp 0 CAP 0.375] - local-parameter : left -- [S.xl SB] - local-parameter : right -- [S.xr RightSB] - - local xCenter : [mix left right 0.5] + 0.25 * F.thick - local deco : Math.max DecoSizeX (0.5 * ArchDepthA - 2 * S.thick) - local waveTop : top - deco - - # Top-right stroke - include : fraktur-stroke S - g2 right top - g2.left.mid [mix@ 0.5] (top - 0.5 * FHook) - corner (post@ <+> deco) top - corner xCenter (top - deco) - - # Inner decoration - include : fraktur-stroke F - g2.ld.start [F.connL S xCenter] [F.connB S : top - deco] - ~~~ [Wave.vc (-Wave.DepthX)] - g2.ld.end pre@ bot - - return : object xCenter [waveTop : top - deco] [waveBot bot] - - define flex-params [FrakCOutlineShape] : glyph-proc - local-parameter : mode -- 'C' - local-parameter : top -- [S.yt CAP] - local-parameter : bot -- [S.yb 0] - local-parameter : left -- [S.xl SB] - local-parameter : right -- [S.xr RightSB] - - local [object xCenter waveTop waveBot] : include : FrakCTopAndCenterStroke - bot -- ([mix bot top 0.1] + 2 * Wave.DepthY + 0.5 * S.thick) - - # Left and bottom stroke - local mainStroke : include : fraktur-stroke S - g4.ru.start [T.connL S xCenter] [T.connB S waveTop] [change-profile T] - arch.rhs [T.connT S top] (sw -- T.thick) (anglePre -- (-45)) (anglePost -- 0) - flat left (pre@ <-> 0.6 * ArchDepthA) [change-profile S] - curl pre@ (post@ <+> ArchDepthB) - match mode - : [Just 'C'] : list # C and E - hookend (sw -- S.thick) bot - g2 [T.connR S right] (pre@ <+> [T.connT S SHook]) [change-profile T] - : [Just 'G'] : list # G - arch.lhs (sw -- S.thick) bot - flat right (pre@ <+> ArchDepthA) - decor@ : curl pre@ (post@ <-> 0.5 * ArchDepthB) - decor@@ : g2 [post@tang-out 1] [post@tang-out SlopeB] - decor@ : corner [mix@rev PHexTop] [post@slope SlopeA] - decor@ : corner xCenter [mix waveTop waveBot 0.5] - - return : object xCenter waveTop waveBot - - create-glyph "frak/C" 0x212D : glyph-proc - include : MarkSet.capital - include : FrakCOutlineShape (mode -- 'C') - - create-glyph "frak/E" 0x1D508 : glyph-proc - include [refer-glyph "frak/C"] AS_BASE ALSO_METRICS - local [object xCenter waveTop waveBot] : include : FrakCOutlineShape (mode -- 'C') - - include : fraktur-stroke F - corner [F.connL S xCenter] [F.connB S : mix waveTop waveBot 0.5] - corner (post@ <-> 0.5 * DecoSizeX) [pre@slope SlopeA] - corner [F.xr RightSB] (pre@ <-> 0.5 * DecoSizeY) - - create-glyph "frak/G" 0x1D50A : glyph-proc - include : MarkSet.capital - include : FrakCOutlineShape (mode -- 'G') - - create-glyph "frak/H" 0x210C : glyph-proc - include : MarkSet.capDesc - - local xExt : mix 0 SB 0.25 - local xLeftStem : Math.max (xExt + 1.5 * DecoSizeX) [mix SB RightSB 0] - local ada : 0.6 * ArchDepthA - local adb : 0.6 * ArchDepthB - - local xMidStrokeTop : S.xp xLeftStem RightSB 0.625 - local yMidStrokeTop : S.yt (XH - FHook) - local xMidStrokeStart : S.xl xLeftStem - local yMidStrokeStart : yMidStrokeTop - SlopeA * (xMidStrokeTop - xMidStrokeStart) - - # Top and left stroke - include : fraktur-stroke S - g2 [S.xr RightSB] ([S.yt CAP] - FHook) - ~~~ [arch.rhs [S.yt CAP] (sw -- S.thick) (blendPre -- null) (blendPost -- null)] - corner [S.xl xLeftStem] ([S.yt CAP] - adb) - curl [S.xl xLeftStem] [Math.min [S.yt (XH - FHook)] [S.yp 0 CAP 0.5]] - corner [S.xl xExt] [Math.min yMidStrokeStart ([S.yb 0] + LbFootRise)] - g2c.right.end (Middle - DecoSizeX) [S.yb 0] - corner Middle ([S.yb 0] + DecoSizeY) - - # Middle and right stroke - include : fraktur-stroke S - g2 xMidStrokeStart yMidStrokeStart - corner xMidStrokeTop yMidStrokeTop - g2.down.mid [S.xr RightSB] [S.yp Descender(XH - FHook) 0.75] - ~~~ [alsoThru.g2 0.5 0.5] - g2.down.mid [S.xp xLeftStem RightSB 0.75] [S.yp Descender(XH - FHook) 0.25] - g2 [S.xr RightSB] [S.yb Descender] - - do "I, J" - define [IJTopStroke] : glyph-proc - include : fraktur-stroke S - g2.ld.start [S.xr RightSB] [S.yt CAP] - ~~~ [Wave.h] - g2.ld.end [S.xl SB] (pre@ <-> Wave.DepthY) [change-profile F] - ~~~ [Wave.vc (-Wave.DepthX)] - g2.ld.end pre@ (CAP * 0.625 - 2 * F.thick) - - create-glyph "frak/I" 0x2111 : glyph-proc - include : MarkSet.capital - include : IJTopStroke - - local iBox : S.box CAP 0 SB RightSB - include : fraktur-stroke S - g2.ld.start iBox.right iBox.top - g4 [iBox.xp 0.7] [mix@ 0.375] - g4 iBox.right (post@ <+> ArchDepthA) - hookend (sw -- S.thick) iBox.bot - g2 iBox.left (pre@ <+> SHook) - - create-glyph "frak/J" 0x1D50D : glyph-proc - include : MarkSet.capDesc - include : IJTopStroke - - local jBox : S.box [S.yt (CAP - 1.5 * Wave.DepthY - 2 * S.thick)] Descender SB RightSB - include : fraktur-stroke S - g4 [T.connR S jBox.right] (post@ <-> FHook) [change-profile T] - hookstart (sw -- S.thick) [T.connT S jBox.top] - g4 ([jBox.xp 0.6] - S.thick) (pre@ <-> 0.6 * ArchDepthA) [change-profile S] - g4 jBox.right (post@ <+> ArchDepthA) - hookend (sw -- S.thick) jBox.bot - g2 jBox.left (pre@ <+> SHook) - - create-glyph "frak/R" 0x211C : glyph-proc - include : MarkSet.capital - - local xExt : mix 0 SB 0.25 - local xLeftStem : Math.max (xExt + 1.5 * DecoSizeX) [mix SB RightSB 0.166] - local ltHook : 0.25 * Hook - local ada : 0.6 * ArchDepthA - local adb : 0.6 * ArchDepthB - - # Deocration at top-left - # include : LtDecorativeWave [S.xl xExt] [S.yt (CAP - Wave.DepthY)] (CAP * 0.625) - - local xMidStrokeL : S.xl xLeftStem - local xMidStrokeR : S.xp xLeftStem RightSB 0.625 - local yMidStrokeR : S.yp 0 CAP 0.55 - local yMidStrokeL : yMidStrokeR - SlopeA * (xMidStrokeR - xMidStrokeL) - - local xArchStart xMidStrokeL - local xArchTop xMidStrokeR - local yArchTop : S.yt CAP - local yArchStart : yArchTop - SlopeA * (xArchTop - xArchStart) - - # Left stroke - include : fraktur-stroke F - g2.ru.start post@ (CAP * 0.625 - 2 * F.thick) - ~~~ [Wave.vc Wave.DepthX] - g2.ru.start [S.xl xExt] (post@ <-> ltHook) [change-profile S] - arch.rhs (blendPre -- null) [S.yt CAP] 0.625 - flat [S.xl xLeftStem] [Math.max ([S.yb CAP] - ada) yArchStart] - curl (pre@ <+> 0) yMidStrokeL - corner [S.xl xExt] (post@ <+> LbFootRise) - g2c.right.end (post@ <-> DecoSizeX) [S.yb 0] - corner Middle (pre@ <+> DecoSizeY) - - # Top-right arch - include : fraktur-stroke S - flat xArchStart yArchStart - corner xArchTop yArchTop - g2.down.mid [S.xr RightSB] [mix@ 0.5] - flat xMidStrokeR yMidStrokeR - curl xMidStrokeL yMidStrokeL - - local xLegStart : mix xMidStrokeL xMidStrokeR 0.75 - local yLegStart : mix yMidStrokeL yMidStrokeR 0.75 - local xLegEnd RightSB - local yLegEnd : S.yb 0 - - # Leg - include : fraktur-stroke S - [g2.sr SlopeA].start xLegStart yLegStart - flat [mix@ 0.75] (pre@ <-> adb) - decor@ : curl pre@ (post@ <+> ada) - corner xLegEnd yLegEnd - corner (pre@ <+> DecoSizeX) (pre@ <+> DecoSizeY) - - create-glyph "frak/Z" 0x2128 : glyph-proc - include : MarkSet.capital - - local zBox : S.box CAP 0 SB RightSB - - # Top Stroke - include : fraktur-stroke S - g2.ld.start zBox.right zBox.top - ~~~ [Wave.h] - g2.ld.mid zBox.left (pre@ <-> Wave.DepthY) - - # Bottom Stroke - local diag : list - corner zBox.right zBox.top - corner [zBox.xp 0.166] [zBox.yp 0.5] - include : fraktur-stroke S diag - include : difference - fraktur-stroke S - g2.ru.start diag.1.x diag.1.y - ~~~ [arch.rhs [zBox.yp 0.55] 0.375 (sw -- S.thick)] - g2.down.mid zBox.right (post@ <+> ArchDepthA) - hookend zBox.bot (sw -- S.thick) - g2 zBox.left (pre@ <+> SHook) - MaskAboveLine diag.0.x diag.0.y diag.1.x diag.1.y 4 - - - create-glyph "frak/e" 0xAB32 : glyph-proc - include : MarkSet.e - local eBox : S.box XH 0 SB RightSB - include : fraktur-stroke S - corner (eBox.left + S.thick) [post@slope SlopeA] - g2 eBox.xMid [eBox.yp DesignParameters.eBarPos] - corner eBox.right [pre@slope SlopeA] - corner [eBox.xp PHexTop] eBox.top - corner eBox.left [pre@slope SlopeA] - curl pre@ (post@ <+> ArchDepthB) - [g2c.sr (-SlopeA)].end [eBox.xp PHexTop] eBox.bot - corner eBox.right [pre@slope SlopeA] - - alias 'mathFrak/e' 0x1D522 'frak/e' - - create-glyph "frak/o" 0xAB3D : glyph-proc - include : MarkSet.e - local oBox : S.box XH 0 SB RightSB - include : fraktur-stroke S - [cg2.sr SlopeB].start [oBox.xp PHexTop] oBox.top - g2.down.mid oBox.right [mix@ 0.5] - [g2c.sl SlopeA].start [oBox.xp PHexBot] oBox.bot - corner oBox.left [pre@slope SlopeB] - corner pre@ [post@slope SlopeA] - close - - alias 'mathFrak/o' 0x1D52C 'frak/o' +export : define [apply] : begin + define $$Capture$$ this + run-glyph-module "./fraktur/common.mjs" + + run-glyph-module "./fraktur/upper-a.mjs" + run-glyph-module "./fraktur/upper-ceg.mjs" + run-glyph-module "./fraktur/upper-hkr.mjs" + run-glyph-module "./fraktur/upper-ij.mjs" + run-glyph-module "./fraktur/upper-z.mjs" + + run-glyph-module "./fraktur/lower-e.mjs" + run-glyph-module "./fraktur/lower-o.mjs" diff --git a/packages/font-glyphs/src/letter-like/fraktur/common.ptl b/packages/font-glyphs/src/letter-like/fraktur/common.ptl new file mode 100644 index 000000000..91ae85a2e --- /dev/null +++ b/packages/font-glyphs/src/letter-like/fraktur/common.ptl @@ -0,0 +1,140 @@ +$$include '../../meta/macros.ptl' + +import [mix fallback] from "@iosevka/util" +import [SpiroPenGeometry] from "@iosevka/geometry" +import [Vec2] from "@iosevka/geometry/point" +import [Box] from "@iosevka/geometry/box" +import [Interpolator] from "@iosevka/geometry/spiro-control" +import [PenKnotCollector] from "@iosevka/geometry/spiro-pen-expand" + +glyph-module + +glyph-block LetterLike-Fraktur-Common : begin + + # [fraktur-stroke profile ...] will construct a Fraktur stroke from a pen profile and a list + # of control knots. The knots will form a (usually open) spiro path, then the result will be + # the area that the pen tip covers when moving along the path. + glyph-block-export fraktur-stroke + define [fraktur-stroke profile __knots] : begin + local knots : {}.slice.call arguments 1 + return : new FrakturImpl profile knots + + class FrakturProxy + public [new gizmo profile collector] : begin + set this.gizmo gizmo + set this.knots collector.knots + + set this.geometry : new SpiroPenGeometry + begin gizmo + begin profile + begin collector.closed + begin collector.knots + + public [first i] this.knots.[fallback i 0] + public [last i] this.knots.(this.knots.length - [fallback i 1]) + + class FrakturImpl + public [new profile knots] : begin + this.profile = profile + this.knots = knots + + public [applyToGlyph glyph] : begin + local defaultProfile : this.profile.getPenShape glyph.gizmo + local collector : new PenKnotCollector glyph.gizmo defaultProfile + local c : spiro-collect collector this.knots + + local proxy : new FrakturProxy glyph.gizmo defaultProfile collector + glyph.includeGeometry proxy.geometry + return proxy + + # Directive to change the profile + glyph-block-export change-profile + define [change-profile newProfile] : function : begin + this.setProfile : newProfile.getPenShape this.gizmo + + # A pen profile describes a virtual flat-tip pen. We use a 45-degree arrangement to + # simplify the math. + class FrakturProfile + public [new thick thin] : begin + # .thick is the half length of the flat tip, projected to the X/Y axis + this.thick = 0.25 * [Math.sqrt 2] * thick + # .thin is the half width of the thin tip, projected to the X/Y axis + this.thin = 0.25 * [Math.sqrt 2] * thin + + public [getPenShape gizmo] : begin + local thickTf : gizmo.applyOffsetXY this.thick this.thick + list + new Vec2 (thickTf.x - this.thin) (thickTf.y + this.thin) + new Vec2 (thickTf.x + this.thin) (thickTf.y + this.thin) + new Vec2 (thickTf.x + this.thin) (thickTf.y - this.thin) + new Vec2 (-thickTf.x + this.thin) (-thickTf.y - this.thin) + new Vec2 (-thickTf.x - this.thin) (-thickTf.y - this.thin) + new Vec2 (-thickTf.x - this.thin) (-thickTf.y + this.thin) + + public [box u d l r] : new Box [this.yt u] [this.yb d] [this.xl l] [this.xr r] + + public [xl x] : x + this.thick + public [xr x] : x - this.thick + public [xp l r p] : mix [this.xl l] [this.xr r] p + + public [yb y] : y + this.thick + public [yt y] : y - this.thick + public [yp b t p] : mix [this.yb b] [this.yt t] p + + # Connection to another profile's pen tip position + public [connL otherProfile x] : x - otherProfile.thick + this.thick + public [connR otherProfile x] : x + otherProfile.thick - this.thick + public [connB otherProfile y] : y - otherProfile.thick + this.thick + public [connT otherProfile y] : y + otherProfile.thick - this.thick + + # Stroke widths + define frakThin : 1.0 * [AdviceStroke 12] + define frakThick : 1.0 * Stroke + define frakFine : 1.0 * [AdviceStroke 4] # For decoration + + glyph-block-export S + define S : new FrakturProfile frakThick (0.875 * frakThin) + + glyph-block-export F + define F : new FrakturProfile frakFine (0.875 * frakThin) + + glyph-block-export T + define T : new FrakturProfile frakThin (0.875 * frakThin) + + # Key metrics + glyph-block-export DecoSizeX DecoSizeY FHook Wave.DepthY Wave.DepthX LbFootRise + define DecoSizeX : 0.15 * (RightSB - SB) + define DecoSizeY : 0.08 * (RightSB - SB) + define FHook : 0.4 * SHook - 0.25 * S.thick + define LbFootRise : 0.375 * SHook + 0.375 * S.thick + + glyph-block-export SlopeA SlopeB + define SlopeA : 0.875 * DecoSizeY / DecoSizeX + define SlopeB : 0.875 * -[mix SlopeA 1.0 0.5] + + # Wave blenders + glyph-block-export Wave + define Wave : namespace + export : define DepthY : 0.4 * SHook - 0.25 * S.thick + export : define DepthX : 1 * DecoSizeX + + export : define [vc waveDepth] : Interpolator vcWaveBlender [object waveDepth] + define [vcWaveBlender before after args] : begin + local [object waveDepth] args + return : list + g2 (before.x + 0.5 * waveDepth) [mix before.y after.y 0.375] + g2 (after.x - 0.5 * waveDepth) [mix before.y after.y 0.625] + + export : define [h] : Interpolator hWaveBlender [object h] + define [hWaveBlender before after] : begin + return : list + g2 [mix before.x after.x 0.375] after.y + g2 [mix before.x after.x 0.625] before.y + + glyph-block-export PHexTop + define PHexTop : 0.5 + 0.5 * ([Math.max DecoSizeX frakThin] / (RightSB - SB)) + glyph-block-export PHexBot + define PHexBot : 1 - PHexTop + + glyph-block-export FrakDf + define [FrakDf div m] : DivFrame [fallback div 1] [fallback m 2] [Math.max 1 : DecoSizeX / SB] diff --git a/packages/font-glyphs/src/letter-like/fraktur/lower-e.ptl b/packages/font-glyphs/src/letter-like/fraktur/lower-e.ptl new file mode 100644 index 000000000..00f89b994 --- /dev/null +++ b/packages/font-glyphs/src/letter-like/fraktur/lower-e.ptl @@ -0,0 +1,27 @@ +$$include '../../meta/macros.ptl' + +glyph-module + +glyph-block LetterLike-Fraktur-Lower-E : begin + glyph-block-import Common-Derivatives + glyph-block-import CommonShapes + glyph-block-import LetterLike-Fraktur-Common : FrakDf S F T fraktur-stroke change-profile + glyph-block-import LetterLike-Fraktur-Common : DecoSizeX DecoSizeY SlopeA SlopeB + glyph-block-import LetterLike-Fraktur-Common : Wave LbFootRise FHook PHexTop PHexBot + + create-glyph "frak/e" 0xAB32 : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.e + + local eBox : S.box XH 0 df.leftSB df.rightSB + include : fraktur-stroke S + corner (eBox.left + S.thick) [post@slope SlopeA] + g2 eBox.xMid [eBox.yp DesignParameters.eBarPos] + corner eBox.right [pre@slope SlopeA] + corner [eBox.xp PHexTop] eBox.top + corner eBox.left [pre@slope SlopeA] + curl pre@ (post@ <+> ArchDepthB) + [g2c.sr (-SlopeA)].end [eBox.xp PHexTop] eBox.bot + corner eBox.right [pre@slope SlopeA] + + alias 'mathFrak/e' 0x1D522 'frak/e' diff --git a/packages/font-glyphs/src/letter-like/fraktur/lower-o.ptl b/packages/font-glyphs/src/letter-like/fraktur/lower-o.ptl new file mode 100644 index 000000000..3b6aea73d --- /dev/null +++ b/packages/font-glyphs/src/letter-like/fraktur/lower-o.ptl @@ -0,0 +1,25 @@ +$$include '../../meta/macros.ptl' + +glyph-module + +glyph-block LetterLike-Fraktur-Lower-O : begin + glyph-block-import Common-Derivatives + glyph-block-import CommonShapes + glyph-block-import LetterLike-Fraktur-Common : FrakDf S F T fraktur-stroke change-profile + glyph-block-import LetterLike-Fraktur-Common : DecoSizeX DecoSizeY SlopeA SlopeB + glyph-block-import LetterLike-Fraktur-Common : Wave LbFootRise FHook PHexTop PHexBot + + create-glyph "frak/o" 0xAB3D : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.e + + local oBox : S.box XH 0 df.leftSB df.rightSB + include : fraktur-stroke S + [cg2.sr SlopeB].start [oBox.xp PHexTop] oBox.top + g2.down.mid oBox.right [mix@ 0.5] + [g2c.sl SlopeA].start [oBox.xp PHexBot] oBox.bot + corner oBox.left [pre@slope SlopeB] + corner pre@ [post@slope SlopeA] + close + + alias 'mathFrak/o' 0x1D52C 'frak/o' diff --git a/packages/font-glyphs/src/letter-like/fraktur/upper-a.ptl b/packages/font-glyphs/src/letter-like/fraktur/upper-a.ptl new file mode 100644 index 000000000..b38cb8b3f --- /dev/null +++ b/packages/font-glyphs/src/letter-like/fraktur/upper-a.ptl @@ -0,0 +1,35 @@ +$$include '../../meta/macros.ptl' + +import [mix fallback] from "@iosevka/util" + +glyph-module + +glyph-block LetterLike-Fraktur-Upper-A : begin + glyph-block-import Common-Derivatives + glyph-block-import CommonShapes + glyph-block-import LetterLike-Fraktur-Common : FrakDf S F T fraktur-stroke change-profile + glyph-block-import LetterLike-Fraktur-Common : DecoSizeX DecoSizeY SlopeA SlopeB + glyph-block-import LetterLike-Fraktur-Common : Wave LbFootRise FHook PHexTop PHexBot + + create-glyph 'frak/A' 0x1D504 : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.capital + + local aBox : S.box CAP 0 df.leftSB df.rightSB + + include : fraktur-stroke S + g2.ru.start (post@) ([aBox.yp 0.625] - 2 * F.thick) [change-profile F] + ~~~ [Wave.vc Wave.DepthX] + g2.ru.mid aBox.left (post@ <-> DecoSizeY) [change-profile S] + arch.rhs (sw -- S.thick) (blendPre -- null) aBox.top 0.4 + straight.down.mid [aBox.xp 0.5] [mix@ 0.375] + [flatc.sl SlopeA].end (aBox.left - 0.25 * DecoSizeX) [post@slope SlopeB] + corner [aBox.xp PHexBot] aBox.bot + corner aBox.right [pre@slope SlopeA] + + include : fraktur-stroke S + flat aBox.right aBox.top + curl pre@ [post@slope : 2 * SlopeB] + [flatc.sr SlopeB].end (pre@ <+> 0.5 * DecoSizeX) aBox.bot + corner (pre@ <+> DecoSizeX) (pre@ <+> DecoSizeY) + # g2.ld.mid aBox.left (pre@ <-> Wave.DepthY) diff --git a/packages/font-glyphs/src/letter-like/fraktur/upper-ceg.ptl b/packages/font-glyphs/src/letter-like/fraktur/upper-ceg.ptl new file mode 100644 index 000000000..fa0bfeb4a --- /dev/null +++ b/packages/font-glyphs/src/letter-like/fraktur/upper-ceg.ptl @@ -0,0 +1,92 @@ +$$include '../../meta/macros.ptl' + +import [mix fallback] from "@iosevka/util" + +glyph-module + +glyph-block LetterLike-Fraktur-Upper-CEG : begin + glyph-block-import Common-Derivatives + glyph-block-import CommonShapes + glyph-block-import LetterLike-Fraktur-Common : FrakDf S F T fraktur-stroke change-profile + glyph-block-import LetterLike-Fraktur-Common : DecoSizeX DecoSizeY SlopeA SlopeB + glyph-block-import LetterLike-Fraktur-Common : Wave LbFootRise FHook PHexTop PHexBot + + + define flex-params [FrakCTopAndCenterStroke] : glyph-proc + local-parameter df + local-parameter : top -- [S.yt CAP] + local-parameter : bot -- [S.yp 0 CAP 0.375] + local-parameter : left -- [S.xl df.leftSB] + local-parameter : right -- [S.xr df.rightSB] + + local xCenter : [mix left right 0.5] + 0.25 * F.thick + local deco : Math.max DecoSizeX (0.5 * ArchDepthA - 2 * S.thick) + local waveTop : top - deco + + # Top-right stroke + include : fraktur-stroke S + g2 right top + g2.left.mid [mix@ 0.5] (top - 0.5 * FHook) + corner (post@ <+> deco) top + corner xCenter (top - deco) + + # Inner decoration + include : fraktur-stroke F + g2.ld.start [F.connL S xCenter] [F.connB S : top - deco] + ~~~ [Wave.vc (-Wave.DepthX)] + g2.ld.end pre@ bot + + return : object xCenter [waveTop : top - deco] [waveBot bot] + + define flex-params [FrakCOutlineShape] : glyph-proc + local-parameter df + local-parameter : mode -- 'C' + local-parameter : top -- [S.yt CAP] + local-parameter : bot -- [S.yb 0] + local-parameter : left -- [S.xl df.leftSB] + local-parameter : right -- [S.xr df.rightSB] + + local [object xCenter waveTop waveBot] : include : FrakCTopAndCenterStroke df + bot -- ([mix bot top 0.1] + 2 * Wave.DepthY + 0.5 * S.thick) + + # Left and bottom stroke + include : fraktur-stroke S + g4.ru.start [T.connL S xCenter] [T.connB S waveTop] [change-profile T] + arch.rhs [T.connT S top] (sw -- T.thick) (anglePre -- (-45)) (anglePost -- 0) + flat left (pre@ <-> 0.6 * ArchDepthA) [change-profile S] + curl pre@ (post@ <+> ArchDepthB) + match mode + : [Just 'C'] : list # C and E + hookend (sw -- S.thick) bot + g2 [T.connR S right] (pre@ <+> [T.connT S SHook]) [change-profile T] + : [Just 'G'] : list # G + arch.lhs (sw -- S.thick) bot + flat right (pre@ <+> ArchDepthA) + decor@ : curl pre@ (post@ <-> 0.5 * ArchDepthB) + decor@@ : g2 [post@tang-out 1] [post@tang-out SlopeB] + decor@ : corner [mix@rev PHexTop] [post@slope SlopeA] + decor@ : corner xCenter [mix waveTop waveBot 0.5] + + return : object xCenter waveTop waveBot + + create-glyph "frak/C" 0x212D : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.capital + + include : FrakCOutlineShape df (mode -- 'C') + + create-glyph "frak/E" 0x1D508 : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.capital + + local [object xCenter waveTop waveBot] : include : FrakCOutlineShape df (mode -- 'C') + + include : fraktur-stroke F + corner [F.connL S xCenter] [F.connB S : mix waveTop waveBot 0.5] + corner (post@ <-> 0.5 * DecoSizeX) [pre@slope SlopeA] + corner [F.xr df.rightSB] (pre@ <-> 0.5 * DecoSizeY) + + create-glyph "frak/G" 0x1D50A : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.capital + include : FrakCOutlineShape df (mode -- 'G') diff --git a/packages/font-glyphs/src/letter-like/fraktur/upper-hkr.ptl b/packages/font-glyphs/src/letter-like/fraktur/upper-hkr.ptl new file mode 100644 index 000000000..743e2bb25 --- /dev/null +++ b/packages/font-glyphs/src/letter-like/fraktur/upper-hkr.ptl @@ -0,0 +1,102 @@ +$$include '../../meta/macros.ptl' + +import [mix fallback] from "@iosevka/util" + +glyph-module + +glyph-block LetterLike-Fraktur-Upper-HKR : begin + glyph-block-import Common-Derivatives + glyph-block-import CommonShapes + glyph-block-import LetterLike-Fraktur-Common : FrakDf S F T fraktur-stroke change-profile + glyph-block-import LetterLike-Fraktur-Common : DecoSizeX DecoSizeY SlopeA SlopeB + glyph-block-import LetterLike-Fraktur-Common : Wave LbFootRise FHook PHexTop PHexBot + + define [HOuterShape bBody bDeco yConnT yConnB] : fraktur-stroke S + g2 bBody.right (post@ <-> FHook) + arch.lhs bBody.top (sw -- S.thick) (blendPre -- {}) + ~~~ [corner (post@ <-> 0.5 * DecoSizeX) [post@slope SlopeB]] + corner bBody.left [max@ yConnT (pre@ <-> 0.75 * ArchDepthA)] + curl pre@ [min@ yConnB (post@ <+> ArchDepthA)] + corner bDeco.left (post@ <+> 2 * DecoSizeY) + g2c.r.end (post@ <-> DecoSizeX) bBody.bot + corner bBody.xMid (pre@ <+> DecoSizeY) + + define [KRLegs box] : glyph-proc + # Top-right arch + local c : include : fraktur-stroke S + flat box.left [post@slope SlopeA] + corner [box.xp PHexTop] box.top + g2.down.mid box.right [mix@ 0.5] + flat [box.xp 0.625] [box.yp 0.55] + curl box.left [pre@slope SlopeA] + + + local xLegStart : mix [c.last 1].x [c.last 2].x 0.75 + local yLegStart : mix [c.last 1].y [c.last 2].y 0.75 + + # Leg + include : fraktur-stroke S + [g2.sr SlopeA].start xLegStart yLegStart + flat [mix@ 0.75] (pre@ <-> 0.6 * ArchDepthB) + decor@ : curl pre@ (post@ <+> 2 * DecoSizeY) + corner (box.right + 0.5 * DecoSizeX) box.bot + corner (pre@ <+> DecoSizeX) (pre@ <+> DecoSizeY) + + return : object [yConnT [c.first].y] [yConnB [c.last].y] + + create-glyph "frak/H" 0x210C : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.capDesc + + local hBox : S.box CAP 0 df.leftSB df.rightSB + local hDeco : hBox.padLeft (-0.25 * DecoSizeX) # top-left decoration ref box + local hBody : hBox.padLeft (+0.75 * DecoSizeX) # body ref box + local hInner : [hBody.withTop : hBody.yp 0.6].withBottom Descender + + # Inner stroke + local c : include : fraktur-stroke S + corner hInner.left [post@slope SlopeA] + corner [hInner.xp PHexTop] hInner.top + g2.down.mid hInner.right [hInner.yp 0.75] + ~~~ [alsoThru.g2 0.5 0.5] + g2.down.mid [hInner.xp 0.75] [hInner.yp 0.25] + g2 hInner.right hInner.bot + + # Top and left stroke + include : HOuterShape hBody hDeco (-VERY-FAR) [c.first].y + + create-glyph "frak/K" 0x1D50E : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.capital + + local kBox : S.box CAP 0 df.leftSB df.rightSB + local kDeco : kBox.padLeft (-0.25 * DecoSizeX) # top-left decoration ref box + local kBody : kBox.padLeft (+0.75 * DecoSizeX) # body ref box + local kInner : kBody.withTop : Math.min [kBody.yp 0.75] (kBody.top - FHook - Wave.DepthY - S.thick) + + local leg : include : KRLegs kInner + + include : HOuterShape kBody kDeco leg.yConnT leg.yConnB + + create-glyph "frak/R" 0x211C : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.capital + + local rBox : S.box CAP 0 df.leftSB df.rightSB + local rDeco : rBox.padLeft (-0.25 * DecoSizeX) # top-left decoration ref box + local rBody : rBox.padLeft (+1.50 * DecoSizeX) # body ref box + + # Legs + local leg : include : KRLegs rBody + + # Left stroke + include : fraktur-stroke F + g2.ru.start post@ ([rDeco.yp 0.625] - 2 * F.thick) + ~~~ [Wave.vc Wave.DepthX] + g2.ru.mid rDeco.left (post@ <-> DecoSizeY) [change-profile S] + arch.rhs (blendPre -- {}) rBody.top 0.625 + flat rBody.left (pre@ <-> 0.6 * ArchDepthA) + curl (pre@ <+> 0) leg.yConnB + corner rDeco.left (post@ <+> 2 * DecoSizeY) + g2c.right.end (post@ <-> DecoSizeX) [S.yb 0] + corner [rBody.xp 0.5] (pre@ <+> DecoSizeY) diff --git a/packages/font-glyphs/src/letter-like/fraktur/upper-ij.ptl b/packages/font-glyphs/src/letter-like/fraktur/upper-ij.ptl new file mode 100644 index 000000000..7a6ccb388 --- /dev/null +++ b/packages/font-glyphs/src/letter-like/fraktur/upper-ij.ptl @@ -0,0 +1,46 @@ +$$include '../../meta/macros.ptl' + +glyph-module + +glyph-block LetterLike-Fraktur-Upper-IJ : begin + glyph-block-import Common-Derivatives + glyph-block-import CommonShapes + glyph-block-import LetterLike-Fraktur-Common : FrakDf S F T fraktur-stroke change-profile + glyph-block-import LetterLike-Fraktur-Common : DecoSizeX DecoSizeY SlopeA SlopeB + glyph-block-import LetterLike-Fraktur-Common : Wave LbFootRise FHook PHexTop PHexBot + + define [TopStroke df] : glyph-proc + local iBox : S.box CAP 0 df.leftSB df.rightSB + include : fraktur-stroke S + g2.ld.start iBox.right iBox.top + ~~~ [Wave.h] + g2.ld.end iBox.left (pre@ <-> Wave.DepthY) [change-profile F] + ~~~ [Wave.vc (-Wave.DepthX)] + g2.ld.end pre@ ([iBox.yp 0.625] - 2 * F.thick) + + define [BottomStroke df bot archScalar] : glyph-proc + local gap : 2.5 * Wave.DepthY + 1 * S.thick + local jBox : S.box [S.yt (CAP - gap)] bot df.leftSB df.rightSB + local ada1 : 0.6 * archScalar * ArchDepthA + local ada2 : archScalar * ArchDepthA + include : fraktur-stroke S + g4 [T.connR S jBox.right] (post@ <-> FHook) [change-profile T] + hookstart (sw -- S.thick) [T.connT S jBox.top] + g4 ([jBox.xp 0.6] - S.thick) (jBox.top - ada1) [change-profile S] + g4 jBox.right (jBox.bot + ada2) + hookend (sw -- S.thick) jBox.bot + g2 jBox.left (pre@ <+> SHook) + + create-glyph "frak/I" 0x2111 : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.capital + + include : TopStroke df + include : BottomStroke df 0 0.75 + + create-glyph "frak/J" 0x1D50D : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.capDesc + + include : TopStroke df + include : BottomStroke df Descender 1 diff --git a/packages/font-glyphs/src/letter-like/fraktur/upper-z.ptl b/packages/font-glyphs/src/letter-like/fraktur/upper-z.ptl new file mode 100644 index 000000000..d80c51eaf --- /dev/null +++ b/packages/font-glyphs/src/letter-like/fraktur/upper-z.ptl @@ -0,0 +1,36 @@ +$$include '../../meta/macros.ptl' + +glyph-module + +glyph-block LetterLike-Fraktur-Upper-Z : begin + glyph-block-import Common-Derivatives + glyph-block-import CommonShapes + glyph-block-import LetterLike-Fraktur-Common : FrakDf S F T fraktur-stroke change-profile + glyph-block-import LetterLike-Fraktur-Common : DecoSizeX DecoSizeY SlopeA SlopeB + glyph-block-import LetterLike-Fraktur-Common : Wave LbFootRise FHook PHexTop PHexBot + + create-glyph "frak/Z" 0x2128 : glyph-proc + local df : include : FrakDf 1 + include : df.markSet.capital + + local zBox : S.box CAP 0 df.leftSB df.rightSB + + # Top Stroke + include : fraktur-stroke S + g2.ld.start zBox.right zBox.top + ~~~ [Wave.h] + g2.ld.mid zBox.left (pre@ <-> Wave.DepthY) + + # Bottom Stroke + local diag : include : fraktur-stroke S + corner zBox.right zBox.top + corner [zBox.xp 0.166] [zBox.yp 0.5] + + include : difference + fraktur-stroke S + g2.ru.start [diag.last].x [diag.last].y + ~~~ [arch.rhs [zBox.yp 0.55] 0.375 (sw -- S.thick)] + g2.down.mid zBox.right (post@ <+> ArchDepthA) + hookend zBox.bot (sw -- S.thick) + g2 zBox.left (pre@ <+> SHook) + MaskAboveLine [diag.first].x [diag.first].y [diag.last].x [diag.last].y 4 diff --git a/packages/font-glyphs/src/meta/macros.ptl b/packages/font-glyphs/src/meta/macros.ptl index b44c1c817..83b8307d5 100644 --- a/packages/font-glyphs/src/meta/macros.ptl +++ b/packages/font-glyphs/src/meta/macros.ptl @@ -294,7 +294,7 @@ define-macro glyph-block : syntax-rules define booleFnImports `[union intersection difference] - define drvCoordImports `[pre@ post@ mix@ mix@rev pre@slope post@slope + define drvCoordImports `[pre@ post@ mix@ mix@rev pre@slope post@slope min@ max@ decor@ decor@@ decor@@@ pre@tang-in post@tang-in pre@tang-out post@tang-out] dirty `[$GlyphBlocks$.push : lambda [$Capture_Ext$] : begin \\ diff --git a/packages/font-kits/src/derived-coordinates.mjs b/packages/font-kits/src/derived-coordinates.mjs index efb94eac2..1ba7189b0 100644 --- a/packages/font-kits/src/derived-coordinates.mjs +++ b/packages/font-kits/src/derived-coordinates.mjs @@ -36,8 +36,11 @@ export function SetupBuilders(_bindings) { "pre@slope": (s, delta) => new CAtSlopePre(s, delta), "post@slope": (s, delta) => new CAtSlopePost(s, delta), - // Interpolators + // Min and max derived coordinates + "min@": (...args) => new CMathFold(Math.min, args), + "max@": (...args) => new CMathFold(Math.max, args), + // Interpolators // decor@, decor@@, decor@@@: Add a "delay" to the thing inside when resolving the spiro // controls. This is a very useful utility for coordinate propagation, which allow us to // "skip" the current point and go to the next or previous point. The number of @'s @@ -98,6 +101,54 @@ class CDeltaPost extends DerivedCoordinateBase { } } +class CMathFold extends DerivedCoordinateBase { + constructor(operator, args) { + super(); + this.operator = operator; + this.args = args; + } + getDependencyForX() { + let flag = 0; + for (const item of this.args) { + if (typeof item === "number") continue; + flag |= item.getDependencyForX(); + } + return flag; + } + getDependencyForY() { + let flag = 0; + for (const item of this.args) { + if (typeof item === "number") continue; + flag |= item.getDependencyForY(); + } + return flag; + } + resolveX(pre, curr, post) { + let result = + typeof this.args[0] === "number" + ? this.args[0] + : this.args[0].resolveX(pre, curr, post); + for (let i = 1; i < this.args.length; i++) { + const item = this.args[i]; + const value = typeof item === "number" ? item : item.resolveX(pre, curr, post); + result = this.operator(result, value); + } + return result; + } + resolveY(pre, curr, post) { + let result = + typeof this.args[0] === "number" + ? this.args[0] + : this.args[0].resolveY(pre, curr, post); + for (let i = 1; i < this.args.length; i++) { + const item = this.args[i]; + const value = typeof item === "number" ? item : item.resolveY(pre, curr, post); + result = this.operator(result, value); + } + return result; + } +} + export class CMixCoord extends DerivedCoordinateBase { constructor(proportion, delta, mockPre, mockPost) { super(); diff --git a/packages/geometry/src/box.mjs b/packages/geometry/src/box.mjs index 984dce62c..19cb9a014 100644 --- a/packages/geometry/src/box.mjs +++ b/packages/geometry/src/box.mjs @@ -27,6 +27,20 @@ export class Box { withYPadding(d) { return new Box(this.top - d, this.bottom + d, this.left, this.right); } + + padLeft(d) { + return new Box(this.top, this.bottom, this.left + d, this.right); + } + padRight(d) { + return new Box(this.top, this.bottom, this.left, this.right - d); + } + padTop(d) { + return new Box(this.top - d, this.bottom, this.left, this.right); + } + padBottom(d) { + return new Box(this.top, this.bottom + d, this.left, this.right); + } + withXMix(pL, pR) { return new Box( this.top,