Skip to content

Commit d630c8c

Browse files
authored
Add latin vy (#2956)
* vy * Use ALL-OUTER instead since it is always MIDH-TOP * clipping fixes * more fixes in edge cases
1 parent 270e57e commit d630c8c

File tree

3 files changed

+138
-92
lines changed

3 files changed

+138
-92
lines changed

changes/33.3.5.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44
- CYRILLIC CAPITAL LETTER SHHA (`U+04BA`).
55
- CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER (`U+0526`).
66
- CYRILLIC CAPITAL LETTER HWE (`U+A694`).
7+
* Refine spacing of diagonal-tailed `i` and `j`.
8+
* Add Characters:
9+
- LATIN CAPITAL LETTER VY (`U+A760`).
10+
- LATIN SMALL LETTER VY (`U+A761`).

packages/font-glyphs/src/letter/latin/lower-y.ptl

Lines changed: 96 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,25 @@ glyph-block Letter-Latin-Lower-Y : begin
3030
define BS-TURN 1
3131
define BS-LOOP 2
3232

33-
define [GenNonCursiveShape straightBar bottomShape slabKind] : namespace
33+
glyph-block-export NonCursiveYShapeT NonCursiveYConfig
34+
define [NonCursiveYShapeT straightBar bottomShape slabKind _l _r _sb _sw] : namespace
3435
local { doSlabTop doSlabBottom doSlabMotion } slabKind
3536

37+
local l : fallback _l 0
38+
local r : fallback _r Width
39+
local m : mix l r 0.5
40+
local sb : fallback _sb SB
41+
local rsb : r + l - sb
42+
local sw : fallback _sw Stroke
43+
3644
local useStraightBottom : straightBar && !bottomShape
3745
local slabCurly : doSlabTop && !straightBar
3846
local slabCurlyNoTurnT : doSlabTop && !straightBar && !bottomShape
3947
local slabCurlyNoTurnB : doSlabBottom && !straightBar && !bottomShape
4048
local bottomIsNotVertical : doSlabBottom || useStraightBottom || bottomShape
4149

4250
define yBottomJut : Jut * 1.25
43-
define slabysize : 0.5 * yBottomJut * (Width / HalfUPM) + Stroke
51+
define slabysize : 0.5 * yBottomJut * (Width / HalfUPM) + sw
4452

4553
define [CalcDS top bottom] : begin
4654
local pds 0.1
@@ -53,7 +61,7 @@ glyph-block Letter-Latin-Lower-Y : begin
5361
return {ds ds2}
5462

5563
define [Metrics ts kShrink] : namespace
56-
define pxHookRightOffset : [StrokeWidthBlend (0.5 * TailX) (0.375 * TailX)] / (RightSB - SB)
64+
define pxHookRightOffset : [StrokeWidthBlend (0.5 * TailX) (0.375 * TailX)] / (rsb - sb)
5765
export : define px1 : 0.84 - [if (ts == TS-HOOK-RIGHT) pxHookRightOffset 0]
5866
export : define py1 : [StrokeWidthBlend 0.8 0.76] * [if slabCurly [StrokeWidthBlend 1 0.9] 1]
5967
export : define px2 : if slabCurlyNoTurnB px1 0.95
@@ -62,9 +70,9 @@ glyph-block Letter-Latin-Lower-Y : begin
6270
export : define dpy1 : (1 - [linreg (1 - px2) (1 - py2) px1 py1 1]) / (1 - py1)
6371
export : define dpy2 : (1 - [linreg (1 - px1) (1 - py1) px2 py2 1]) / (1 - py2)
6472

65-
define yrstrokel0 : mix Middle 0 0.2
66-
export : define yrstrokel : yrstrokel0 + [HSwToV : Stroke * [if bottomIsNotVertical (2 / 3) (1 / 3)] * [if slabCurly [StrokeWidthBlend 0.95 0.97] 1]]
67-
export : define yrstroker : mix Width RightSB : if straightBar DesignParameters.straightSmallYShapeSbShrink 1
73+
define yrstrokel0 : mix l r 0.4
74+
export : define yrstrokel : yrstrokel0 + [HSwToV : sw * [if bottomIsNotVertical (2 / 3) (1 / 3)] * [if slabCurly [StrokeWidthBlend 0.95 0.97] 1]]
75+
export : define yrstroker : mix r rsb : if straightBar DesignParameters.straightSmallYShapeSbShrink 1
6876

6977
export : define yshrink : mix 1 ([StrokeWidthBlend 1 0.85] * [if straightBar ([AdviceStroke 3.25] / Stroke) 1]) kShrink
7078

@@ -79,35 +87,35 @@ glyph-block Letter-Latin-Lower-Y : begin
7987

8088
export : define [yJoinHeight top bottom] : begin
8189
local {ds ds2} : CalcDS top bottom
82-
return : mix (bottom + ds2) (top - ds) [yJoinProportion Middle]
90+
return : mix (bottom + ds2) (top - ds) [yJoinProportion m]
8391

8492
export : define [createSplitMask top bottom dir elev] : begin
8593
local {ds ds2} : CalcDS top bottom
86-
local jp0 : yJoinProportion : mix Middle 0 dir
87-
local jp1 : yJoinProportion : mix Middle Width dir
88-
local hs : 0.75 * Stroke
94+
local jp0 : yJoinProportion : mix m l dir
95+
local jp1 : yJoinProportion : mix m r dir
96+
local hs : 0.75 * sw
8997
local yLeft : [mix (bottom + ds2) (top - ds) jp1] + hs - [fallback elev 0]
9098
local yRight : [mix (bottom + ds2) (top - ds) jp0] + hs - [fallback elev 0]
9199
local yMin : Math.min bottom yLeft yRight
92100
return : spiro-outline
93-
corner Width yMin
94-
corner Width yRight
95-
corner 0 yLeft
96-
corner 0 yMin
101+
corner r yMin
102+
corner r yRight
103+
corner l yLeft
104+
corner l yMin
97105

98-
define [RightHalf ts kShrink] : namespace
106+
export : define [RightHalf ts kShrink] : namespace
99107
local me : Metrics ts kShrink
100108

101109
export : define [topKnots top bottom] : begin
102110
local {ds} : CalcDS top bottom
103111
return : piecewise
104112
(ts == TS-HOOK-RIGHT) : list
105-
straight.left.start ([mix me.yrstrokel me.yrstroker me.px1] - HalfStroke + 0.875 * TailX) (top - Stroke - O) [widths.rhs]
113+
straight.left.start ([mix me.yrstrokel me.yrstroker me.px1] - (sw / 2) + 0.875 * TailX) (top - sw - O) [widths.rhs sw]
106114
alsoThruThem {{[StrokeWidthBlend 0.58 0.65] 0.2} {[StrokeWidthBlend 0.78 0.85] 0.5}} important
107115
straightBar : list
108-
flat me.yrstroker top [widths.rhs.heading ([me.diagCor (top - bottom)] * Stroke) Downward]
116+
flat me.yrstroker top [widths.rhs.heading ([me.diagCor (top - bottom)] * sw) Downward]
109117
true : list
110-
flat me.yrstroker top [widths.rhs.heading Stroke Downward]
118+
flat me.yrstroker top [widths.rhs.heading sw Downward]
111119
curl me.yrstroker (top - ds) [heading Downward]
112120
quadControls 0 me.dpy1 16
113121

@@ -118,7 +126,7 @@ glyph-block Letter-Latin-Lower-Y : begin
118126
define coJoinY : mix (bottom + ds2) (top - ds) me.py1
119127
define joinX : mix me.yrstrokel me.yrstroker (1 - me.px2)
120128
define joinY : mix (bottom + ds2) (top - ds) (1 - me.py2)
121-
define [ConnectZ shrink] [curl joinX joinY [widths.rhs : Stroke * shrink]]
129+
define [ConnectZ shrink] [curl joinX joinY [widths.rhs : sw * shrink]]
122130

123131
return : list
124132
if (straightBar && ts != TS-HOOK-RIGHT)
@@ -128,32 +136,32 @@ glyph-block Letter-Latin-Lower-Y : begin
128136
piecewise
129137
useStraightBottom : list
130138
ConnectZ me.yshrink
131-
curl [mix me.yrstroker joinX ((top - bottom) / (top - joinY))] bottom [widths.rhs.heading ([me.diagCor (top - bottom)] * Stroke) Downward]
139+
curl [mix me.yrstroker joinX ((top - bottom) / (top - joinY))] bottom [widths.rhs.heading ([me.diagCor (top - bottom)] * sw) Downward]
132140
(bottomShape == BS-LOOP) : begin
133141
local joinHeight1 : me.yJoinHeight top bottom
134-
local k : Math.abs : 1 / [Math.sin : Math.atan2 (joinX - Middle) (joinY - joinHeight1)] - 0.25
135-
local joinHeight3 : k * Stroke + joinHeight1
136-
local deltaX : Math.max yBottomJut : HSwToV : 1.2 * Stroke
137-
local fine : AdviceStroke 3
142+
local k : Math.abs : 1 / [Math.sin : Math.atan2 (joinX - m) (joinY - joinHeight1)] - 0.25
143+
local joinHeight3 : k * sw + joinHeight1
144+
local deltaX : Math.max yBottomJut : HSwToV : 1.2 * sw
145+
local fine : [AdviceStroke 3] / Stroke * sw
138146
local xLoopLeft : Math.min (joinX - [HSwToV : 1.5 * fine]) : Math.max ((-0.25) * SB) : mix joinX (me.yrstrokel - deltaX) 2
139147
local xCenter : mix xLoopLeft joinX 0.5
140148
list
141149
ConnectZ me.yshrink
142-
g2.left.mid [arch.adjust-x.bot xCenter fine] bottom [widths.rhs]
150+
g2.left.mid [arch.adjust-x.bot xCenter fine] bottom [widths.rhs sw]
143151
archv
144152
g2.up.mid xLoopLeft [mix bottom joinHeight3 0.5] [widths.rhs.heading fine Upward]
145153
arcvh
146154
flat xCenter joinHeight3 [heading Rightward]
147-
curl Middle joinHeight3 [heading Rightward]
155+
curl m joinHeight3 [heading Rightward]
148156
(bottomShape == BS-TURN) : list
149157
ConnectZ me.yshrink
150-
flat (me.yrstrokel - slabysize) bottom [widths.rhs]
158+
flat (me.yrstrokel - slabysize) bottom [widths.rhs sw]
151159
curl [Math.min (me.yrstrokel - slabysize - TINY) (me.yrstrokel - Stroke - yBottomJut)] bottom
152160
true : list
153161
ConnectZ 1
154162
quadControls 1 (1 - me.dpy2) 16
155-
flat me.yrstrokel (bottom + ds2) [widths.heading 0 Stroke Downward]
156-
curl me.yrstrokel bottom [widths.heading 0 Stroke Downward]
163+
flat me.yrstrokel (bottom + ds2) [widths.rhs.heading sw Downward]
164+
curl me.yrstrokel bottom [widths.rhs.heading sw Downward]
157165

158166
export : define [baseSerif top bottom] : glyph-proc
159167
local {ds ds2} : CalcDS top bottom
@@ -163,9 +171,9 @@ glyph-block Letter-Latin-Lower-Y : begin
163171
if bottomShape : return nothing
164172
if (useStraightBottom) : begin
165173
local xBaseKnot : mix me.yrstroker joinX ((top - bottom) / (top - joinY))
166-
include : HSerif.lb (xBaseKnot - [HSwToV HalfStroke]) bottom yBottomJut
174+
include : HSerif.lb (xBaseKnot - [HSwToV : sw / 2]) bottom yBottomJut
167175
: else : begin
168-
include : HSerif.lb (me.yrstrokel - [HSwToV HalfStroke]) bottom yBottomJut
176+
include : HSerif.lb (me.yrstrokel - [HSwToV : sw / 2]) bottom yBottomJut
169177

170178
export : define [ogonekAttach top bottom] : glyph-proc
171179
define {ds ds2} : CalcDS top bottom
@@ -180,17 +188,17 @@ glyph-block Letter-Latin-Lower-Y : begin
180188

181189
export : define [splitMask top bottom elev] : me.createSplitMask top bottom (-1) elev
182190

183-
define [LeftHalf ts kShrink] : namespace
191+
export : define [LeftHalf ts kShrink] : namespace
184192
local me : Metrics ts kShrink
185193

186194
export : define [topKnots top bottom] : begin
187195
local {ds} : CalcDS top bottom
188196
if straightBar
189197
: then : return : list
190-
flat (Width - me.yrstroker) top [widths.lhs.heading ([me.diagCor (top - bottom)] * Stroke) Downward]
198+
flat (l + r - me.yrstroker) top [widths.lhs.heading ([me.diagCor (top - bottom)] * sw) Downward]
191199
: else : return : list
192-
flat (Width - me.yrstroker) top [widths.lhs.heading Stroke Downward]
193-
curl (Width - me.yrstroker) (top - ds) [heading Downward]
200+
flat (l + r - me.yrstroker) top [widths.lhs.heading sw Downward]
201+
curl (l + r - me.yrstroker) (top - ds) [heading Downward]
194202
quadControls 0 me.dpy1 16
195203

196204
export : define [joinKnots top bottom] : begin
@@ -199,85 +207,81 @@ glyph-block Letter-Latin-Lower-Y : begin
199207
if straightBar : then : list
200208
: else : list
201209
flat
202-
mix (Width - me.yrstrokel) (Width - me.yrstroker) me.px1
210+
mix (l + r - me.yrstrokel) (l + r - me.yrstroker) me.px1
203211
mix (bottom + ds2) (top - ds) me.py1
204212
curl Middle
205213
me.yJoinHeight top bottom
206-
widths.lhs (Stroke * me.yshrink)
214+
widths.lhs (sw * me.yshrink)
207215

208216
export : define [splitMask top bottom elev] : me.createSplitMask top bottom (+1) elev
209217

210-
export : define [SmallYShape top bottom] : glyph-proc
218+
export : define [SmallYShape top bottom yShCutoff] : glyph-proc
211219
local right : RightHalf TS-NONE SHRINK-NONE
212220
local rightSh : RightHalf TS-NONE SHRINK-INNER
213221
local left : LeftHalf TS-NONE SHRINK-INNER
214222

223+
local leftSplitMask : if (yShCutoff !== nothing)
224+
union [MaskBelow yShCutoff] : left.splitMask top bottom
225+
left.splitMask top bottom
226+
215227
include : right.ogonekAttach top bottom
216-
include : union
228+
include : tagged 'rightHalf' : union
217229
intersection
218230
dispiro
219231
right.topKnots top bottom
220232
right.baseKnots top bottom
221-
left.splitMask top bottom
233+
* leftSplitMask
222234

223235
difference
224236
dispiro
225237
right.topKnots top bottom
226238
rightSh.baseKnots top bottom
227-
left.splitMask top bottom
239+
* leftSplitMask
228240

229-
difference
230-
dispiro
231-
left.topKnots top bottom
232-
left.joinKnots top bottom
233-
right.splitMask top bottom
234-
Rect (bottom + HalfStroke) (bottom - top) 0 Width
235-
236-
if doSlabTop
237-
let [sf : SerifFrame.fromDf [DivFrame 1] top bottom] : composite-proc sf.lt.full sf.rt.full
238-
no-shape
239-
if doSlabBottom
240-
right.baseSerif top bottom
241-
no-shape
242-
if doSlabMotion
243-
HSerif.lt SB top SideJut
244-
no-shape
245-
246-
export : define [SmallYHookRightShape top bottom] : glyph-proc
241+
include : tagged 'leftHalf' : difference
242+
dispiro
243+
left.topKnots top bottom
244+
left.joinKnots top bottom
245+
right.splitMask top bottom
246+
Rect (bottom + sw / 2) (bottom - top) l r
247+
248+
if doSlabTop : include : let [sf : SerifFrame.fromDf [DivFrame 1] top bottom] : composite-proc sf.lt.full sf.rt.full
249+
if doSlabBottom : include : right.baseSerif top bottom
250+
if doSlabMotion : include : HSerif.lt sb top SideJut
251+
252+
export : define [SmallYHookRightShape top bottom yShCutoff] : glyph-proc
247253
local right : RightHalf TS-HOOK-RIGHT SHRINK-NONE
248254
local rightSh : RightHalf TS-HOOK-RIGHT SHRINK-INNER
249255
local left : LeftHalf TS-NONE SHRINK-INNER
250256

257+
local leftSplitMask : if (yShCutoff !== nothing)
258+
intersection [MaskAbove yShCutoff] : left.splitMask top bottom
259+
left.splitMask top bottom
260+
251261
include : right.ogonekAttach top bottom
252-
include : union
262+
include : tagged 'rightHalf' : union
253263
intersection
254264
dispiro
255265
right.topKnots top bottom
256266
right.baseKnots top bottom
257-
left.splitMask top bottom
267+
* leftSplitMask
258268

259269
difference
260270
dispiro
261271
right.topKnots top bottom
262272
rightSh.baseKnots top bottom
263-
left.splitMask top bottom
273+
* leftSplitMask
264274

265-
difference
266-
dispiro
267-
left.topKnots top bottom
268-
left.joinKnots top bottom
269-
right.splitMask top bottom
270-
Rect (bottom + HalfStroke) (bottom - top) 0 Width
271-
272-
if doSlabTop
273-
let [sf : SerifFrame.fromDf [DivFrame 1] top bottom] sf.lt.full
274-
no-shape
275-
if doSlabBottom
276-
right.baseSerif top bottom
277-
no-shape
278-
if doSlabMotion
279-
HSerif.lt SB top SideJut
280-
no-shape
275+
include : tagged 'leftHalf' : difference
276+
dispiro
277+
left.topKnots top bottom
278+
left.joinKnots top bottom
279+
right.splitMask top bottom
280+
Rect (bottom + sw / 2) (bottom - top) l r
281+
282+
if doSlabTop : include : let [sf : SerifFrame.fromDf [DivFrame 1] top bottom] sf.lt.full
283+
if doSlabBottom : include : right.baseSerif top bottom
284+
if doSlabMotion : include : HSerif.lt sb top SideJut
281285

282286
export : define [SmallLambdaShape top bottom] : union : glyph-proc
283287
set currentGlyph.gizmo : Italify (-para.slopeAngle)
@@ -295,7 +299,7 @@ glyph-block Letter-Latin-Lower-Y : begin
295299
include : Scale (+1) (-1)
296300
include : Translate 0 (+[mix bottom top 0.5])
297301

298-
define NonCursiveConfig : SuffixCfg.weave
302+
define NonCursiveYConfig : SuffixCfg.weave
299303
object # body
300304
straight true
301305
curly false
@@ -309,8 +313,8 @@ glyph-block Letter-Latin-Lower-Y : begin
309313
serifed SLAB-ALL
310314
motionSerifed SLAB-MOTION
311315

312-
foreach { suffix { straightBar bottomShape slabKind } } [Object.entries NonCursiveConfig] : do
313-
define Shapes : GenNonCursiveShape straightBar bottomShape slabKind
316+
foreach { suffix { straightBar bottomShape slabKind } } [Object.entries NonCursiveYConfig] : do
317+
define Shapes : NonCursiveYShapeT straightBar bottomShape slabKind
314318
create-glyph "y.\(suffix)" : glyph-proc
315319
include : MarkSet.p
316320
set-base-anchor 'strike' Middle (XH / 2)
@@ -357,7 +361,7 @@ glyph-block Letter-Latin-Lower-Y : begin
357361
alias 'grek/lambda.curlyTailedTurnSerifless' null 'grek/lambdaTailed.curlyTurnSerifless'
358362
alias 'latn/lambdaStroke.curlyTailedTurnSerifless' null 'latn/lambdaStrokeTailed.curlyTurnSerifless'
359363

360-
define Cursive : namespace
364+
define CursiveYShape : namespace
361365
export : define [Arc top bottom] : uBowl.shape
362366
top -- top
363367
bottom -- bottom
@@ -389,37 +393,37 @@ glyph-block Letter-Latin-Lower-Y : begin
389393
include sf.lt.outer
390394
if [not doSlabMotion] : include sf.rt.inner
391395

392-
define CursiveConfig : SuffixCfg.weave
396+
define CursiveYConfig : SuffixCfg.weave
393397
object # body
394-
cursive Cursive.Hook
395-
cursiveFlatHook Cursive.FlatHook
398+
cursive CursiveYShape.Hook
399+
cursiveFlatHook CursiveYShape.FlatHook
396400
object # serifs
397401
serifless SLAB-NONE
398402
serifed SLAB-ALL
399403
motionSerifed SLAB-CURSIVE-MOTION
400404

401-
foreach { suffix { hookShape slabKind } } [Object.entries CursiveConfig] : do
405+
foreach { suffix { hookShape slabKind } } [Object.entries CursiveYConfig] : do
402406
create-glyph "y.\(suffix)" : glyph-proc
403407
include : MarkSet.p
404408
set-base-anchor 'strike' Middle (XH / 2)
405409
set-base-anchor 'yBelowDot' Middle Descender
406-
include : Cursive.Arc XH 0
410+
include : CursiveYShape.Arc XH 0
407411
include : hookShape XH Descender
408-
include : Cursive.Serifs XH slabKind
412+
include : CursiveYShape.Serifs XH slabKind
409413

410414
if (slabKind !== SLAB-ALL) : create-glyph "yHookRight.\(suffix)" : glyph-proc
411415
include : MarkSet.p
412-
include : Cursive.Arc XH 0
416+
include : CursiveYShape.Arc XH 0
413417
include : hookShape (XH - TailY - HalfStroke) Descender
414418
include : TopHook.toRight.rBarInner RightSB 0 XH
415-
include : Cursive.Serifs XH slabKind
419+
include : CursiveYShape.Serifs XH slabKind
416420
eject-contour 'serifRT'
417421

418422
create-glyph "yCap.\(suffix)" : glyph-proc
419423
include : MarkSet.capital
420-
include : Cursive.Arc CAP (CAP - XH)
424+
include : CursiveYShape.Arc CAP (CAP - XH)
421425
include : hookShape CAP 0
422-
include : Cursive.Serifs CAP slabKind
426+
include : CursiveYShape.Serifs CAP slabKind
423427

424428
select-variant 'y' 'y'
425429
link-reduced-variant 'y/sansSerif' 'y' MathSansSerif

0 commit comments

Comments
 (0)