Add fraktur A and K (#2450)

This commit is contained in:
Belleve 2024-08-01 00:30:22 -10:00 committed by GitHub
parent d3767217af
commit dc9d7f3ac2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 584 additions and 395 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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