diff --git a/font-src/glyphs/letter/latin/lower-y.ptl b/font-src/glyphs/letter/latin/lower-y.ptl index 7d016f373..2ae9eda47 100644 --- a/font-src/glyphs/letter/latin/lower-y.ptl +++ b/font-src/glyphs/letter/latin/lower-y.ptl @@ -20,6 +20,12 @@ glyph-block Letter-Latin-Lower-Y : begin define SLAB-MOTION { false false true } define SLAB-CURSIVE-MOTION { true true true } + define TS-NONE 0 + define TS-HOOKTOP 1 + + define SHRINK-NONE 0 + define SHRINK-INNER 1 + define BS-STRAIGHT 0 define BS-TURN 1 define BS-LOOP 2 @@ -33,209 +39,233 @@ glyph-block Letter-Latin-Lower-Y : begin local slabCurlyNoTurnB : doSlabBottom && !straightBar && !bottomShape local bottomIsNotVertical : doSlabBottom || useStraightBottom || bottomShape - local px1 0.84 - local py1 : [StrokeWidthBlend 0.8 0.76] * [if slabCurly [StrokeWidthBlend 1 0.9] 1] - local px2 : if slabCurlyNoTurnB px1 0.95 - local py2VertBot : 0.88 * [if slabCurly [StrokeWidthBlend 1 0.9] 1] - local py2 : if slabCurlyNoTurnB py1 : if bottomIsNotVertical 0.97 py2VertBot - local pds 0.1 - local pds2 0.01 - local dpy1 : (1 - [linreg (1 - px2) (1 - py2) px1 py1 1]) / (1 - py1) - local dpy2 : (1 - [linreg (1 - px1) (1 - py1) px2 py2 1]) / (1 - py2) - local yrstrokel0 : Middle - Width * 0.1 - local yrstrokel : Middle - Width * 0.1 + ([HSwToV Stroke] * [if bottomIsNotVertical (2 / 3) (1 / 3)] * [if slabCurly [StrokeWidthBlend 0.95 0.97] 1]) - local yrstroker : Width - SB * [if straightBar DesignParameters.straightSmallYShapeSbShrink 1] - local yshrink : [StrokeWidthBlend 1 0.85] * [if straightBar ([AdviceStroke 3.25] / Stroke) 1] - local yBottomJut : Jut * 1.25 - local slabysize : Jut * 1.25 * (Width / UPM) + Stroke - local slabyvx 0.625 + define yBottomJut : Jut * 1.25 + define slabysize : yBottomJut * (Width / UPM) + Stroke define [CalcDS top bottom] : begin + local pds 0.1 + local pds2 0.01 + local slabyvx 0.625 local ds0 : (top - bottom) * pds local ds20 : (top - bottom) * pds2 local ds : if slabCurly [Math.max [AdviceStroke2 3 6 (top - bottom)] ds0] ds0 local ds2 : if slabCurlyNoTurnB ds : ds20 + [if bottomIsNotVertical (slabysize * slabyvx) 0] return {ds ds2} - define [yDiagCor dy] : DiagCor dy (yrstroker - yrstrokel) 0 0 + define [Metrics ts kShrink] : namespace + define pxHookTopOffset : [StrokeWidthBlend (0.5 * TailX) (0.375 * TailX)] / (RightSB - SB) + export : define px1 : 0.84 - [if (ts == TS-HOOKTOP) pxHookTopOffset 0] + export : define py1 : [StrokeWidthBlend 0.8 0.76] * [if slabCurly [StrokeWidthBlend 1 0.9] 1] + export : define px2 : if slabCurlyNoTurnB px1 0.95 + export : define py2VertBot : 0.88 * [if slabCurly [StrokeWidthBlend 1 0.9] 1] + export : define py2 : if slabCurlyNoTurnB py1 : if bottomIsNotVertical 0.97 py2VertBot + export : define dpy1 : (1 - [linreg (1 - px2) (1 - py2) px1 py1 1]) / (1 - py1) + export : define dpy2 : (1 - [linreg (1 - px1) (1 - py1) px2 py2 1]) / (1 - py2) - define [yTopKnots x top bottom ds dir] : begin - local hs : HalfStroke * [if straightBar [yDiagCor (top - bottom)] 1] - local hl : hs - hs * dir - local hr : hs + hs * dir - if straightBar : return : list - flat x top [widths.heading hl hr Downward] - : else : return : list - flat x top [widths.heading hl hr Downward] - curl x (top - ds) [widths.heading hl hr Downward] - quadControls 0 dpy1 16 + define yrstrokel0 : Middle - Width * 0.1 + export : define yrstrokel : Middle - Width * 0.1 + ([HSwToV Stroke] * [if bottomIsNotVertical (2 / 3) (1 / 3)] * [if slabCurly [StrokeWidthBlend 0.95 0.97] 1]) + export : define yrstroker : Width - SB * [if straightBar DesignParameters.straightSmallYShapeSbShrink 1] - 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) + export : define yshrink : mix 1 ([StrokeWidthBlend 1 0.85] * [if straightBar ([AdviceStroke 3.25] / Stroke) 1]) kShrink - define anchorX : mix coJoinX joinX ((0 - coJoinY) / (joinY - coJoinY)) - set-base-anchor 'trailing' anchorX 0 - OgonekTrY.set currentGlyph + export : define [diagCor dy] : DiagCor dy (yrstroker - yrstrokel) 0 0 - define [px1HooktopAdj hooktop] : begin - return : px1 - [if hooktop ([StrokeWidthBlend (0.5 * TailX) (0.375 * TailX)] / (RightSB - SB)) 0] + export : define [yJoinProportion x] : linreg + 1 - px2 + 1 - py2 + if (straightBar && ts != TS-HOOKTOP) 1 px1 + if (straightBar && ts != TS-HOOKTOP) 1 py1 + (x - yrstrokel) / (yrstroker - yrstrokel) - define [yBaseKnots top bottom shrink hooktop] : begin - define {ds ds2} : CalcDS top bottom + export : define [yJoinHeight top bottom] : begin + local {ds ds2} : CalcDS top bottom + return : mix (bottom + ds2) (top - ds) [yJoinProportion Middle] - define coJoinX : mix yrstrokel yrstroker [px1HooktopAdj hooktop] - define coJoinY : mix (bottom + ds2) (top - ds) py1 - define joinX : mix yrstrokel yrstroker (1 - px2) - define joinY : mix (bottom + ds2) (top - ds) (1 - py2) - define [ConnectZ shrink] : curl joinX joinY [widths.rhs : Stroke * shrink] + export : define [createSplitMask top bottom dir elev] : begin + local {ds ds2} : CalcDS top bottom + local jp0 : yJoinProportion (Width / 2 - Width / 2 * dir) + local jp1 : yJoinProportion (Width / 2 + Width / 2 * dir) + local hs : 0.75 * Stroke + local yLeft : [mix (bottom + ds2) (top - ds) jp1] + hs - [fallback elev 0] + local yRight : [mix (bottom + ds2) (top - ds) jp0] + hs - [fallback elev 0] + local yMin : Math.min bottom yLeft yRight + return : spiro-outline + corner Width yMin + corner Width yRight + corner 0 yLeft + corner 0 yMin + define [RightHalf ts kShrink] : namespace + local me : Metrics ts kShrink - return : list - if (straightBar && !hooktop) - then : list - else : list [flat coJoinX coJoinY] - - piecewise - useStraightBottom : list - ConnectZ shrink - curl [mix yrstroker joinX ((top - bottom) / (top - joinY))] bottom [widths.heading 0 (Stroke * [yDiagCor (top - bottom)]) Downward] - (bottomShape == BS-LOOP) : begin - local joinHeight1 : yJoinHeight ds ds2 top bottom false - local k : 1 / [Math.sin : Math.atan2 (joinX - Middle) (joinY - joinHeight1)] - 0.25 - local joinHeight3 : [Math.abs k] * Stroke + joinHeight1 - local deltaX : Math.max yBottomJut [HSwToV : 1.2 * Stroke] - local fine : AdviceStroke 3 - local xLoopLeft : Math.max (SB * -0.25) [mix joinX (yrstrokel - deltaX) 2] - local xCenter : mix xLoopLeft joinX 0.5 - list - ConnectZ shrink - g4.left.mid ([Math.min (yrstrokel - deltaX) xCenter] + CorrectionOMidS) bottom [widths.rhs] - archv - g4.up.mid xLoopLeft [mix bottom joinHeight3 0.5] [widths.rhs.heading fine Upward] - arcvh - flat xCenter joinHeight3 [heading Rightward] - curl Middle joinHeight3 [heading Rightward] - (bottomShape == BS-TURN) : list - ConnectZ shrink - flat (yrstrokel - slabysize) bottom [widths.rhs] - curl [Math.min (yrstrokel - slabysize - 0.1) (yrstrokel - Stroke - yBottomJut)] bottom + export : define [topKnots top bottom] : begin + local {ds} : CalcDS top bottom + return : piecewise + (ts == TS-HOOKTOP) : list + straight.left.start ([mix me.yrstrokel me.yrstroker me.px1] - HalfStroke + 0.875 * TailX) (top - Stroke - O) [widths.rhs] + alsoThruThem {{[StrokeWidthBlend 0.58 0.65] 0.2} {[StrokeWidthBlend 0.78 0.85] 0.5}} important + straightBar : list + flat me.yrstroker top [widths.rhs.heading ([me.diagCor (top - bottom)] * Stroke) Downward] true : list - ConnectZ 1 - quadControls 1 (1 - dpy2) 16 - flat yrstrokel (bottom + ds2) [widths.heading 0 Stroke Downward] - curl yrstrokel bottom [widths.heading 0 Stroke Downward] + flat me.yrstroker top [widths.rhs.heading Stroke Downward] + curl me.yrstroker (top - ds) [heading Downward] + quadControls 0 me.dpy1 16 - define [yBaseSerif top bottom] : glyph-proc - local {ds ds2} : CalcDS top bottom - define joinX : mix yrstrokel yrstroker (1 - px2) - define joinY : mix (bottom + ds2) (top - ds) (1 - py2) + export : define [baseKnots top bottom] : begin + define {ds ds2} : CalcDS top bottom - if bottomShape : return nothing - if (useStraightBottom) : begin - local xBaseKnot : mix yrstroker joinX ((top - bottom) / (top - joinY)) - include : HSerif.lb (xBaseKnot - [HSwToV HalfStroke]) bottom yBottomJut - : else : begin - include : HSerif.lb (yrstrokel - [HSwToV HalfStroke]) bottom yBottomJut + define coJoinX : mix me.yrstrokel me.yrstroker me.px1 + define coJoinY : mix (bottom + ds2) (top - ds) me.py1 + define joinX : mix me.yrstrokel me.yrstroker (1 - me.px2) + define joinY : mix (bottom + ds2) (top - ds) (1 - me.py2) + define [ConnectZ shrink] : curl joinX joinY [widths.rhs : Stroke * shrink] - define [yJoinProportion hooktop x] : linreg - 1 - px2 - 1 - py2 - if (straightBar && !hooktop) 1 [px1HooktopAdj hooktop] - if (straightBar && !hooktop) 1 py1 - (x - yrstrokel) / (yrstroker - yrstrokel) + return : list + if (straightBar && ts != TS-HOOKTOP) + then : list + else : list [flat coJoinX coJoinY] - define [yJoinHeight ds ds2 top bottom hooktop] : begin - return : mix (bottom + ds2) (top - ds) [yJoinProportion hooktop Middle] + piecewise + useStraightBottom : list + ConnectZ me.yshrink + curl [mix me.yrstroker joinX ((top - bottom) / (top - joinY))] bottom [widths.rhs.heading ([me.diagCor (top - bottom)] * Stroke) Downward] + (bottomShape == BS-LOOP) : begin + local joinHeight1 : me.yJoinHeight top bottom + local k : 1 / [Math.sin : Math.atan2 (joinX - Middle) (joinY - joinHeight1)] - 0.25 + local joinHeight3 : [Math.abs k] * Stroke + joinHeight1 + local deltaX : Math.max yBottomJut [HSwToV : 1.2 * Stroke] + local fine : AdviceStroke 3 + local xLoopLeft : Math.max (SB * -0.25) [mix joinX (me.yrstrokel - deltaX) 2] + local xCenter : mix xLoopLeft joinX 0.5 + list + ConnectZ me.yshrink + g4.left.mid ([Math.min (me.yrstrokel - deltaX) xCenter] + CorrectionOMidS) bottom [widths.rhs] + archv + g4.up.mid xLoopLeft [mix bottom joinHeight3 0.5] [widths.rhs.heading fine Upward] + arcvh + flat xCenter joinHeight3 [heading Rightward] + curl Middle joinHeight3 [heading Rightward] + (bottomShape == BS-TURN) : list + ConnectZ me.yshrink + flat (me.yrstrokel - slabysize) bottom [widths.rhs] + curl [Math.min (me.yrstrokel - slabysize - 0.1) (me.yrstrokel - Stroke - yBottomJut)] bottom + true : list + ConnectZ 1 + quadControls 1 (1 - me.dpy2) 16 + flat me.yrstrokel (bottom + ds2) [widths.heading 0 Stroke Downward] + curl me.yrstrokel bottom [widths.heading 0 Stroke Downward] - define [yJoinKnots ds ds2 top bottom hooktop] : begin - return : list - if straightBar : then : list - : else : list - flat - mix (Width - yrstrokel) (Width - yrstroker) px1 - mix (bottom + ds2) (top - ds) py1 - curl Middle - yJoinHeight ds ds2 top bottom hooktop - widths.lhs (Stroke * yshrink) + export : define [baseSerif top bottom] : glyph-proc + local {ds ds2} : CalcDS top bottom + define joinX : mix me.yrstrokel me.yrstroker (1 - me.px2) + define joinY : mix (bottom + ds2) (top - ds) (1 - me.py2) - define [SmallYStrokeSplitMask top bottom hooktop dir elev] : begin - local {ds ds2} : CalcDS top bottom - local jp0 : yJoinProportion hooktop (Width / 2 - Width / 2 * dir) - local jp1 : yJoinProportion hooktop (Width / 2 + Width / 2 * dir) - local hs : 0.75 * Stroke - local yLeft : [mix (bottom + ds2) (top - ds) jp1] + hs - [fallback elev 0] - local yRight : [mix (bottom + ds2) (top - ds) jp0] + hs - [fallback elev 0] - local yMin : Math.min bottom yLeft yRight - return : spiro-outline - corner Width yMin - corner Width yRight - corner 0 yLeft - corner 0 yMin + if bottomShape : return nothing + if (useStraightBottom) : begin + local xBaseKnot : mix me.yrstroker joinX ((top - bottom) / (top - joinY)) + include : HSerif.lb (xBaseKnot - [HSwToV HalfStroke]) bottom yBottomJut + : else : begin + include : HSerif.lb (me.yrstrokel - [HSwToV HalfStroke]) bottom yBottomJut + + export : define [ogonekAttach top bottom] : glyph-proc + define {ds ds2} : CalcDS top bottom + define coJoinX : if (straightBar && ts != TS-HOOKTOP) me.yrstroker [mix me.yrstrokel me.yrstroker me.px1] + define coJoinY : if (straightBar && ts != TS-HOOKTOP) top [mix (bottom + ds2) (top - ds) me.py1] + define joinX : mix me.yrstrokel me.yrstroker (1 - me.px2) + define joinY : mix (bottom + ds2) (top - ds) (1 - me.py2) + + define anchorX : mix coJoinX joinX ((0 - coJoinY) / (joinY - coJoinY)) + set-base-anchor 'trailing' anchorX 0 + OgonekTrY.set currentGlyph + + export : define [splitMask top bottom elev] : me.createSplitMask top bottom (-1) elev + + define [LeftHalf ts kShrink] : namespace + local me : Metrics ts kShrink + + export : define [topKnots top bottom] : begin + local {ds} : CalcDS top bottom + if straightBar + : then : return : list + flat (Width - me.yrstroker) top [widths.lhs.heading ([me.diagCor (top - bottom)] * Stroke) Downward] + : else : return : list + flat (Width - me.yrstroker) top [widths.lhs.heading Stroke Downward] + curl (Width - me.yrstroker) (top - ds) [heading Downward] + quadControls 0 me.dpy1 16 + + export : define [joinKnots top bottom] : begin + local {ds ds2} : CalcDS top bottom + return : list + if straightBar : then : list + : else : list + flat + mix (Width - me.yrstrokel) (Width - me.yrstroker) me.px1 + mix (bottom + ds2) (top - ds) me.py1 + curl Middle + me.yJoinHeight top bottom + widths.lhs (Stroke * me.yshrink) + + export : define [splitMask top bottom elev] : me.createSplitMask top bottom (+1) elev export : define [SmallYShape top bottom] : glyph-proc - local {ds ds2} : CalcDS top bottom + local right : RightHalf TS-NONE SHRINK-NONE + local rightSh : RightHalf TS-NONE SHRINK-INNER + local left : LeftHalf TS-NONE SHRINK-INNER - include : yOgonekAttach top bottom yshrink + include : right.ogonekAttach top bottom + include : union + intersection + dispiro + right.topKnots top bottom + right.baseKnots top bottom + left.splitMask top bottom - include : intersection - SmallYStrokeSplitMask top bottom false 1 - dispiro - yTopKnots yrstroker top bottom ds 1 - yBaseKnots top bottom 1 + difference + dispiro + right.topKnots top bottom + rightSh.baseKnots top bottom + left.splitMask top bottom - include : difference - dispiro - yTopKnots yrstroker top bottom ds 1 - yBaseKnots top bottom yshrink - SmallYStrokeSplitMask top bottom false 1 1 - - 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 + difference + dispiro + left.topKnots top bottom + left.joinKnots top bottom + right.splitMask top bottom + Rect (bottom + HalfStroke) (bottom - top) 0 Width if doSlabTop : include : let [sf : SerifFrame.fromDf [DivFrame 1] top bottom] composite-proc sf.lt.full sf.rt.full - if doSlabBottom : include : yBaseSerif top bottom + if doSlabBottom : include : right.baseSerif top bottom if doSlabMotion : include : HSerif.lt SB top SideJut export : define [SmallYHookTopShape top bottom] : glyph-proc - local {ds ds2} : CalcDS top bottom + local right : RightHalf TS-HOOKTOP SHRINK-NONE + local rightSh : RightHalf TS-HOOKTOP SHRINK-INNER + local left : LeftHalf TS-NONE SHRINK-INNER - include : yOgonekAttach top bottom yshrink true + include : right.ogonekAttach top bottom + include : union + intersection + dispiro + right.topKnots top bottom + right.baseKnots top bottom + left.splitMask top bottom - local startX : [mix yrstrokel yrstroker px1] - HalfStroke + [StrokeWidthBlend 0.5 0.75] * TailX - local startY : top - Stroke - O + difference + dispiro + right.topKnots top bottom + rightSh.baseKnots top bottom + left.splitMask top bottom - local [rightStroke shrink] : dispiro - straight.left.start startX startY [widths.rhs] - alsoThruThem {{[StrokeWidthBlend 0.58 0.65] 0.2} {[StrokeWidthBlend 0.78 0.85] 0.5}} important - yBaseKnots top bottom shrink true + difference + dispiro + left.topKnots top bottom + left.joinKnots top bottom + right.splitMask top bottom + Rect (bottom + HalfStroke) (bottom - top) 0 Width - include : intersection - rightStroke 1 - SmallYStrokeSplitMask top bottom true 1 - - include : difference - rightStroke yshrink - SmallYStrokeSplitMask top bottom true 1 1 - - include : difference - dispiro - widths.center - yTopKnots (Width - yrstroker) top bottom ds (-1) - yJoinKnots ds ds2 top bottom true - SmallYStrokeSplitMask top bottom true (-1) - Rect (bottom + HalfStroke) (bottom - top) 0 Width - - if doSlabTop : include : let [sf : SerifFrame.fromDf [DivFrame 1] top bottom] sf.lt.full - if doSlabBottom : include : yBaseSerif top bottom + if doSlabTop : include : let [sf : SerifFrame.fromDf [DivFrame 1] top bottom] sf.lt.full + if doSlabBottom : include : right.baseSerif top bottom if doSlabMotion : include : HSerif.lt SB top SideJut export : define [SmallLambdaShape top bottom] : union : glyph-proc