- MATHEMATICAL FRAKTUR CAPITAL B (`U+1D505`).
  - MATHEMATICAL FRAKTUR CAPITAL M (`U+1D510`).
  - MATHEMATICAL FRAKTUR CAPITAL N (`U+1D511`).
  - MATHEMATICAL FRAKTUR CAPITAL P (`U+1D513`).
  - MATHEMATICAL FRAKTUR CAPITAL V (`U+1D519`).
  - MATHEMATICAL FRAKTUR CAPITAL W (`U+1D51A`).
This commit is contained in:
Belleve 2024-08-02 00:02:19 -10:00 committed by GitHub
parent 8f945312fb
commit 58530575cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 273 additions and 14 deletions

View file

@ -1,7 +1,3 @@
* Add separate variant selectors for Cyrillic Capital En/Er (`VXAA`, `VXAB`).
* Add variant selectors for Greek lower Beta/Gamma/Nu/Upsilon (`VXAC`, `VXAD`, `VXAE`, `VXAF`).
* Optimize glyph for VERTICAL LINE WITH MIDDLE DOT (`U+2327`).
* Improve `k` (`cv46`) and `x` (`cv58`) variants used by `ss03`, `ss08`, `ss09`, `ss10`, `ss12`, `ss14`, and `ss18` under slab italic.
* Add characters:
- BLACK-LETTER CAPITAL H (`U+210C`) (#714).
- BLACK-LETTER CAPITAL I (`U+2111`) (#714).
@ -12,9 +8,19 @@
- 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 B (`U+1D505`) (#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 CAPITAL M (`U+1D510`) (#444).
- MATHEMATICAL FRAKTUR CAPITAL N (`U+1D511`) (#444).
- MATHEMATICAL FRAKTUR CAPITAL P (`U+1D513`) (#444).
- MATHEMATICAL FRAKTUR CAPITAL V (`U+1D519`) (#444).
- MATHEMATICAL FRAKTUR CAPITAL W (`U+1D51A`) (#444).
- MATHEMATICAL FRAKTUR SMALL E (`U+1D522`) (#444).
- MATHEMATICAL FRAKTUR SMALL O (`U+1D52C`) (#444).
* Add separate variant selectors for Cyrillic Capital En/Er (`VXAA`, `VXAB`).
* Add variant selectors for Greek lower Beta/Gamma/Nu/Upsilon (`VXAC`, `VXAD`, `VXAE`, `VXAF`).
* Optimize glyph for VERTICAL LINE WITH MIDDLE DOT (`U+2327`).
* Improve `k` (`cv46`) and `x` (`cv58`) variants used by `ss03`, `ss08`, `ss09`, `ss10`, `ss12`, `ss14`, and `ss18` under slab italic.

View file

@ -5,9 +5,11 @@ export : define [apply] : begin
run-glyph-module "./fraktur/common.mjs"
run-glyph-module "./fraktur/upper-a.mjs"
run-glyph-module "./fraktur/upper-bvw.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-mnp.mjs"
run-glyph-module "./fraktur/upper-z.mjs"
run-glyph-module "./fraktur/lower-e.mjs"

View file

@ -37,10 +37,9 @@ glyph-block LetterLike-Fraktur-Common : begin
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 collector : new PenKnotCollector glyph.gizmo defaultProfile this.profile.fixed
local c : spiro-collect collector this.knots
local proxy : new FrakturProxy glyph.gizmo defaultProfile collector
@ -56,6 +55,7 @@ glyph-block LetterLike-Fraktur-Common : begin
# simplify the math.
class FrakturProfile
public [new thick thin] : begin
this.fixed = false
# .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
@ -92,15 +92,30 @@ glyph-block LetterLike-Fraktur-Common : begin
define frakThick : 1.0 * Stroke
define frakFine : 1.0 * [AdviceStroke 4] # For decoration
class MaskingProfile
public [new dx dy] : begin
this.fixed = true
this.dx = dx
this.dy = dy
public [getPenShape gizmo] : begin
local tf : gizmo.applyOffsetXY this.dx this.dy
list [new Vec2 0 0] [new Vec2 tf.x tf.y]
glyph-block-export S
define S : new FrakturProfile frakThick (0.875 * frakThin)
glyph-block-export M
define M : new FrakturProfile [AdviceStroke 3 para.diversityM] (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)
glyph-block-export CutMaskLeft
define CutMaskLeft : new MaskingProfile (-VERY-FAR) 0
# Key metrics
glyph-block-export DecoSizeX DecoSizeY FHook Wave.DepthY Wave.DepthX LbFootRise
define DecoSizeX : 0.15 * (RightSB - SB)
@ -117,19 +132,32 @@ glyph-block LetterLike-Fraktur-Common : begin
define Wave : namespace
export : define DepthY : 0.4 * SHook - 0.25 * S.thick
export : define DepthX : 1 * DecoSizeX
export : define LTDecoSize : 0.75 * DecoSizeX
export : define [vc waveDepth] : Interpolator vcWaveBlender [object waveDepth]
define [vcWaveBlender before after args] : begin
export : define [h] : Interpolator hBlender
define [hBlender 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
export : define [vc waveDepth] : Interpolator vcBlender [object waveDepth]
define [vcBlender 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
export : define [v] : Interpolator vBlender
define [vBlender 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
g2 after.x [mix before.y after.y 0.375]
g2 before.x [mix before.y after.y 0.625]
export : define [vDistAfter d] : Interpolator vDistAfterBlender [object d]
define [vDistAfterBlender before after args] : begin
return : list
g2 after.x [mix before.y after.y 0.375]
g2 (after.x - args.d) [mix before.y after.y 0.625]
glyph-block-export PHexTop
define PHexTop : 0.5 + 0.5 * ([Math.max DecoSizeX frakThin] / (RightSB - SB))

View file

@ -0,0 +1,135 @@
$$include '../../meta/macros.ptl'
import [mix fallback] from "@iosevka/util"
glyph-module
glyph-block LetterLike-Fraktur-Upper-BVW : begin
glyph-block-import Common-Derivatives
glyph-block-import CommonShapes
glyph-block-import LetterLike-Fraktur-Common : FrakDf S M F 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
glyph-block-import LetterLike-Fraktur-Common : CutMaskLeft
define [deriveBoxes box] : begin
local body : box.padLeft (+1.50 * DecoSizeX)
local deco : box.padLeft (-0.25 * DecoSizeX)
return { body deco }
define [StartStroke mode box profile pRight] : glyph-proc
local { body deco } : deriveBoxes box
local [knots] : list
g2.ru.start (post@) ([deco.yp 0.625] - 2 * F.thick) [change-profile F]
~~~ [Wave.vc Wave.LTDecoSize]
g2.ru.mid deco.left (post@ <-> DecoSizeY) [change-profile M]
arch.rhs (sw -- S.thick) (blendPre -- null) deco.top 0.4
match mode
[Just "P"] : list
flat body.left [mix@ 0.375]
virt pre@ body.bot
curl body.left Descender
_ : list
straight.down.mid body.left [mix@ 0.375]
corner deco.left [post@slope SlopeB]
virt [body.xp : pRight * PHexBot] body.bot
local s : include : fraktur-stroke profile [knots]
return : object
lbKnot : s.last
maskLeft : function [] : fraktur-stroke CutMaskLeft [knots]
create-glyph 'frak/B' 0x1D505 : glyph-proc
local df : include : FrakDf 1
include : df.markSet.capital
local box : S.box CAP 0 df.leftSB df.rightSB
local { body deco } : deriveBoxes box
local leftStroke : include : StartStroke 'B' box S 1
local rightStroke : include : difference
union
fraktur-stroke S
corner leftStroke.lbKnot.x leftStroke.lbKnot.y
corner [body.xp PHexBot] body.bot
decor@ : g2.up.mid body.right [mix@ 0.5]
corner [body.xp 0.625] [body.yp 0.55]
fraktur-stroke S
corner deco.left [post@slope SlopeA]
corner [body.xp PHexTop] body.top
decor@ : g2.down.mid body.right [mix@ 0.5]
corner [body.xp 0.625] [body.yp 0.55]
corner deco.left [pre@slope : 0.5 * SlopeA]
leftStroke.maskLeft
create-glyph 'frak/P' 0x1D513 : glyph-proc
local df : include : FrakDf 1
include : df.markSet.capDesc
local box : S.box CAP 0 df.leftSB df.rightSB
local { body deco } : deriveBoxes box
local leftStroke : include : StartStroke "P" box S 1
local rightStroke : include : difference
fraktur-stroke S
g2 deco.left (post@ <+> Wave.DepthY)
~~~ [g2 [deco.xp 0.21] (pre@ <+> Wave.DepthY)]
g2 [deco.xp 0.625] body.bottom
~~~ [Wave.vDistAfter : 1.5 * Wave.DepthX]
[g2c.sr SlopeA].end (body.right + 0.25 * DecoSizeX) ([body.yp 0.75] + S.thick)
~~~ [curl [pre@tang-in 1] [pre@tang-in SlopeB]]
g2 (pre@ <-> Wave.DepthX) [mix@ 0.5]
arch.rhs (sw -- S.thick) (blendPre -- {}) body.top
corner (body.left - S.thick) (pre@ <-> ArchDepthA)
intersection [leftStroke.maskLeft] [MaskAbove body.yMid]
create-glyph 'frak/V' 0x1D519 : glyph-proc
local df : include : FrakDf 1
include : df.markSet.capital
local box : S.box CAP 0 df.leftSB df.rightSB
local { body deco } : deriveBoxes box
local leftStroke : include : StartStroke 'V' box S 1
local rightStroke : include : difference
fraktur-stroke S
corner leftStroke.lbKnot.x leftStroke.lbKnot.y
[cg2.sr SlopeA].start [body.xp PHexBot] body.bottom
~~~ [Wave.vDistAfter : 1.5 * Wave.DepthX]
[g2c.sr SlopeA].end (body.right + 0.25 * DecoSizeX) ([body.yp 0.75] + S.thick)
~~~ [curl [pre@tang-in 1] [pre@tang-in SlopeB]]
g2 (pre@ <-> Wave.DepthX) [mix@ 0.5]
arch.rhs (sw -- S.thick) (blendPre -- {}) body.top
corner (body.left - S.thick) (pre@ <-> ArchDepthA)
leftStroke.maskLeft
create-glyph 'frak/W' 0x1D51A : glyph-proc
local df : include : FrakDf para.diversityM 3
include : df.markSet.capital
local box : M.box CAP 0 df.leftSB df.rightSB
local { body deco } : deriveBoxes box
local leftStroke : include : StartStroke 'W' box M 0.5 1
local rightStroke : include : fraktur-stroke M
corner leftStroke.lbKnot.x leftStroke.lbKnot.y
corner [deco.xp : 0.5 * PHexBot] box.bottom
corner deco.xMid [post@slope SlopeB]
[cg2.sr SlopeA].start [deco.xp : mix 0.5 1 PHexBot] body.bot
~~~ [Wave.vDistAfter : 0.75 * Wave.DepthX]
[g2c.sr SlopeA].end (body.right + 0.5 * DecoSizeX) ([body.yp 0.75] + S.thick)
~~~ [curl [pre@tang-in 1] [pre@tang-in SlopeB]]
g2 (pre@ <-> 0.75 * Wave.DepthX) [mix@ 0.5]
arch.rhs (sw -- M.thick) (blendPre -- {}) body.top
corner body.xMid (body.top - 0.5 * Wave.DepthY)
~~~ [arch.rhs (sw -- M.thick) (blendPre -- {}) (blendPost -- {}) body.top]
corner body.left pre@
local middleStroke : include : fraktur-stroke M
virt [deco.xp : mix 0.5 1 PHexBot] body.bot
corner deco.xMid [pre@slope SlopeB]
~~~ [Wave.vDistAfter : 0.375 * Wave.DepthX]
corner body.xMid (body.top - 0.5 * Wave.DepthY)

View file

@ -92,7 +92,7 @@ glyph-block LetterLike-Fraktur-Upper-HKR : begin
# Left stroke
include : fraktur-stroke F
g2.ru.start post@ ([rDeco.yp 0.625] - 2 * F.thick)
~~~ [Wave.vc Wave.DepthX]
~~~ [Wave.vc Wave.LTDecoSize]
g2.ru.mid rDeco.left (post@ <-> DecoSizeY) [change-profile S]
arch.rhs (blendPre -- {}) rBody.top 0.625
flat rBody.left (pre@ <-> 0.6 * ArchDepthA)

View file

@ -0,0 +1,86 @@
$$include '../../meta/macros.ptl'
import [mix fallback] from "@iosevka/util"
glyph-module
glyph-block LetterLike-Fraktur-Upper-MNP : begin
glyph-block-import Common-Derivatives
glyph-block-import CommonShapes
glyph-block-import LetterLike-Fraktur-Common : FrakDf S M F T fraktur-stroke change-profile
glyph-block-import LetterLike-Fraktur-Common : DecoSizeX DecoSizeY SlopeA SlopeB CutMaskLeft
glyph-block-import LetterLike-Fraktur-Common : Wave LbFootRise FHook PHexTop PHexBot
define [deriveBoxes box] : begin
local body : box.padLeft (+1.50 * DecoSizeX)
local deco : box.padLeft (-0.25 * DecoSizeX)
return { body deco }
define [LeftStroke box profile] : glyph-proc
local { body deco } : deriveBoxes box
local [knots] : list
g2.ru.start (post@) ([deco.yp 0.625] - 2 * F.thick) [change-profile F]
~~~ [Wave.vc Wave.LTDecoSize]
g2.ru.mid deco.left (post@ <-> DecoSizeY) [change-profile profile]
arch.rhs (sw -- profile.thick) (blendPre -- null) deco.top 0.4
flat body.left (pre@ <-> ArchDepthA)
curl pre@ (post@ <+> ArchDepthB)
corner (deco.left + 0.5 * DecoSizeX) deco.bot
corner (pre@ <-> DecoSizeX) (pre@ <+> DecoSizeY)
local s : include : fraktur-stroke profile [knots]
return : object
maskLeft : function [] : fraktur-stroke CutMaskLeft [knots]
create-glyph 'frak/M' 0x1D510 : glyph-proc
local df : include : FrakDf para.diversityM 3
include : df.markSet.capital
local box : M.box CAP 0 df.leftSB df.rightSB
local { body deco } : deriveBoxes box
local leftStroke : include : LeftStroke box M
local rightStroke : include : fraktur-stroke M
corner (post@ <+> DecoSizeX) (post@ <+> DecoSizeY)
corner (body.right + 0.25 * DecoSizeX) body.bottom
~~~ [straight.up.mid (pre@ <-> Wave.DepthX) [mix@ 0.5]]
corner (pre@ <+> 0.25 * DecoSizeX) ([body.yp 0.75] + S.thick)
~~~ [curl [pre@tang-in 1] [pre@tang-in SlopeB]]
g2 (pre@ <-> 0.75 * Wave.DepthX) [mix@ 0.5]
arch.rhs (sw -- M.thick) (blendPre -- {}) body.top
corner (body.xMid - 0.25 * Wave.DepthX) (body.top - 0.5 * Wave.DepthY)
~~~ [arch.rhs (sw -- M.thick) (blendPre -- {}) (blendPost -- {}) body.top]
corner body.left pre@
local middleStroke : include : fraktur-stroke M
corner (post@ <-> DecoSizeX) (post@ <+> DecoSizeY)
corner deco.xMid deco.bot
flat post@ [mix@ 0.5]
# flat post@ (pre@ <+> ArchDepthB)
flat post@ ([body.yp 0.75] + S.thick)
curl (body.xMid - 0.25 * Wave.DepthX) (body.top - 0.5 * Wave.DepthY)
create-glyph 'frak/N' 0x1D511 : glyph-proc
local df : include : FrakDf 1
include : df.markSet.capital
local box : S.box CAP 0 df.leftSB df.rightSB
local { body deco } : deriveBoxes box
local leftStroke : include : LeftStroke box S
local rightStroke : include : difference
fraktur-stroke S
corner (post@ <+> DecoSizeX) (post@ <+> DecoSizeY)
corner (body.right + 0.25 * DecoSizeX) body.bottom
~~~ [straight.up.mid (pre@ <-> Wave.DepthX) [mix@ 0.5]]
corner pre@ ([body.yp 0.75] + S.thick)
~~~ [curl [pre@tang-in 1] [pre@tang-in SlopeB]]
g2 (pre@ <-> Wave.DepthX) [mix@ 0.5]
arch.rhs (sw -- S.thick) (blendPre -- {}) body.top
corner (body.left - S.thick) (pre@ <-> ArchDepthA)
leftStroke.maskLeft

View file

@ -6,11 +6,12 @@ import { Point } from "./point.mjs";
import { MonoKnot } from "./spiro-to-outline.mjs";
export class PenKnotCollector {
constructor(gizmo, defaultProfile) {
constructor(gizmo, defaultProfile, fProfileFixed) {
this.gizmo = gizmo;
this.m_profile = defaultProfile;
this.m_lastKnot = null;
this.m_finished = false;
this.m_profileFixed = fProfileFixed;
this.knots = [];
this.closed = false;
@ -35,6 +36,7 @@ export class PenKnotCollector {
setContrast() {}
setProfile(profile) {
if (this.m_profileFixed) return;
if (profile.length !== this.m_profile.length)
throw new Error("Pen profile length mismatch");
if (this.m_lastKnot) this.m_lastKnot.profile = profile;