diff --git a/changes/27.2.1.md b/changes/27.2.1.md index d34a03c33..8b78198e3 100644 --- a/changes/27.2.1.md +++ b/changes/27.2.1.md @@ -1,6 +1,7 @@ * Refine shape of flat `5` (#2030). * Fix `ss02`, `ss04`, `ss06`, `ss13`, `ss17`'s application on `i` and `j` (#2033). * Add tailed lower lambda (#2036). +* Add Chancery and Semi-Chancery variants for lowercase `x` and Greek Chi (#2037). * Add `arrow-lr` ligation group for C-like's spaceship operators (#2041). * Add raised cap-height cent sign (`ยข`) variants to `VSAM` (#2044). * Fix `cv02`, `cv04`, `cv05`, `cv06`, `cv11`, `cv12`, `cv15`, `cv17`, `cv18`, `cv25`, `cv28`, `cv43`, `cv70`, `cv71`, `cv81`, and `cv82` for `ss17` under slab. diff --git a/font-src/glyphs/letter/latin/x.ptl b/font-src/glyphs/letter/latin/x.ptl index 052278125..733e4b498 100644 --- a/font-src/glyphs/letter/latin/x.ptl +++ b/font-src/glyphs/letter/latin/x.ptl @@ -85,6 +85,26 @@ glyph-block Letter-Latin-X : begin define lowerHalfLastKnot lowerHalf.rhsKnots.(lowerHalf.rhsKnots.length - 1) set-base-anchor 'cyrlDescenderAttach' lowerHalfLastKnot.x lowerHalfLastKnot.y + define [XChanceryStrand sign leftX leftY rightX rightY sw] : begin + local blendK1X : StrokeWidthBlend 0.58 0.65 + local blendK1Y 0.2 + local blendK2X 0.78 + local blendK2Y : StrokeWidthBlend 0.5 0.4 + + local pStraightX : StrokeWidthBlend 0.3 0.35 + local pStraightY : StrokeWidthBlend 0.2 0.25 + + local fine : [AdviceStroke 3] / Stroke * sw + + return : dispiro + straight.right.start leftX (leftY - sign * sw / 2) [widths.center sw] + alsoThruThem {{blendK1X blendK1Y} {blendK2X blendK2Y}} + flat [mix leftX rightX pStraightX] [mix leftY rightY pStraightY] [widths.center : mix sw fine 0.5] + corner [mix leftX rightX 0.5] [mix leftY rightY 0.5] [widths.center fine] + curl [mix leftX rightX (1 - pStraightX)] [mix leftY rightY (1 - pStraightY)] [widths.center : mix sw fine 0.5] + alsoThruThem {{(1 - blendK2X) (1 - blendK2Y)} {(1 - blendK1X) (1 - blendK1Y)}} + straight.right.end rightX (rightY + sign * sw / 2) [widths.center sw] + define Shape : namespace define [XBase fStraight fSlab top bottom turn tension] : composite-proc XStrand fStraight fSlab SB bottom RightSB top turn 0.4 tension @@ -100,6 +120,16 @@ glyph-block Letter-Latin-X : begin include : FlipAround Middle [mix bottom top 0.5] include : XCursiveHalfShape top bottom Middle RightSB (setMark -- true) + export : define [SemiChanceryStr fSlab top bottom turn tension] : union + XChanceryStrand (+1) SB top RightSB bottom Stroke + XStrand true fSlab SB bottom RightSB top turn 0.4 tension + export : define [SemiChanceryCur fSlab top bottom turn tension] : union + XChanceryStrand (+1) SB top RightSB bottom Stroke + XStrand false fSlab SB bottom RightSB top turn 0.4 tension + export : define [ChanceryBase fSlab top bottom turn tension] : union + XChanceryStrand (+1) SB top RightSB bottom Stroke + XChanceryStrand (-1) SB bottom RightSB top Stroke + # Serifs export : define [FullSerifs top bot] : let [sf : SerifFrame.fromDf [DivFrame 1] top bot] composite-proc sf.lt.full sf.rt.full sf.lb.full sf.rb.full @@ -110,15 +140,18 @@ glyph-block Letter-Latin-X : begin include : tagged 'serifRB' : HSerif.rb RightSB bot SideJut define Config : object - straightSerifless { Shape.StraightBase null false } - curlySerifless { Shape.CurlyBase null false } - cursive { Shape.CursiveBase null false } - straightSerifed { Shape.StraightBase Shape.FullSerifs true } - curlySerifed { Shape.CurlyBase Shape.FullSerifs true } - straightMotionSerifed { Shape.StraightBase Shape.MotionSerifs false } - curlyMotionSerifed { Shape.CurlyBase Shape.MotionSerifs false } - straightBilateralMotionSerifed { Shape.StraightBase Shape.MotionSerifsBilateral false } - curlyBilateralMotionSerifed { Shape.CurlyBase Shape.MotionSerifsBilateral false } + straightSerifless { Shape.StraightBase null false } + curlySerifless { Shape.CurlyBase null false } + cursive { Shape.CursiveBase null false } + semiChanceryStraight { Shape.SemiChanceryStr null false } + semiChanceryCurly { Shape.SemiChanceryCur null false } + chancery { Shape.ChanceryBase null false } + straightSerifed { Shape.StraightBase Shape.FullSerifs true } + curlySerifed { Shape.CurlyBase Shape.FullSerifs true } + straightMotionSerifed { Shape.StraightBase Shape.MotionSerifs false } + curlyMotionSerifed { Shape.CurlyBase Shape.MotionSerifs false } + straightBilateralMotionSerifed { Shape.StraightBase Shape.MotionSerifsBilateral false } + curlyBilateralMotionSerifed { Shape.CurlyBase Shape.MotionSerifsBilateral false } foreach { suffix { baseShape serifShape fMaskBase} } [Object.entries Config] : do define [letterShape top bottom turn tension] : glyph-proc diff --git a/font-src/support/gr.mjs b/font-src/support/gr.mjs index 288828fd0..f064f449b 100644 --- a/font-src/support/gr.mjs +++ b/font-src/support/gr.mjs @@ -436,6 +436,8 @@ function queryCvFeatureTagsOf(sink, gid, glyph, tagSet) { for (const g of existingFeatures.values()) sink.push(g); } +/////////////////////////////////////////////////////////////////////////////////////////////////// + export function linkSuffixGr(gs, suffix, gr) { const reSuffix = new RegExp("\\." + suffix + "$"); for (const [gnSuffixed, gSuffixed] of gs.namedEntries()) { diff --git a/params/variants.toml b/params/variants.toml index 0a6370b7e..40162fc19 100644 --- a/params/variants.toml +++ b/params/variants.toml @@ -3855,6 +3855,33 @@ selectorAffix.x = "cursive" selectorAffix."x/sansSerif" = "cursive" selectorAffix."cyrl/ha" = "cursive" +[prime.x.variants-buildup.stages.body.semi-chancery-straight] +rank = 4 +nonBreakingVariantAdditionPriority = 100 +next = "END" +descriptionAffix = "Semi-chancery shape with straight counter-leg" +selectorAffix.x = "semiChanceryStraight" +selectorAffix."x/sansSerif" = "semiChanceryStraight" +selectorAffix."cyrl/ha" = "semiChanceryStraight" + +[prime.x.variants-buildup.stages.body.semi-chancery-curly] +rank = 5 +nonBreakingVariantAdditionPriority = 100 +next = "END" +descriptionAffix = "Semi-chancery shape with curly counter-leg" +selectorAffix.x = "semiChanceryCurly" +selectorAffix."x/sansSerif" = "semiChanceryCurly" +selectorAffix."cyrl/ha" = "semiChanceryCurly" + +[prime.x.variants-buildup.stages.body.chancery] +rank = 6 +nonBreakingVariantAdditionPriority = 200 +next = "END" +descriptionAffix = "Chancery shape" +selectorAffix.x = "chancery" +selectorAffix."x/sansSerif" = "chancery" +selectorAffix."cyrl/ha" = "chancery" + [prime.x.variants-buildup.stages.serifs.serifless] rank = 1 descriptionAffix = "serifs" @@ -3865,7 +3892,6 @@ selectorAffix."cyrl/ha" = "serifless" [prime.x.variants-buildup.stages.serifs.motion-serifed] rank = 2 -disableIf = [{ body = "cursive" }] descriptionAffix = "motion serifs" selectorAffix.x = "motionSerifed" selectorAffix."x/sansSerif" = "serifless" @@ -3873,7 +3899,6 @@ selectorAffix."cyrl/ha" = "motionSerifed" [prime.x.variants-buildup.stages.serifs.serifed] rank = 3 -disableIf = [{ body = "cursive" }] descriptionAffix = "serifs" selectorAffix.x = "serifed" selectorAffix."x/sansSerif" = "serifless" @@ -4785,6 +4810,31 @@ descriptionAffix = "curly shape" selectorAffix."grek/chi" = "curly" selectorAffix."grek/chi/sansSerif" = "curly" +[prime.lower-chi.variants-buildup.stages.body.semi-chancery-straight] +rank = 3 +nonBreakingVariantAdditionPriority = 100 +next = "END" +descriptionAffix = "Semi-chancery shape with straight counter-leg" +selectorAffix."grek/chi" = "semiChanceryStraight" +selectorAffix."grek/chi/sansSerif" = "semiChanceryStraight" + +[prime.lower-chi.variants-buildup.stages.body.semi-chancery-curly] +rank = 4 +nonBreakingVariantAdditionPriority = 100 +next = "END" +descriptionAffix = "Semi-chancery shape with curly counter-leg" +selectorAffix."grek/chi" = "semiChanceryCurly" +selectorAffix."grek/chi/sansSerif" = "semiChanceryCurly" + +[prime.lower-chi.variants-buildup.stages.body.chancery] +rank = 5 +nonBreakingVariantAdditionPriority = 200 +next = "END" +descriptionAffix = "Chancery shape" +selectorAffix."grek/chi" = "chancery" +selectorAffix."grek/chi/sansSerif" = "chancery" + + [prime.lower-chi.variants-buildup.stages.serifs.serifless] rank = 1 descriptionAffix = "serifs" @@ -7542,6 +7592,7 @@ u = "toothed-serifless" y = "straight-turn-serifless" long-s = "flat-hook-serifless" eszet = "longs-s-lig-serifless" +lower-chi = "semi-chancery-straight" lower-eth = "straight-bar" lower-iota = "tailed-serifed" lower-lambda = "tailed-turn" @@ -7643,6 +7694,7 @@ u = "toothed-serifless" y = "straight-turn-serifless" long-s = "flat-hook-middle-serifed" eszet = "longs-s-lig-serifless" +lower-chi = "semi-chancery-straight" lower-eth = "straight-bar" lower-lambda = "straight-turn" cyrl-capital-zhe = "straight" @@ -7994,7 +8046,7 @@ capital-lambda = "curly-serifless" lower-lambda = "curly-tailed-turn" lower-mu = "toothed-serifless" lower-tau = "tailed" -lower-chi = "curly-serifless" +lower-chi = "semi-chancery-curly" cyrl-capital-zhe = "curly" cyrl-zhe = "curly" cyrl-capital-ka = "curly-serifless"