More refactor

This commit is contained in:
be5invis 2023-05-24 00:42:05 -07:00
parent 09d80208a8
commit 2890a4cd00
16 changed files with 1085 additions and 1436 deletions

View file

@ -695,7 +695,7 @@ i = "serifless"
j = "flat-hook-serifless" j = "flat-hook-serifless"
k = "straight-serifless" k = "straight-serifless"
l = "serifless" l = "serifless"
r = "compact" r = "compact-serifless"
t = "flat-hook" t = "flat-hook"
u = "toothed-serifless" u = "toothed-serifless"
w = "straight-flat-top-serifless" w = "straight-flat-top-serifless"
@ -727,7 +727,7 @@ i = "serifed"
j = "flat-hook-serifed" j = "flat-hook-serifed"
k = "straight-serifless" k = "straight-serifless"
l = "serifed" l = "serifed"
r = "compact" r = "compact-serifless"
t = "flat-hook" t = "flat-hook"
u = "toothed-serifless" u = "toothed-serifless"
w = "straight-flat-top-serifless" w = "straight-flat-top-serifless"

View file

@ -1,8 +1,10 @@
* \[**BREAKING**\] Add taller slash, broken slash and broken zero variants for Zero. As a result, current variants are reordered (#1307, #1509, #1678). * \[**BREAKING**\] Add taller slash, broken slash and broken zero variants for Zero. As a result, current variants are reordered (#1307, #1509, #1678).
* \[**BREAKING**\] Add above-baseline crossed variant for Q. As a result, current variants are reordered (#1533). * \[**BREAKING**\] Add above-baseline crossed variant for Q. As a result, current variants are reordered (#1533).
* \[**BREAKING**\] Rectify the variant atlas. As a result, if a character's variant list has motion-serifed, then it will have serifless and serifed variants: the serifed-ness will no longer be controlled by SLAB variable. The characters influenced are `M`, `N`, `P`, `R`, `U`, `V`, `W`, `b`, `h`, `m`, `n`, `p`, `q`, `u`, `v`, `w`, `y`. * \[**BREAKING**\] Rectify the variant atlas. As a result, if a character's variant list has motion-serifed, then it will have serifless and serifed variants: the serifed-ness will no longer be controlled by SLAB variable. The characters influenced are `M`, `N`, `P`, `R`, `U`, `V`, `W`, `b`, `h`, `m`, `n`, `p`, `q`, `u`, `v`, `w`, `y`.
* \[**BREAKING**\] Reordered the variants of the following letters: * \[**BREAKING**\] Renamed and/or reordered the variants of the following letters:
- `K`, `k`, Cyrillic Ka. - `K`, `k`, Cyrillic Ka.
- `r`.
- `W`, `w`.
* Add Characters: * Add Characters:
- CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN (`U+29BC`). - CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN (`U+29BC`).
- CIRCLED WHITE BULLET (`U+29BE`). - CIRCLED WHITE BULLET (`U+29BE`).

View file

@ -8,18 +8,11 @@ import [DesignParameters] from"../meta/aesthetics.mjs"
extern isFinite extern isFinite
import [mix linreg clamp fallback] from"../support/utils.mjs" import [mix linreg clamp fallback $NamedParameterPair$] from"../support/utils.mjs"
import [calculateMetrics setFontMetrics GenDivFrame] from"../meta/aesthetics.mjs" import [calculateMetrics setFontMetrics GenDivFrame] from"../meta/aesthetics.mjs"
$$include '../meta/macros.ptl' $$include '../meta/macros.ptl'
define [$NamedParameterPair$ l r] : begin
set this.left l
set this.right r
return this
define [$DoNothing$] nothing
export : define [buildGlyphs para recursive] : begin export : define [buildGlyphs para recursive] : begin
local glyphStore : new GlyphStore local glyphStore : new GlyphStore
@ -110,7 +103,6 @@ export : define [buildGlyphs para recursive] : begin
$assignUnicodeImpl$ $assignUnicodeImpl$
$defineGlyphBlockImpl$ $defineGlyphBlockImpl$
$execState$ $execState$
$DoNothing$
Metrics : Object.assign {.} Metrics Metrics : Object.assign {.} Metrics
para para
recursive recursive

View file

@ -1,6 +1,6 @@
$$include '../../../meta/macros.ptl' $$include '../../../meta/macros.ptl'
import [mix linreg clamp fallback] from"../../../support/utils.mjs" import [mix linreg clamp fallback SuffixCfg] from"../../../support/utils.mjs"
import [Dotless CvDecompose MathSansSerif] from"../../../support/gr.mjs" import [Dotless CvDecompose MathSansSerif] from"../../../support/gr.mjs"
glyph-module glyph-module
@ -149,29 +149,38 @@ glyph-block Letter-Latin-Lower-R : begin
curl (xBar - Stroke * HVContrast) 0 [heading Downward] curl (xBar - Stroke * HVContrast) 0 [heading Downward]
if doBottomSerif : include : rBottomSerif 0 if doBottomSerif : include : rBottomSerif 0
define SmallRConfig : object define [FlapHooklessShape df md doTopSerif doBottomSerif] : glyph-proc
'serifless' { StandardShape dfN rStraight { 0 0 } } define [object xBar rBottomSerif xArchMiddle setMarks] : RDim df md
'serifed' { StandardShape dfN rSerifed { 1 1 } } set-base-anchor 'overlay' (xBar - 0.5 * Stroke * HVContrast) (XH / 2)
'topSerifed' { StandardShape dfN rSerifed { 1 0 } } include : setMarks doTopSerif
'baseSerifed' { StandardShape dfN rSerifed { 0 1 } } include : dispiro
'earlessCorner' { EarlessCornerShape dfN rEarless { 0 0 } } widths.lhs
'earlessCornerSerifed' { EarlessCornerShape dfN rEarless { 0 1 } } g4.left.start (xArchMiddle - CorrectionOMidS * [linreg 72 0.75 108 1 Stroke]) (XH - O)
'earlessRounded' { EarlessRoundedShape dfN rEarless { 0 0 } } archv
'earlessRoundedSerifed' { EarlessRoundedShape dfN rEarless { 0 1 } } flat (xBar - Stroke * HVContrast) (XH - SmallArchDepthA)
'hookless' { CompactShape dfN rNarrow { 0 0 } } curl (xBar - Stroke * HVContrast) 0 [heading Downward]
'hooklessSerifed' { CompactShape dfN rNarrowSerifed { 1 1 } } if doBottomSerif : include : rBottomSerif 0
'hooklessTopSerifed' { CompactShape dfN rNarrowSerifed { 1 0 } }
'hooklessBaseSerifed' { CompactShape dfN rNarrowSerifed { 0 1 } }
'compact' { CompactShape dfR rNarrow { 0 0 } }
'compactSerifed' { CompactShape dfR rNarrowSerifed { 1 1 } }
'compactTopSerifed' { CompactShape dfR rNarrowSerifed { 1 0 } }
'compactBaseSerifed' { CompactShape dfR rNarrowSerifed { 0 1 } }
'cornerHooked' { CornerHookShape dfN rCornerHooked { 0 0 } }
'cornerHookedSerifed' { CornerHookShape dfN rCornerHookedSerifed { 1 1 } }
'cornerHookedTopSerifed' { CornerHookShape dfN rCornerHookedSerifed { 1 0 } }
'cornerHookedBaseSerifed' { CornerHookShape dfN rCornerHookedSerifed { 0 1 } }
foreach { suffix { F df mode { doTS doBS } } } [Object.entries SmallRConfig] : do define SmallRConfig : SuffixCfg.weave
# Body
object
'' { StandardShape dfN rStraight }
earlessCorner { EarlessCornerShape dfN rEarless }
earlessRounded { EarlessRoundedShape dfN rEarless }
hookless { CompactShape dfN rNarrow }
cornerHooked { CornerHookShape dfN rCornerHooked }
compact { CompactShape dfR rNarrow }
hooklessFlap { FlapHooklessShape dfN rNarrow }
compactFlap { FlapHooklessShape dfR rNarrow }
# Serifs
object
serifless { 0 0 }
topSerifed { 1 0 }
baseSerifed { 0 1 }
serifed { 1 1 }
foreach { suffix { {F df mode} {doTS doBS} } } [pairs-of SmallRConfig] : do
create-glyph "r.\(suffix)" : glyph-proc create-glyph "r.\(suffix)" : glyph-proc
set-width df.width set-width df.width
include : df.markSet.e include : df.markSet.e
@ -256,34 +265,5 @@ glyph-block Letter-Latin-Lower-R : begin
include : dfR.markSet.e include : dfR.markSet.e
include : BBRShape dfN rStraight 0 0 include : BBRShape dfN rStraight 0 0
select-variant 'rFlap' 0x27E (shapeFrom -- 'r')
create-glyph 'rFlap.serifless' : glyph-proc
set-width dfN.width
include : dfN.markSet.e
define [object rBottomSerif] : RDim dfN rEarless
include : EarlessRoundedShape dfN rEarless 0 0
create-forked-glyph 'rFlap.serifed' : rBottomSerif 0
define [rFlapHooklessShape df] : glyph-proc
include : df.markSet.e
define [object xBar rBottomSerif xArchMiddle] : RDim df rNarrow
set-base-anchor 'overlay' (xBar - 0.5 * Stroke * HVContrast) (XH / 2)
include : dispiro
widths.lhs
g4.left.start (xArchMiddle - CorrectionOMidS * [linreg 72 0.75 108 1 Stroke]) (XH - O)
archv
flat (xBar - Stroke * HVContrast) (XH - SmallArchDepthA)
curl (xBar - Stroke * HVContrast) 0 [heading Downward]
if SLAB : include : rBottomSerif 0
create-glyph 'rFlap.hookless' : glyph-proc
set-width dfN.width
include : rFlapHooklessShape dfN
create-glyph 'rFlap.compact' : glyph-proc
set-width dfR.width
include : rFlapHooklessShape dfR
select-variant 'rFlap' 0x27E
CreateAccentedComposition 'rFlapTildeOver' 0x1D73 'rFlap' 'tildeOver' CreateAccentedComposition 'rFlapTildeOver' 0x1D73 'rFlap' 'tildeOver'

View file

@ -1,6 +1,6 @@
$$include '../../../meta/macros.ptl' $$include '../../../meta/macros.ptl'
import [mix linreg clamp fallback] from"../../../support/utils.mjs" import [mix fallback SuffixCfg] from"../../../support/utils.mjs"
import [Dotless CvDecompose] from"../../../support/gr.mjs" import [Dotless CvDecompose] from"../../../support/gr.mjs"
glyph-module glyph-module
@ -207,26 +207,19 @@ glyph-block Letter-Latin-Lower-T : begin
include : VBar.m df.middle 0 top include : VBar.m df.middle 0 top
include : HCrossBar.top df.middle (df.middle + df.div * LongJut) yCrossBar include : HCrossBar.top df.middle (df.middle + df.div * LongJut) yCrossBar
define SmallTConfig : object define SmallTConfig :SuffixCfg.weave
standard { [DivFrame 1] Standard Ascender } object # body
diagonalTailed { dfNarrowT DiagTail Ascender } standard { [DivFrame 1] Standard }
flatHook { dfNarrowT Flat Ascender } diagonalTailed { dfNarrowT DiagTail }
cross { dfNarrowT Cross Ascender } flatHook { dfNarrowT Flat }
hooklessAsymmetric { dfNarrowT HooklessAsymmetric Ascender } cross { dfNarrowT Cross }
hooklessAsymmetric { dfNarrowT HooklessAsymmetric }
object # height
"" Ascender
shortNeck yShortNeck1
shortNeck2 yShortNeck2
standardShortNeck { [DivFrame 1] Standard yShortNeck1 } foreach { suffix { {df Style} top } } [pairs-of SmallTConfig] : do
diagonalTailedShortNeck { dfNarrowT DiagTail yShortNeck1 }
flatHookShortNeck { dfNarrowT Flat yShortNeck1 }
crossShortNeck { dfNarrowT Cross yShortNeck1 }
hooklessAsymmetricShortNeck { dfNarrowT HooklessAsymmetric yShortNeck1 }
standardShortNeck2 { [DivFrame 1] Standard yShortNeck2 }
diagonalTailedShortNeck2 { dfNarrowT DiagTail yShortNeck2 }
flatHookShortNeck2 { dfNarrowT Flat yShortNeck2 }
crossShortNeck2 { dfNarrowT Cross yShortNeck2 }
hooklessAsymmetricShortNeck2 { dfNarrowT HooklessAsymmetric yShortNeck2 }
foreach { suffix { df Style top } } [Object.entries SmallTConfig] : do
create-glyph "t.\(suffix)" : glyph-proc create-glyph "t.\(suffix)" : glyph-proc
set-width df.width set-width df.width
include : df.markSet.b include : df.markSet.b

View file

@ -1,6 +1,6 @@
$$include '../../../meta/macros.ptl' $$include '../../../meta/macros.ptl'
import [mix linreg clamp fallback] from"../../../support/utils.mjs" import [mix fallback SuffixCfg] from"../../../support/utils.mjs"
import [Dotless CvDecompose MathSansSerif] from"../../../support/gr.mjs" import [Dotless CvDecompose MathSansSerif] from"../../../support/gr.mjs"
glyph-module glyph-module
@ -323,43 +323,32 @@ glyph-block Letter-Latin-W : begin
define [WCursiveImpl df top bodyType serifsType] : WCursiveImplImpl false df top bodyType serifsType define [WCursiveImpl df top bodyType serifsType] : WCursiveImplImpl false df top bodyType serifsType
define [WHookTopCursive df top bodyType serifsType] : WCursiveImplImpl true df top bodyType serifsType define [WHookTopCursive df top bodyType serifsType] : WCursiveImplImpl true df top bodyType serifsType
define WConfig : object define WConfig : SuffixCfg.weave
cyrlCapialOmega { WShapeImpl WHooktopShape FORM-CYRL-OMEGA SERIFS-CYRL-OMEGA } # Body
cyrlSmallOmega { WShapeImpl WHooktopShape FORM-CYRL-OMEGA SERIFS-CURSIVE } object
straight { WShapeImpl WHooktopShape FORM-STRAIGHT }
straightAsymmetric { WShapeImpl WHooktopShape FORM-ASYMMETRIC }
straightDoubleV { WShapeImpl WHooktopShape FORM-DOUBLE-V }
straightFlatTop { WShapeImpl WHooktopShape FORM-FLAT-TOP }
straightVerticalSides { WVertSides WVSHookTopShape FORM-STRAIGHT }
curly { WShapeImpl WHooktopShape FORM-CURLY }
cursive { WCursiveImpl WHookTopCursive FORM-CURLY }
cyrlCapialOmega { WShapeImpl WHooktopShape FORM-CYRL-OMEGA }
cyrlSmallOmega { WShapeImpl WHooktopShape FORM-CYRL-OMEGA }
straightAsymmetric { WShapeImpl WHooktopShape FORM-ASYMMETRIC SERIFS-ASYMMETRIC } # Serifs
straightDoubleV { WShapeImpl WHooktopShape FORM-DOUBLE-V SERIFS-DOUBLE-V } function [body] : if (body == 'cyrlCapialOmega' || body == 'cyrlSmallOmega')
straightFlatTop { WShapeImpl WHooktopShape FORM-FLAT-TOP SERIFS-AUTO } then : object ["" SERIFS-CYRL-OMEGA]
straight { WShapeImpl WHooktopShape FORM-STRAIGHT SERIFS-AUTO } else : object
straightVerticalSides { WVertSides WVSHookTopShape FORM-STRAIGHT SERIFS-AUTO } serifless SERIFS-NONE
curly { WShapeImpl WHooktopShape FORM-CURLY SERIFS-AUTO } motionSerifed SERIFS-MOTION
cursive { WCursiveImpl WHookTopCursive FORM-CURLY SERIFS-CURSIVE } serifed : match body
[Just 'straightAsymmetric'] SERIFS-ASYMMETRIC-ALL
[Just 'straightDoubleV'] SERIFS-DOUBLE-V-ALL
[Just 'cursive'] SERIFS-MOTION
__ SERIFS-ALL
straightAsymmetricSerifless { WShapeImpl WHooktopShape FORM-ASYMMETRIC SERIFS-NONE } foreach { suffix { {implT hookTopImplT bodyType} slabType } } [pairs-of WConfig] : do
straightDoubleVSerifless { WShapeImpl WHooktopShape FORM-DOUBLE-V SERIFS-NONE }
straightFlatTopSerifless { WShapeImpl WHooktopShape FORM-FLAT-TOP SERIFS-NONE }
straightVerticalSidesSerifless { WVertSides WVSHookTopShape FORM-STRAIGHT SERIFS-NONE }
straightSerifless { WShapeImpl WHooktopShape FORM-STRAIGHT SERIFS-NONE }
curlySerifless { WShapeImpl WHooktopShape FORM-CURLY SERIFS-NONE }
cursiveSerifless { WCursiveImpl WHookTopCursive FORM-CURLY SERIFS-NONE }
straightAsymmetricMotionSerifed { WShapeImpl WHooktopShape FORM-ASYMMETRIC SERIFS-MOTION }
straightDoubleVMotionSerifed { WShapeImpl WHooktopShape FORM-DOUBLE-V SERIFS-MOTION }
straightFlatTopMotionSerifed { WShapeImpl WHooktopShape FORM-FLAT-TOP SERIFS-MOTION }
straightVerticalSidesMotionSerifed { WVertSides WVSHookTopShape FORM-STRAIGHT SERIFS-MOTION }
straightMotionSerifed { WShapeImpl WHooktopShape FORM-STRAIGHT SERIFS-MOTION }
curlyMotionSerifed { WShapeImpl WHooktopShape FORM-CURLY SERIFS-MOTION }
cursiveMotionSerifed { WCursiveImpl WHookTopCursive FORM-CURLY SERIFS-MOTION }
straightAsymmetricSerifed { WShapeImpl WHooktopShape FORM-ASYMMETRIC SERIFS-ASYMMETRIC-ALL }
straightDoubleVSerifed { WShapeImpl WHooktopShape FORM-DOUBLE-V SERIFS-DOUBLE-V-ALL }
straightFlatTopSerifed { WShapeImpl WHooktopShape FORM-FLAT-TOP SERIFS-ALL }
straightVerticalSidesSerifed { WVertSides WVSHookTopShape FORM-STRAIGHT SERIFS-ALL }
straightSerifed { WShapeImpl WHooktopShape FORM-STRAIGHT SERIFS-ALL }
curlySerifed { WShapeImpl WHooktopShape FORM-CURLY SERIFS-ALL }
cursiveSerifed { WCursiveImpl WHookTopCursive FORM-CURLY SERIFS-MOTION }
foreach { suffix { implT hookTopImplT bodyType slabType } } [Object.entries WConfig] : do
create-glyph "W.\(suffix)" : glyph-proc create-glyph "W.\(suffix)" : glyph-proc
local df : DivFrame para.diversityM 3 local df : DivFrame para.diversityM 3
set-width df.width set-width df.width

View file

@ -1,6 +1,6 @@
$$include '../../meta/macros.ptl' $$include '../../meta/macros.ptl'
import [mix linreg clamp fallback] from"../../support/utils.mjs" import [mix clamp fallback SuffixCfg] from"../../support/utils.mjs"
import [AnyCv getGrMesh VS01] from"../../support/gr.mjs" import [AnyCv getGrMesh VS01] from"../../support/gr.mjs"
glyph-module glyph-module
@ -105,8 +105,8 @@ glyph-block Digits-Zero : begin
define [BrokenVerticalBar top] : difference define [BrokenVerticalBar top] : difference
VBar.m Middle (0 + O) (top - O) [Math.min (CircleInnerWidth * 0.375) OverlayStroke] VBar.m Middle (0 + O) (top - O) [Math.min (CircleInnerWidth * 0.375) OverlayStroke]
intersection intersection
MaskAbove (top * (1/2 + 1/16)) MaskAbove (top * (1/2 - 1/16))
MaskBelow (top * (1/2 - 1/16)) MaskBelow (top * (1/2 + 1/16))
define [ZeroDotShape top] : begin define [ZeroDotShape top] : begin
local halfDotWidth : Math.min DotRadius (CircleInnerWidth / 4) local halfDotWidth : Math.min DotRadius (CircleInnerWidth / 4)
@ -150,50 +150,48 @@ glyph-block Digits-Zero : begin
Middle + halfDotWidth - OX Middle + halfDotWidth - OX
begin 0 begin 0
define ZeroConfig : object define ZeroConfig : SuffixCfg.weave
'unslashed' { null null } object # outline shape
'slashed' { ZeroSlash null } '' { ZeroOutlineShape ZeroOutlineMask }
'reverseSlashed' { ZeroRevSlash null } 'oval' { ZeroOvalShape ZeroOvalMask }
'tallSlashed' { ZeroTallSlash null } object # overlay/cutout
'tallReverseSlashed' { ZeroTallRevSlash null } 'unslashed' { null null }
'dotted' { ZeroDotShape null } 'slashed' { ZeroSlash null }
'longDotted' { ZeroLongDotShape null } 'reverseSlashed' { ZeroRevSlash null }
'slashedSplit' { ZeroSlash InsetShape } 'tallSlashed' { ZeroTallSlash null }
'reverseSlashedSplit' { ZeroRevSlash InsetShape } 'tallReverseSlashed' { ZeroTallRevSlash null }
'brokenSlash' { BrokenTallSlash null } 'dotted' { ZeroDotShape null }
'brokenReverseSlash' { BrokenTallRevSlash null } 'longDotted' { ZeroLongDotShape null }
'brokenVerticalBar' { BrokenVerticalBar null } 'slashedSplit' { ZeroSlash InsetShape }
'slashedCutout' { CutoutSlash Cutout } 'reverseSlashedSplit' { ZeroRevSlash InsetShape }
'reverseSlashedCutout' { CutoutRevSlash Cutout } 'brokenSlash' { BrokenTallSlash null }
'tallSlashedCutout' { CutoutTallSlash Cutout } 'brokenReverseSlash' { BrokenTallRevSlash null }
'tallReverseSlashedCutout' { CutoutTallRevSlash Cutout } 'brokenVerticalBar' { BrokenVerticalBar null }
'verticalBarCutout' { CutoutVerticalBar Cutout } 'slashedCutout' { CutoutSlash Cutout }
'topRightCutout' { TopRightCutoutSlash Cutout } 'reverseSlashedCutout' { CutoutRevSlash Cutout }
'tallSlashedCutout' { CutoutTallSlash Cutout }
'tallReverseSlashedCutout' { CutoutTallRevSlash Cutout }
'verticalBarCutout' { CutoutVerticalBar Cutout }
'topRightCutout' { TopRightCutoutSlash Cutout }
define Shapes : object define Heights : object
'' { ZeroOutlineShape ZeroOutlineMask }
'Oval' { ZeroOvalShape ZeroOvalMask }
define Infixes : object
'lnum' { CAP [function [] : MarkSet.capital] } 'lnum' { CAP [function [] : MarkSet.capital] }
'onum' { OnumHeight [function [] : OnumMarks.e] } 'onum' { OnumHeight [function [] : OnumMarks.e] }
foreach { shapeSuffix { Outline Mask } } [Object.entries Shapes] : begin foreach { suffix { {Outline Mask} {Overlay Postproc} } } [pairs-of ZeroConfig] : begin
foreach { infix { height Marks } } [Object.entries Infixes] : begin foreach { infix { height Marks } } [pairs-of Heights] : begin
local zeroShape : Outline height create-glyph "zero.\(infix).\(suffix)" : glyph-proc
foreach { suffix { Overlay Postproc } } [Object.entries ZeroConfig] : begin include : Marks
create-glyph "zero.\(infix).\(suffix)\(shapeSuffix)" : glyph-proc local zeroShape : Outline height
include : Marks local overlayShape : if Overlay [Overlay height] null
if Postproc
local overlayShape : if Overlay [Overlay height] null : then : begin
if Postproc include : Postproc zeroShape overlayShape Mask height
: then : begin : else : begin
include : Postproc zeroShape overlayShape Mask height include zeroShape
: else : begin if Overlay : if Mask
include zeroShape include : intersection overlayShape : Mask height
if Overlay : if Mask include overlayShape
include : intersection overlayShape : Mask height
include overlayShape
select-variant 'zero.lnum' [CodeLnum '0'] (follow -- 'zero') select-variant 'zero.lnum' [CodeLnum '0'] (follow -- 'zero')
select-variant 'zero.onum' [CodeOnum '0'] (follow -- 'zero') select-variant 'zero.onum' [CodeOnum '0'] (follow -- 'zero')

View file

@ -1,6 +1,11 @@
### Autoarg macro ### Autoarg macro
define-operator "--" 890 'right' : syntax-rules define-operator "--" 890 'right' : syntax-rules
`(@l -- @r) [atom l] : dirty `[new $NamedParameterPair$ @{".quote" [formOf l]} @r] `(@l -- @r) [atom l] : dirty `[new $NamedParameterPair$ @{".quote" [formOf l]} @r]
`(@{".quote" l} -- @r) : dirty `[new $NamedParameterPair$ @l @r]
### Arbitrary pair operator
define-operator "~>" 880 'right' : syntax-rules
`(@l ~> @r) `{.left @l .right @r}
### Macro for identity match ### Macro for identity match
define-macro Just : begin define-macro Just : begin
@ -30,7 +35,7 @@ define-macro params : syntax-rules
local declarations `[begin] local declarations `[begin]
local namedAssigns `[begin] local namedAssigns `[begin]
local indexAssigns `[begin] local indexAssigns `[begin]
local tearDowns `[begin] local tearDowns `[begin]
local j 0 local j 0
foreach [pf : items-of : formOf _pairs] : begin foreach [pf : items-of : formOf _pairs] : begin
@ -204,14 +209,13 @@ define-macro glyph-block : syntax-rules
([typeof form] === "string") : set variableSet.(form) true ([typeof form] === "string") : set variableSet.(form) true
traceBody body traceBody body
traceBody `[$NamedParameterPair$ $DoNothing$ $createAndSaveGlyphImpl$ $assignUnicodeImpl$] traceBody `[$NamedParameterPair$ $createAndSaveGlyphImpl$ $assignUnicodeImpl$ $execState$]
set externEnv.$glyphBlockVariableUsage$ variableSet set externEnv.$glyphBlockVariableUsage$ variableSet
define captureImports `[$createAndSaveGlyphImpl$ $NamedParameterPair$ define captureImports `[$createAndSaveGlyphImpl$ $NamedParameterPair$ $assignUnicodeImpl$
$assignUnicodeImpl$ $DoNothing$ $execState$ $execState$ Metrics para recursive glyphStore glyph-is-needed SpiroFns BooleFns
Metrics para recursive glyphStore glyph-is-needed SpiroFns BooleFns MarkSet AS_BASE MarkSet AS_BASE ALSO_METRICS buildGlyphs tagged DivFrame fontMetrics]
ALSO_METRICS buildGlyphs tagged DivFrame fontMetrics]
define metricImports `[DesignParameters UPM HalfUPM Width SB CAP XH Ascender Descender define metricImports `[DesignParameters UPM HalfUPM Width SB CAP XH Ascender Descender
Contrast SymbolMid ParenTop ParenBot OperTop OperBot TackTop TackBot PlusTop PlusBot Contrast SymbolMid ParenTop ParenBot OperTop OperBot TackTop TackBot PlusTop PlusBot

View file

@ -1,12 +1,11 @@
$$include '../meta/macros.ptl'
import [AddCommonFeature AddFeature AddLookup AddFeatureLookup ChainRuleBuilder BeginLookupBlock EndLookupBlock UkMapToLookup UkMap2ToLookup] from"./table-util.mjs" import [AddCommonFeature AddFeature AddLookup AddFeatureLookup ChainRuleBuilder BeginLookupBlock EndLookupBlock UkMapToLookup UkMap2ToLookup] from"./table-util.mjs"
import [AnyCv Dotless TieMark TieGlyph OgonekTrY IsSuperscript IsSubscript] from"../support/gr.mjs" import [AnyCv Dotless TieMark TieGlyph OgonekTrY IsSuperscript IsSubscript] from"../support/gr.mjs"
import as UnicodeKnowledge from"../meta/unicode-knowledge.mjs" import as UnicodeKnowledge from"../meta/unicode-knowledge.mjs"
extern Set extern Set
define-operator "~>" 880 'right' : syntax-rules
`(@l ~> @r) `{.left @l .right @r}
define-macro Ccmp-Group : syntax-rules define-macro Ccmp-Group : syntax-rules
`[Ccmp-Group @description @body] `[Ccmp-Group @description @body]
dirty `[$ExecCcmpGroup$ [function [export-lookup chain-rule] @[formOf body]]] dirty `[$ExecCcmpGroup$ [function [export-lookup chain-rule] @[formOf body]]]

View file

@ -1,3 +1,5 @@
$$include '../meta/macros.ptl'
import [AddLookup AddCommonFeature PickCommonFeature AddFeatureLookup PickLookup BeginLookupBlock EndLookupBlock ChainRuleBuilder] from"./table-util.mjs" import [AddLookup AddCommonFeature PickCommonFeature AddFeatureLookup PickLookup BeginLookupBlock EndLookupBlock ChainRuleBuilder] from"./table-util.mjs"
import [Cv AnyCv CvDecompose RightDependentLink RightDependentTrigger] from"../support/gr.mjs" import [Cv AnyCv CvDecompose RightDependentLink RightDependentTrigger] from"../support/gr.mjs"
@ -5,8 +7,6 @@ extern Map
extern Set extern Set
define look-around null define look-around null
define-operator "~>" 880 'right' : syntax-rules
`(@l ~> @r) `{.left @l .right @r}
define [FeatureName tag] : tag + '_cvss' define [FeatureName tag] : tag + '_cvss'
define [SsLookupName tag] : 'lookup_ss_' + tag define [SsLookupName tag] : 'lookup_ss_' + tag

View file

@ -1,9 +1,8 @@
$$include '../meta/macros.ptl'
import [AddCommonFeature AddFeature AddLookup BeginLookupBlock EndLookupBlock ChainRuleBuilder] from"./table-util.mjs" import [AddCommonFeature AddFeature AddLookup BeginLookupBlock EndLookupBlock ChainRuleBuilder] from"./table-util.mjs"
import [NumeratorForm DenominatorForm] from"../support/gr.mjs" import [NumeratorForm DenominatorForm] from"../support/gr.mjs"
define-operator "~>" 880 'right' : syntax-rules
`(@l ~> @r) `{.left @l .right @r}
# Name-driven feature pairs # Name-driven feature pairs
export : define [buildFrac sink glyphStore] : begin export : define [buildFrac sink glyphStore] : begin
local rec : BeginLookupBlock sink local rec : BeginLookupBlock sink

View file

@ -1,10 +1,9 @@
$$include '../meta/macros.ptl'
import [AddCommonFeature AddFeature ChainRuleBuilder BeginLookupBlock EndLookupBlock] from"./table-util.mjs" import [AddCommonFeature AddFeature ChainRuleBuilder BeginLookupBlock EndLookupBlock] from"./table-util.mjs"
extern Map extern Map
extern Set extern Set
define-operator "~>" 880 'right' : syntax-rules
`(@l ~> @r) `{.left @l .right @r}
define [arrowBarX s] : lambda [t] : t.map : lambda [x] "\(x).arrowBar.\(s)" define [arrowBarX s] : lambda [t] : t.map : lambda [x] "\(x).arrowBar.\(s)"
define [lsx s] : lambda [t] : t.map : lambda [x] "\(x).lig.\(s)" define [lsx s] : lambda [t] : t.map : lambda [x] "\(x).lig.\(s)"
define [csx s] : lambda [t] : t.map : lambda [x] "\(x).\(s)" define [csx s] : lambda [t] : t.map : lambda [x] "\(x).\(s)"

View file

@ -1,7 +1,6 @@
import [AddCommonFeature AddFeature AddLookup ChainRuleBuilder QueryRelatedGlyphs BeginLookupBlock EndLookupBlock] from"./table-util.mjs" $$include '../meta/macros.ptl'
define-operator "~>" 880 'right' : syntax-rules import [AddCommonFeature AddFeature AddLookup ChainRuleBuilder QueryRelatedGlyphs BeginLookupBlock EndLookupBlock] from"./table-util.mjs"
`(@l ~> @r) `{.left @l .right @r}
export : define [buildGsubThousands sink para] : begin export : define [buildGsubThousands sink para] : begin
local rec : BeginLookupBlock sink local rec : BeginLookupBlock sink

View file

@ -34,28 +34,49 @@ export function joinCamel(a, b) {
return a + b[0].toUpperCase() + b.slice(1); return a + b[0].toUpperCase() + b.slice(1);
} }
function joinSuffixListImpl(sink, k, v, configs) { function joinSuffixListImpl(sink, k, v, telescope, configs) {
if (!configs.length) { if (!configs.length) {
sink[k] = v; sink[k] = v;
return; return;
} }
for (const [keySuffix, valueSuffix] of Object.entries(configs[0])) { let [item, ...rest] = configs;
if (item instanceof Function) item = item(...telescope);
if (!item) return;
for (const [keySuffix, valueSuffix] of Object.entries(item)) {
const k1 = joinCamel(k, keySuffix); const k1 = joinCamel(k, keySuffix);
const v1 = [...v, valueSuffix]; const v1 = [...v, valueSuffix];
joinSuffixListImpl(sink, k1, v1, configs.slice(1)); const telescope1 = [...telescope, keySuffix];
joinSuffixListImpl(sink, k1, v1, telescope1, rest);
} }
} }
export const SuffixCfg = { export const SuffixCfg = {
weave: function (...configs) { weave: function (...configs) {
let ans = {}; let ans = {};
joinSuffixListImpl(ans, "", [], configs); joinSuffixListImpl(ans, "", [], [], configs);
return ans; return ans;
}, },
combine: function (...configs) { combine: function (...configs) {
let ans = {}; let ans = {};
for (const item of configs) for (const [k, v] of Object.entries(item)) ans[k] = v; for (const item of configs) for (const [k, v] of Object.entries(item)) ans[k] = v;
return ans; return ans;
},
collect: function (pairs) {
let ans = {};
for (const pair of pairs) {
if (pair) ans[pair.left] = pair.right;
}
return ans;
} }
}; };
///////////////////////////////////////////////////////////////////////////////////////////////////
export class $NamedParameterPair$ {
constructor(l, r) {
this.left = l;
this.right = r;
}
}

View file

@ -261,55 +261,36 @@ class VbStageAlternative {
this.key = key; this.key = key;
this.rank = raw.rank; this.rank = raw.rank;
this.next = raw.next; this.next = raw.next;
if (key !== "*") this.keySuffix = raw.keySuffix ?? key; this.mode = raw.mode;
this.descriptionSuffix = raw.descriptionSuffix;
this.descriptionJoiner = raw.descriptionJoiner || "with";
this.disableIf = raw.disableIf; this.disableIf = raw.disableIf;
this.selectorSuffix = raw.selectorSuffix; if (key !== "*") this.keyAffix = raw.keyAffix ?? key;
this.descriptionAffix = raw.descriptionAffix;
this.descriptionJoiner = raw.descriptionJoiner || "with";
this.selectorAffix = raw.selectorAffix;
} }
fallback(defaultAlternative) { fallback(defaultAlternative) {
this.next = this.next || defaultAlternative.next; this.next = this.next || defaultAlternative.next;
this.keySuffix = this.keySuffix || defaultAlternative.keySuffix; this.mode = this.mode || defaultAlternative.mode || "append";
this.descriptionSuffix = this.descriptionSuffix || defaultAlternative.descriptionSuffix; this.keyAffix = this.keyAffix || defaultAlternative.keyAffix;
this.descriptionAffix = this.descriptionAffix || defaultAlternative.descriptionAffix;
this.descriptionJoiner = this.descriptionJoiner || defaultAlternative.descriptionJoiner; this.descriptionJoiner = this.descriptionJoiner || defaultAlternative.descriptionJoiner;
this.disableIf = this.disableIf || defaultAlternative.disableIf; this.disableIf = this.disableIf || defaultAlternative.disableIf;
this.selectorSuffix = this.selectorSuffix || defaultAlternative.selectorSuffix;
} }
tryAccept(globalState, localState) { tryAccept(globalState, localState) {
// Detect whether this alternative is applicable. // Reject if disable conditions match
if (this.disableIf) { if (this.shouldReject(localState)) return null;
for (const branch of this.disableIf) {
let statementMatches = true;
for (let [k, v] of Object.entries(branch)) {
v = v.trim();
if (/^NOT(?=\s)/.test(v)) {
v = v.slice(3).trim();
if (localState.assignments.get(k) === v) {
statementMatches = false;
break;
}
} else {
if (localState.assignments.get(k) !== v) {
statementMatches = false;
break;
}
}
}
if (statementMatches) return null;
}
}
// Accept this alternative. // Accept this alternative.
const ans = localState.clone(); const ans = localState.clone();
ans.stage = this.next; ans.stage = this.next;
ans.assignments.set(this.stage, this.key); ans.assignments.set(this.stage, this.key);
if (this.keySuffix) ans.key.push(this.keySuffix); if (this.keyAffix) ans.addKeyAffix(this.mode, this.keyAffix);
if (this.descriptionJoiner && this.descriptionSuffix) if (this.descriptionJoiner && this.descriptionAffix)
ans.addDescription(this.descriptionJoiner, this.descriptionSuffix); ans.addDescription(this.mode, this.descriptionJoiner, this.descriptionAffix);
if (this.selectorSuffix) if (this.selectorAffix)
for (const [selector, suffix] of Object.entries(this.selectorSuffix)) for (const [selector, suffix] of Object.entries(this.selectorAffix))
ans.addSelector(selector, suffix); ans.addSelectorAffix(this.mode, selector, suffix);
if (!this.next) { if (!this.next) {
ans.rank = ++globalState.rank; ans.rank = ++globalState.rank;
@ -319,6 +300,31 @@ class VbStageAlternative {
return ans; return ans;
} }
} }
shouldReject(localState) {
if (!this.disableIf) return false;
for (const branch of this.disableIf) {
let statementMatches = true;
for (let [k, v] of Object.entries(branch)) {
v = v.trim();
if (/^NOT(?=\s)/.test(v)) {
v = v.slice(3).trim();
if (localState.assignments.get(k) === v) {
statementMatches = false;
break;
}
} else {
if (localState.assignments.get(k) !== v) {
statementMatches = false;
break;
}
}
}
if (statementMatches) return true;
}
return false;
}
} }
class VbGlobalState { class VbGlobalState {
@ -354,13 +360,56 @@ class VbLocalState {
return ans; return ans;
} }
addDescription(joiner, segment) { addKeyAffix(mode, segment) {
switch (mode) {
case "append":
this.key.push(segment);
return;
case "prepend":
this.key.unshift(segment);
return;
case "replace":
this.key = [segment];
return;
default:
throw new Error(`Invalid key affix mode: ${mode}`);
}
}
addDescription(mode, joiner, segment) {
if (!segment) return; if (!segment) return;
if (!this.descriptions.has(joiner)) this.descriptions.set(joiner, []); if (!this.descriptions.has(joiner)) this.descriptions.set(joiner, []);
this.descriptions.get(joiner).push(segment);
let descriptionSentence = this.descriptions.get(joiner);
switch (mode) {
case "append":
descriptionSentence.push(segment);
return;
case "prepend":
descriptionSentence.unshift(segment);
return;
case "replace":
descriptionSentence.length = 0;
descriptionSentence.push(segment);
return;
default:
throw new Error(`Invalid description affix mode: ${mode}`);
}
} }
addSelector(selector, value) { addSelectorAffix(mode, selector, value) {
this.selector.set(selector, joinCamel(this.selector.get(selector), value)); switch (mode) {
case "append":
this.selector.set(selector, joinCamel(this.selector.get(selector), value));
return;
case "prepend":
this.selector.set(selector, joinCamel(value, this.selector.get(selector)));
return;
case "replace":
this.selector.set(selector, value);
return;
default:
throw new Error(`Invalid selector affix mode: ${mode}`);
}
} }
produceKey() { produceKey() {
@ -388,5 +437,5 @@ class VbLocalState {
function arrayToSentence(arr) { function arrayToSentence(arr) {
if (arr.length == 1) return arr[0]; if (arr.length == 1) return arr[0];
let last = arr.pop(); let last = arr.pop();
return arr.join(", ") + " and " + last; return arr.join(", ") + ", and " + last;
} }

File diff suppressed because it is too large Load diff