diff --git a/changes/16.3.6.md b/changes/16.3.6.md new file mode 100644 index 000000000..81ca66eab --- /dev/null +++ b/changes/16.3.6.md @@ -0,0 +1 @@ + * Fix shape of y-ogonek (used by Elfdalian) (#1437). diff --git a/font-src/glyphs/letter/latin/lower-y.ptl b/font-src/glyphs/letter/latin/lower-y.ptl index 70876d927..4381d911e 100644 --- a/font-src/glyphs/letter/latin/lower-y.ptl +++ b/font-src/glyphs/letter/latin/lower-y.ptl @@ -1,7 +1,7 @@ $$include '../../../meta/macros.ptl' import [mix linreg clamp fallback] from"../../../support/utils.mjs" -import [LowerYDotAtBelow Dotless CvDecompose MathSansSerif] from"../../../support/gr.mjs" +import [LowerYDotAtBelow Dotless CvDecompose MathSansSerif OgonekTrY] from"../../../support/gr.mjs" glyph-module @@ -64,7 +64,18 @@ glyph-block Letter-Latin-Lower-Y : begin curl x (top - ds) [widths.heading hl hr Downward] quadControls 0 dpy1 16 - define [yBaseKnots top bottom shrink hooktop ogonek] : begin + define [yOgonekAttach top bottom shrink hooktop] : glyph-proc + define {ds ds2} : CalcDS top bottom + define coJoinX : if (straightBar && (! hooktop)) yrstroker [mix yrstrokel yrstroker px1] + define coJoinY : if (straightBar && (! hooktop)) top [mix (bottom + ds2) (top - ds) py1] + define joinX : mix yrstrokel yrstroker (1 - px2) + define joinY : mix (bottom + ds2) (top - ds) (1 - py2) + + define anchorX : mix coJoinX joinX ((0 - coJoinY) / (joinY - coJoinY)) + set-base-anchor 'trailing' anchorX 0 + OgonekTrY.set currentGlyph + + define [yBaseKnots top bottom shrink hooktop] : begin define {ds ds2} : CalcDS top bottom define coJoinX : mix yrstrokel yrstroker px1 define coJoinY : mix (bottom + ds2) (top - ds) py1 @@ -72,30 +83,12 @@ glyph-block Letter-Latin-Lower-Y : begin define joinY : mix (bottom + ds2) (top - ds) (1 - py2) define [ConnectZ shrink] : curl joinX joinY [widths.rhs : Stroke * shrink] - define [ogonekKnots] : begin - - local stopX : mix joinX coJoinX ((0 - joinY) / (coJoinY - joinY)) - local stopY 0 - - local depth : 0 - Descender - markStroke - local extL : (0.5 * 0.75 * depth / coJoinY) * depth + 0.25 * markStress - local extR : Math.max (0.5 * markExtend) (1.5 * TanSlope * markStroke) - local turnSlope : 0.5 * ((markStroke - Stroke) / markStroke - (ArchDepthB - ArchDepth) / ArchDepth) - - list - curl stopX stopY [widths.rhs : Stroke * [if useStraightBottom shrink 1]] - g4.down.mid (stopX - extL) (stopY - 0.75 * depth) [widths.rhs.heading [mix Stroke markStroke 0.25] {.x HVContrast .y (-turnSlope)}] - arcvh [widths.rhs markStroke] - g4 (stopX + [mix (-extL) extR (11/16)]) (stopY - depth + O) [heading Rightward] - g4 (stopX + extR) (stopY - depth + 0.5 * O) [heading Rightward] - return : list if (straightBar && (! hooktop)) then : list else : list [flat coJoinX coJoinY] piecewise - ogonek : ogonekKnots useStraightBottom : list ConnectZ shrink curl [mix yrstroker joinX ((top - bottom) / (top - joinY))] bottom [widths.heading 0 (Stroke * [yDiagCor (top - bottom)]) Downward] @@ -159,6 +152,8 @@ glyph-block Letter-Latin-Lower-Y : begin define [SmallYShape top bottom] : glyph-proc local {ds ds2} : CalcDS top bottom + include : yOgonekAttach top bottom yshrink + include : intersection SmallYStrokeSplitMask top bottom false 1 dispiro @@ -183,39 +178,12 @@ glyph-block Letter-Latin-Lower-Y : begin if doSlabBottom : include : yBaseSerif top bottom if doSlabMotion : include : LeftwardTopSerif SB top SideJut - define [SmallYOgonekShape top bottom] : glyph-proc - local {ds ds2} : CalcDS top bottom - - include : intersection - union - SmallYStrokeSplitMask top bottom false 1 - MaskBelow 0 - dispiro - yTopKnots yrstroker top bottom ds 1 - yBaseKnots top bottom 1 false true - - include : difference - dispiro - yTopKnots yrstroker top bottom ds 1 - yBaseKnots top bottom yshrink false true - SmallYStrokeSplitMask top bottom false 1 1 - MaskBelow 0 - - include : difference - dispiro - yTopKnots (Width - yrstroker) top bottom ds (-1) - yJoinKnots ds ds2 top bottom - SmallYStrokeSplitMask top bottom false (-1) - Rect (bottom + HalfStroke) (bottom - top) 0 Width - - if doSlabTop : include : let [sf : SerifFrame top bottom SB RightSB] - composite-proc sf.lt.full sf.rt.full - if doSlabMotion : include : LeftwardTopSerif SB top SideJut - define [SmallYHookTopShape top bottom] : glyph-proc local {ds ds2} : CalcDS top bottom local joinHeight : yJoinHeight ds ds2 top bottom true + include : yOgonekAttach top bottom yshrink true + include : intersection SmallYStrokeSplitMask top bottom true 1 dispiro @@ -248,7 +216,7 @@ glyph-block Letter-Latin-Lower-Y : begin include : Scale 1 (-1) include : Translate 0 (+[mix bottom top 0.5]) - return : object SmallYShape SmallYOgonekShape SmallYHookTopShape SmallLambdaShape + return : object SmallYShape SmallYHookTopShape SmallLambdaShape create-glyph : glyph-proc include : MarkSet.p @@ -271,19 +239,6 @@ glyph-block Letter-Latin-Lower-Y : begin create-forked-glyph 'y.curlyTurnMotionSerifed' : glyph-proc include : [GenSmallYShape false true SLAB-MOTION].SmallYShape XH Descender - create-glyph : glyph-proc - include : MarkSet.p - set-base-anchor 'overlay' Middle (XH / 2) - set-base-anchor 'yBelowDot' (RightSB - 0.5 * DotRadius) (Descender + AccentStackOffset + DotRadius) - create-forked-glyph 'yOgonek.straight' : glyph-proc - include : [GenSmallYShape true false SLAB-AUTO].SmallYOgonekShape XH Descender - create-forked-glyph 'yOgonek.curly' : glyph-proc - include : [GenSmallYShape false false SLAB-AUTO].SmallYOgonekShape XH Descender - create-forked-glyph 'yOgonek.straightMotionSerifed' : glyph-proc - include : [GenSmallYShape true false SLAB-MOTION].SmallYOgonekShape XH Descender - create-forked-glyph 'yOgonek.curlyMotionSerifed' : glyph-proc - include : [GenSmallYShape false false SLAB-MOTION].SmallYOgonekShape XH Descender - define [SmallYCursiveArc top bottom] : new-glyph : glyph-proc include : nShoulder top -- top @@ -343,25 +298,8 @@ glyph-block Letter-Latin-Lower-Y : begin include : LeftwardTopSerif SB XH SideJut set-base-anchor 'overlay' Middle (XH / 2) - create-glyph 'yOgonek.cursive' : glyph-proc - include [refer-glyph 'y.cursive'] AS_BASE ALSO_METRICS - include [refer-glyph 'ogonekBelow'] - - create-glyph 'yOgonek.cursiveFlatHook' : glyph-proc - include [refer-glyph 'y.cursiveFlatHook'] AS_BASE ALSO_METRICS - include [refer-glyph 'ogonekBelow'] - - create-glyph 'yOgonek.cursiveMotionSerifed' : glyph-proc - include [refer-glyph 'y.cursiveMotionSerifed'] AS_BASE ALSO_METRICS - include [refer-glyph 'ogonekBelow'] - - create-glyph 'yOgonek.cursiveFlatHookMotionSerifed' : glyph-proc - include [refer-glyph 'y.cursiveFlatHookMotionSerifed'] AS_BASE ALSO_METRICS - include [refer-glyph 'ogonekBelow'] - select-variant 'y' 'y' link-reduced-variant 'y/sansSerif' 'y' MathSansSerif - select-variant 'yOgonek' 0xE011 alias 'cyrl/u' 0x443 'y' foreach { suffix { DrawAt kdr } } [Object.entries DotVariants] : do diff --git a/font-src/glyphs/marks/horn-and-angle.ptl b/font-src/glyphs/marks/horn-and-angle.ptl index 9a0c11098..5bd38175d 100644 --- a/font-src/glyphs/marks/horn-and-angle.ptl +++ b/font-src/glyphs/marks/horn-and-angle.ptl @@ -150,26 +150,32 @@ glyph-block Mark-Horn-And-Angle : begin include : refer-glyph "leftHalfCircleBelow" include : FlipAround markMiddle (XH / 2) - create-glyph 'ogonekTR' : glyph-proc - set-width 0 + define ogonekTrConfig : object + 'ogonekTR' { (7/16) (1/8) 1 } + 'ogonekTR_Y' { (3/16) 1 6 } - local fine : AdviceStroke 8 - local depth : 0 - Descender - markStroke - local extL : (7 / 16) * depth + 0.125 * markStress - local extR : Math.max (0.125 * markExtend) (1.5 * TanSlope * markStroke) + foreach { glyphName { pExtL pExtR cwMidStrokeWidth } } [Object.entries ogonekTrConfig] : do + create-glyph glyphName : glyph-proc + set-width 0 - local turnSlope : 0.5 * ((markStroke - fine) / markStroke - (ArchDepthB - ArchDepth) / ArchDepth) + local fine : AdviceStroke 8 + local depth : 0 - Descender - markStroke + local extL : pExtL * depth + 0.125 * markStress + local extR : Math.max (pExtR * markExtend) (1.5 * TanSlope * markStroke) - include : difference - dispiro - g4 markMiddle 0 [widths.rhs.heading fine Leftward] - alsoThru 0.5 (0.375 - 0.2 * markStroke / depth) [widths.rhs : mix fine markStroke 0.25] - g4.down.mid (markMiddle - extL) (-0.75 * depth) [widths.rhs.heading markStroke {.x HVContrast .y turnSlope}] - arcvh [widths.rhs markStroke] - g4 (markMiddle + [mix (-extL) extR (11/16)]) (-depth + O) [heading Rightward] - g4 (markMiddle + extR) (-depth + 0.5 * O) [heading Rightward] - intersection - MaskAbove 0 - MaskRight markMiddle + local turnSlope : 0.5 * ((markStroke - fine) / markStroke - (ArchDepthB - ArchDepth) / ArchDepth) + local swMid : Math.min markStroke [AdviceStroke cwMidStrokeWidth] - set-mark-anchor 'trailing' markMiddle 0 (markMiddle + extR) (-depth - 0.5 * O - markStroke) + include : difference + dispiro + g4 markMiddle 0 [widths.rhs.heading fine Leftward] + alsoThru 0.5 (0.375 - 0.2 * markStroke / depth) [widths.rhs : mix fine swMid 0.25] + g4.down.mid (markMiddle - extL) (-0.75 * depth) [widths.rhs.heading swMid {.x HVContrast .y turnSlope}] + arcvh + g4 (markMiddle + [mix (-extL) extR (11/16)]) (-depth + O) [widths.rhs.heading markStroke Rightward] + g4 (markMiddle + extR) (-depth + 0.5 * O) [heading Rightward] + intersection + MaskAbove 0 + MaskRight markMiddle + + set-mark-anchor 'trailing' markMiddle 0 (markMiddle + extR) (-depth - 0.5 * O - markStroke) diff --git a/font-src/meta/unicode-knowledge.ptl b/font-src/meta/unicode-knowledge.ptl index 2fba5f6f8..1af304f9f 100644 --- a/font-src/meta/unicode-knowledge.ptl +++ b/font-src/meta/unicode-knowledge.ptl @@ -4,6 +4,9 @@ export : define iotaBelowToLfTf : object export : define ogonekBelowToTRTf : object 'ogonekBelow' 'ogonekTR' +export : define ogonekBelowToTRTf_Y : object + 'ogonekBelow' 'ogonekTR_Y' + export : define upperGrekMarkToTonosTf : object 'variaAbove' 'variaGrekUpperTonos' 'oxiaAbove' 'oxiaGrekUpperTonos' @@ -30,8 +33,6 @@ export : define markCompositionTf : object 'perispomeniAbove' 'dasiaPerispomeni' 'cyrlPsiliAbove' : object 'cyrlPokrytieAbove' 'cyrlPsiliPokrytieAbove' - 'y' : object - 'ogonekBelow' 'yOgonek' export : define decompositionOverrides : object # Latvians use comma instead of cedillas in several letters. diff --git a/font-src/otl/gsub-ccmp.ptl b/font-src/otl/gsub-ccmp.ptl index bbbcd9b05..d612d6529 100644 --- a/font-src/otl/gsub-ccmp.ptl +++ b/font-src/otl/gsub-ccmp.ptl @@ -1,5 +1,5 @@ import [AddCommonFeature AddFeature AddLookup AddFeatureLookup ChainRuleBuilder BeginLookupBlock EndLookupBlock UkMapToLookup UkMap2ToLookup] from"./table-util.mjs" -import [AnyCv Dotless TieMark TieGlyph CcmpDecompose] from"../support/gr.mjs" +import [AnyCv Dotless TieMark TieGlyph CcmpDecompose OgonekTrY] from"../support/gr.mjs" import as UnicodeKnowledge from"../meta/unicode-knowledge.mjs" extern Set @@ -234,22 +234,32 @@ export : define [buildCCMPPostCvSs sink ccmpFeature glyphStore markGlyphs] : beg define ccmp : AddFeature sink 'ccmp' define {chain-rule} : ChainRuleBuilder sink - define groupTR {} + define triggerGlyphs_Normal { } + define triggerGlyphs_Y { } foreach { gid g } [glyphStore.namedEntries] : if (gid.(0) !== "."): begin - if g.baseAnchors.trailing : groupTR.push gid + if g.baseAnchors.trailing : piecewise + [OgonekTrY.get g] : triggerGlyphs_Y.push gid + true : triggerGlyphs_Normal.push gid - define [OgonekTrailing] : UkMapToLookup UnicodeKnowledge.ogonekBelowToTRTf + define [markTransform_Normal] : UkMapToLookup UnicodeKnowledge.ogonekBelowToTRTf + define [markTransform_Y] : UkMapToLookup UnicodeKnowledge.ogonekBelowToTRTf_Y + + define [pushTransforms sink triggers tf] : begin + sink.push : chain-rule triggers [tf] + sink.push : chain-rule triggers markGlyphs.all [tf] + sink.push : chain-rule triggers markGlyphs.all markGlyphs.all [tf] + sink.push : chain-rule triggers markGlyphs.all markGlyphs.all markGlyphs.all [tf] + sink.push : chain-rule triggers markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all [tf] + sink.push : chain-rule triggers markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all [tf] + sink.push : chain-rule triggers markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all [tf] + + define ogonekTransforms {} + pushTransforms ogonekTransforms triggerGlyphs_Normal markTransform_Normal + pushTransforms ogonekTransforms triggerGlyphs_Y markTransform_Y define lookupMarks1 : AddLookup sink : object .type 'gsub_chaining' - .rules : list - # Ogonek transform (max 6 middle marks are supported) - chain-rule groupTR [OgonekTrailing] - chain-rule groupTR markGlyphs.all [OgonekTrailing] - chain-rule groupTR markGlyphs.all markGlyphs.all [OgonekTrailing] - chain-rule groupTR markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all [OgonekTrailing] - chain-rule groupTR markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all [OgonekTrailing] - chain-rule groupTR markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all markGlyphs.all [OgonekTrailing] + .rules ogonekTransforms ccmpFeature.lookups.push lookupMarks1 EndLookupBlock rec sink diff --git a/font-src/support/gr.mjs b/font-src/support/gr.mjs index baac636e0..d44f52128 100644 --- a/font-src/support/gr.mjs +++ b/font-src/support/gr.mjs @@ -107,6 +107,7 @@ function BoolProp(id) { export const Radical = BoolProp("Radical"); export const RequireCcmpDecompose = BoolProp("RequireCcmpDecompose"); export const NeqLigationSlashDotted = BoolProp("NeqLigationSlashDotted"); +export const OgonekTrY = BoolProp("OgonekTrY"); export const Joining = { get(glyph) { diff --git a/params/variants.toml b/params/variants.toml index 7c9a90bfa..f0cd2ee1a 100644 --- a/params/variants.toml +++ b/params/variants.toml @@ -4270,7 +4270,6 @@ rank = 1 description = "Letter `y` that is fully straight" selector.y = "straight" selector."y/sansSerif" = "straight" -selector.yOgonek = "straight" selector.yHookTop = "straight" [prime.y.variants.straight-turn] @@ -4278,7 +4277,6 @@ rank = 2 description = "Letter `y` with straight upper and a tail turns leftward" selector.y = "straightTurn" selector."y/sansSerif" = "straightTurn" -selector.yOgonek = "straight" selector.yHookTop = "straightTurn" [prime.y.variants.curly] @@ -4286,7 +4284,6 @@ rank = 3 description = "More curly letter `y`, like Iosevka 2.x" selector.y = "curly" selector."y/sansSerif" = "curly" -selector.yOgonek = "curly" selector.yHookTop = "curly" [prime.y.variants.curly-turn] @@ -4294,7 +4291,6 @@ rank = 4 description = "More curly letter `y`, like Iosevka 2.x, with a tail turns leftward" selector.y = "curlyTurn" selector."y/sansSerif" = "curlyTurn" -selector.yOgonek = "curly" selector.yHookTop = "curlyTurn" [prime.y.variants.cursive] @@ -4302,7 +4298,6 @@ rank = 5 description = "Cursive-like `y`" selector.y = "cursive" selector."y/sansSerif" = "cursive" -selector.yOgonek = "cursive" selector.yHookTop = "cursive" [prime.y.variants.cursive-flat-hook] @@ -4310,7 +4305,6 @@ rank = 6 description = "Cursive-like `y` with flat terminal hook" selector.y = "cursiveFlatHook" selector."y/sansSerif" = "cursiveFlatHook" -selector.yOgonek = "cursiveFlatHook" selector.yHookTop = "cursiveFlatHook" [prime.y.variants.straight-motion-serifed] @@ -4318,7 +4312,6 @@ rank = 7 description = "Letter `y` that is fully straight, with motion serifs" selector.y = "straightMotionSerifed" selector."y/sansSerif" = "straight" -selector.yOgonek = "straightMotionSerifed" selector.yHookTop = "straight" [prime.y.variants.straight-turn-motion-serifed] @@ -4326,7 +4319,6 @@ rank = 8 description = "Letter `y` with straight upper and a tail turns leftward, and motion serifs" selector.y = "straightTurnMotionSerifed" selector."y/sansSerif" = "straightTurn" -selector.yOgonek = "straightMotionSerifed" selector.yHookTop = "straightTurn" [prime.y.variants.curly-motion-serifed] @@ -4334,7 +4326,6 @@ rank = 9 description = "More curly letter `y`, like Iosevka 2.x, with motion serifs" selector.y = "curlyMotionSerifed" selector."y/sansSerif" = "curly" -selector.yOgonek = "curlyMotionSerifed" selector.yHookTop = "curly" [prime.y.variants.curly-turn-motion-serifed] @@ -4342,7 +4333,6 @@ rank = 10 description = "More curly letter `y`, like Iosevka 2.x, with a tail turns leftward and motion serifs" selector.y = "curlyTurnMotionSerifed" selector."y/sansSerif" = "curlyTurn" -selector.yOgonek = "curlyMotionSerifed" selector.yHookTop = "curlyTurn" [prime.y.variants.cursive-motion-serifed] @@ -4350,7 +4340,6 @@ rank = 11 description = "Cursive-like `y`, with motion serifs" selector.y = "cursiveMotionSerifed" selector."y/sansSerif" = "cursive" -selector.yOgonek = "cursiveMotionSerifed" selector.yHookTop = "cursive" [prime.y.variants.cursive-flat-hook-motion-serifed] @@ -4358,7 +4347,6 @@ rank = 12 description = "Cursive-like `y` with flat terminal hook, and motion serifs" selector.y = "cursiveFlatHookMotionSerifed" selector."y/sansSerif" = "cursiveFlatHook" -selector.yOgonek = "cursiveFlatHookMotionSerifed" selector.yHookTop = "cursiveFlatHook"