From 58530575cb5c8267a3c2d6ca80d57981e0b7fc69 Mon Sep 17 00:00:00 2001 From: Belleve Date: Fri, 2 Aug 2024 00:02:19 -1000 Subject: [PATCH] Add (#2452) - 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`). --- changes/31.1.0.md | 14 +- .../font-glyphs/src/letter-like/fraktur.ptl | 2 + .../src/letter-like/fraktur/common.ptl | 44 ++++-- .../src/letter-like/fraktur/upper-bvw.ptl | 135 ++++++++++++++++++ .../src/letter-like/fraktur/upper-hkr.ptl | 2 +- .../src/letter-like/fraktur/upper-mnp.ptl | 86 +++++++++++ packages/geometry/src/spiro-pen-expand.mjs | 4 +- 7 files changed, 273 insertions(+), 14 deletions(-) create mode 100644 packages/font-glyphs/src/letter-like/fraktur/upper-bvw.ptl create mode 100644 packages/font-glyphs/src/letter-like/fraktur/upper-mnp.ptl diff --git a/changes/31.1.0.md b/changes/31.1.0.md index a072d17b5..7de5b5bcc 100644 --- a/changes/31.1.0.md +++ b/changes/31.1.0.md @@ -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. diff --git a/packages/font-glyphs/src/letter-like/fraktur.ptl b/packages/font-glyphs/src/letter-like/fraktur.ptl index 177ac9c9b..8be7bc85d 100644 --- a/packages/font-glyphs/src/letter-like/fraktur.ptl +++ b/packages/font-glyphs/src/letter-like/fraktur.ptl @@ -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" diff --git a/packages/font-glyphs/src/letter-like/fraktur/common.ptl b/packages/font-glyphs/src/letter-like/fraktur/common.ptl index 91ae85a2e..2d7335207 100644 --- a/packages/font-glyphs/src/letter-like/fraktur/common.ptl +++ b/packages/font-glyphs/src/letter-like/fraktur/common.ptl @@ -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)) diff --git a/packages/font-glyphs/src/letter-like/fraktur/upper-bvw.ptl b/packages/font-glyphs/src/letter-like/fraktur/upper-bvw.ptl new file mode 100644 index 000000000..5df6b2af7 --- /dev/null +++ b/packages/font-glyphs/src/letter-like/fraktur/upper-bvw.ptl @@ -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) diff --git a/packages/font-glyphs/src/letter-like/fraktur/upper-hkr.ptl b/packages/font-glyphs/src/letter-like/fraktur/upper-hkr.ptl index 743e2bb25..406f05587 100644 --- a/packages/font-glyphs/src/letter-like/fraktur/upper-hkr.ptl +++ b/packages/font-glyphs/src/letter-like/fraktur/upper-hkr.ptl @@ -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) diff --git a/packages/font-glyphs/src/letter-like/fraktur/upper-mnp.ptl b/packages/font-glyphs/src/letter-like/fraktur/upper-mnp.ptl new file mode 100644 index 000000000..7b562b2d6 --- /dev/null +++ b/packages/font-glyphs/src/letter-like/fraktur/upper-mnp.ptl @@ -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 diff --git a/packages/geometry/src/spiro-pen-expand.mjs b/packages/geometry/src/spiro-pen-expand.mjs index 8fcdcc303..45af7dc2a 100644 --- a/packages/geometry/src/spiro-pen-expand.mjs +++ b/packages/geometry/src/spiro-pen-expand.mjs @@ -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;