char/iocgn-mono

iosevka variant inspired by Simple Köln-Bonn

git clone https://git.t4t.associates/char/iocgn-mono

Charlotte Somsimplify pipeline even more (less python!! :D)2ba32a9

main
43.0 KiB942 linesraw
1diff --git a/packages/font-glyphs/src/auto-build/composite.ptl b/packages/font-glyphs/src/auto-build/composite.ptl
2index cce1ecc..6cffb46 100644
3--- a/packages/font-glyphs/src/auto-build/composite.ptl
4+++ b/packages/font-glyphs/src/auto-build/composite.ptl
5@@ -62,7 +62,7 @@ glyph-block Autobuild-Enclosure-Shared : begin
6 		local decomposableJobs      { }
7 		local relApplications       { }
8 		local decomposableRelGlyphs : new Set
9-		foreach demand [items-of demands] : do
10+		foreach demand [items-of demands] : if (!recursive || !recursive.koeln || [recursive.koelnCodes.has demand.0]) : do
11 			local unicode       demand.0
12 			local origParts     demand.1
13 			local mappedParts : MapPartNameWithWidthSuffix origParts suffix
14@@ -1601,8 +1601,9 @@ glyph-block Autobuild-Ligatures : begin
15 		list 0xf883 { 'iAcute' 'jAcute' }
16 
17 	# Link Gr for acute variants
18-	NLDAcuteVariant.set [glyphStore.queryByUnicodeEnsured 0x132] [glyphStore.queryNameByUnicodeEnsured 0xf882]
19-	NLDAcuteVariant.set [glyphStore.queryByUnicodeEnsured 0x133] [glyphStore.queryNameByUnicodeEnsured 0xf883]
20+	if (!recursive || !recursive.koeln) : begin
21+		NLDAcuteVariant.set [glyphStore.queryByUnicodeEnsured 0x132] [glyphStore.queryNameByUnicodeEnsured 0xf882]
22+		NLDAcuteVariant.set [glyphStore.queryByUnicodeEnsured 0x133] [glyphStore.queryNameByUnicodeEnsured 0xf883]
23 
24 	define stdShrink : clamp 0.75 0.9 : StrokeWidthBlend 0.75 0.9
25 	createLigatures 'compatLigature2' stdShrink stdShrink 1 1 0 : list
26@@ -1627,9 +1628,10 @@ glyph-block Autobuild-Ligatures : begin
27 		list 0x1F190 { 'D' 'J' } WideWidth1
28 
29 	# Link Gr for caron variants
30-	HBSCaronVariant.set [glyphStore.queryByUnicodeEnsured 0x1F1] [glyphStore.queryNameByUnicodeEnsured 0x1C4]
31-	HBSCaronVariant.set [glyphStore.queryByUnicodeEnsured 0x1F2] [glyphStore.queryNameByUnicodeEnsured 0x1C5]
32-	HBSCaronVariant.set [glyphStore.queryByUnicodeEnsured 0x1F3] [glyphStore.queryNameByUnicodeEnsured 0x1C6]
33+	if (!recursive || !recursive.koeln) : begin
34+		HBSCaronVariant.set [glyphStore.queryByUnicodeEnsured 0x1F1] [glyphStore.queryNameByUnicodeEnsured 0x1C4]
35+		HBSCaronVariant.set [glyphStore.queryByUnicodeEnsured 0x1F2] [glyphStore.queryNameByUnicodeEnsured 0x1C5]
36+		HBSCaronVariant.set [glyphStore.queryByUnicodeEnsured 0x1F3] [glyphStore.queryNameByUnicodeEnsured 0x1C6]
37 
38 	createLigatures 'romanNumerals1' 1 1 1 1 0 : list
39 		list 0x2160 { 'I' }
40diff --git a/packages/font-glyphs/src/index.ptl b/packages/font-glyphs/src/index.ptl
41index 239bd59..b67daaa 100644
42--- a/packages/font-glyphs/src/index.ptl
43+++ b/packages/font-glyphs/src/index.ptl
44@@ -6,12 +6,15 @@ import as SpiroKit from "@iosevka/font-kits/spiro-kit"
45 import as BooleKit from "@iosevka/font-kits/boole-kit"
46 import [DesignParameters calculateMetrics setFontMetrics GenDivFrame] from "./meta/aesthetics.mjs"
47 import [$NamedParameterPair$] from "@iosevka/util"
48+import [refineAscii] from "../iocgn-ascii.mjs"
49+import [buildNative] from "../iocgn-native.mjs"
50 
51 extern isFinite
52 
53 $$include './meta/macros.ptl'
54 
55-export : define [buildGlyphs para recursive] : begin
56+export : define [buildGlyphs para recursive koelnGeometry] : begin
57+	if (!recursive && !koelnGeometry) : return : buildNative para buildGlyphs
58 	# Execution and dependency management
59 	local $Exec$ : new GlyphBuildExecutor recursive
60 
61@@ -108,12 +111,13 @@ export : define [buildGlyphs para recursive] : begin
62 	run-glyph-module "./orthography/index.mjs"
63 
64 	# Auto-builds
65-	if [not recursive] : begin
66+	if (!recursive || recursive.koeln) : begin
67 		run-glyph-module "./auto-build/recursive-build.mjs"
68 		run-glyph-module "./auto-build/accents.mjs"
69-		run-glyph-module "./auto-build/transformed.mjs"
70+		if [not recursive] : run-glyph-module "./auto-build/transformed.mjs"
71 		run-glyph-module "./auto-build/composite.mjs"
72 
73 	$Exec$.executePendingBlocks
74+	refineAscii glyphStore Metrics para
75 
76-	return : object glyphStore fontMetrics
77+	return : object glyphStore fontMetrics [metrics Metrics] [executor $Exec$]
78diff --git a/packages/font-glyphs/src/letter/latin/c.ptl b/packages/font-glyphs/src/letter/latin/c.ptl
79index 27fe5e7..f96d23e 100644
80--- a/packages/font-glyphs/src/letter/latin/c.ptl
81+++ b/packages/font-glyphs/src/letter/latin/c.ptl
82@@ -1,5 +1,7 @@
83 $$include '../../meta/macros.ptl'
84 
85+import [lowerBowl lowerWidth] from "../../../iocgn-shapes.mjs"
86+
87 import [mix linreg clamp fallback SuffixCfg] from "@iosevka/util"
88 import [DependentSelector MathSansSerif] from "@iosevka/glyph/relation"
89 
90@@ -179,7 +181,13 @@ glyph-block Letter-Latin-C : begin
91 			local lf : CLetterForm [DivFrame 1] sty styBot XH 0
92 				ada -- SmallArchDepthA
93 				adb -- SmallArchDepthB
94-			include : lf.full
95+			local radius : ([lowerWidth Width [HSwToV Stroke]] - 20 * Width / 660) / 2
96+			local terminalExtension : Math.max (Stroke * 0.16) (Stroke * 0.5 - 21.5)
97+			include : if (sty == SLAB-NONE && styBot == SLAB-NONE)
98+				difference
99+					lowerBowl Middle Width XH [HSwToV Stroke]
100+					Rect (XH + 10 - radius - terminalExtension) (radius - 14.5 + 0.04 * Stroke + terminalExtension) Middle Width
101+				lf.full
102 
103 		create-glyph "c/centKernelStd.\(suffix)" : glyph-proc
104 			set-width 0
105diff --git a/packages/font-glyphs/src/letter/latin/lower-a.ptl b/packages/font-glyphs/src/letter/latin/lower-a.ptl
106index 577e9d6..e04cb2e 100644
107--- a/packages/font-glyphs/src/letter/latin/lower-a.ptl
108+++ b/packages/font-glyphs/src/letter/latin/lower-a.ptl
109@@ -2,6 +2,7 @@ $$include '../../meta/macros.ptl'
110 
111 import [mix linreg fallback SuffixCfg] from "@iosevka/util"
112 import [MathSansSerif] from "@iosevka/glyph/relation"
113+import [doubleStoreyA] from "../../../iocgn-shapes.mjs"
114 
115 glyph-module
116 
117@@ -88,10 +89,8 @@ glyph-block Letter-Latin-Lower-A : begin
118 			Serifless  df hookStyle sw
119 			begin [SerifFrame.fromDf df XH 0 (swRef -- [fallback sw : ADoubleStoreyStroke df]) (swSerif -- df.mvs)].rb.outer
120 
121-		export : define [Tailed df hookStyle sw] : union
122-			HookAndBar df hookStyle (XH - [ADoubleStoreySmoothB df] + O) sw
123-			Arc        df 0         0                                    sw
124-			RightwardTailedBar df.rightSB 0 (XH - [ADoubleStoreySmoothB df]) [fallback sw : ADoubleStoreyStroke df]
125+		export : define [Tailed df hookStyle sw] : glyph-proc
126+			include : doubleStoreyA df.middle df.width XH [HSwToV : fallback sw df.mvs]
127 
128 		export : define [ToothlessCorner df hookStyle sw] : union
129 			HookAndBar df hookStyle DToothlessRise sw
130diff --git a/packages/font-glyphs/src/letter/latin/lower-b.ptl b/packages/font-glyphs/src/letter/latin/lower-b.ptl
131index b3864ec..c2c0257 100644
132--- a/packages/font-glyphs/src/letter/latin/lower-b.ptl
133+++ b/packages/font-glyphs/src/letter/latin/lower-b.ptl
134@@ -1,5 +1,7 @@
135 $$include '../../meta/macros.ptl'
136 
137+import [lowerBowl lowerWidth] from "../../../iocgn-shapes.mjs"
138+
139 import [mix fallback SuffixCfg] from "@iosevka/util"
140 import [MathSansSerif] from "@iosevka/glyph/relation"
141 
142@@ -52,10 +54,12 @@ glyph-block Letter-Latin-Lower-B : begin
143 		local yOverlay : mix XH (Ascender - [if doST Stroke 0]) 0.5
144 		create-glyph "b.\(suffix)" : glyph-proc
145 			include : MarkSet.b
146-			include : Body Ascender
147+			local fitted : Body == ToothedBody && Serifs == no-shape
148+			local xStem : if fitted (Middle - [lowerWidth Width [HSwToV Stroke]] / 2) SB
149+			include : if fitted [lowerBowl Middle Width XH [HSwToV Stroke] (-1) Ascender 0] [Body Ascender]
150 			include : Serifs
151-			include : LeaningAnchor.Above.VBar.l SB
152-			set-base-anchor 'overlayOnExtension' (SB + [HSwToV HalfStroke]) yOverlay
153+			include : LeaningAnchor.Above.VBar.l xStem
154+			set-base-anchor 'overlayOnExtension' (xStem + [HSwToV HalfStroke]) yOverlay
155 			set-base-anchor 'overlay' Middle (XH / 2)
156 			set-base-anchor 'strike'  Middle (XH / 2)
157 
158diff --git a/packages/font-glyphs/src/letter/latin/lower-d.ptl b/packages/font-glyphs/src/letter/latin/lower-d.ptl
159index 37bd59f..1abe30b 100644
160--- a/packages/font-glyphs/src/letter/latin/lower-d.ptl
161+++ b/packages/font-glyphs/src/letter/latin/lower-d.ptl
162@@ -1,5 +1,7 @@
163 $$include '../../meta/macros.ptl'
164 
165+import [lowerBowl lowerWidth] from "../../../iocgn-shapes.mjs"
166+
167 import [mix clamp fallback SuffixCfg] from "@iosevka/util"
168 import [MathSansSerif] from "@iosevka/glyph/relation"
169 
170@@ -91,11 +93,13 @@ glyph-block Letter-Latin-Lower-D : begin
171 		: where : [make df] : glyph-proc
172 			include : DivFrame 1
173 			include : df.markSet.b
174-			include : Body df Ascender
175+			local fitted : Body == ToothedBody && !topSerif && !bottomSerif
176+			local xStem : if fitted (df.middle + [lowerWidth df.width [HSwToV df.mvs]] / 2) df.rightSB
177+			include : if fitted [lowerBowl df.middle df.width XH [HSwToV df.mvs] 1 Ascender 0] [Body df Ascender]
178 			if topSerif    : include : topSerif    df Ascender
179 			if bottomSerif : include : bottomSerif df Ascender
180-			include : LeaningAnchor.Above.VBar.r df.rightSB df.mvs
181-			set-base-anchor 'overlayOnExtension' (df.rightSB - [HSwToV : 0.5 * df.mvs]) yOverlay
182+			include : LeaningAnchor.Above.VBar.r xStem df.mvs
183+			set-base-anchor 'overlayOnExtension' (xStem - [HSwToV : 0.5 * df.mvs]) yOverlay
184 			set-base-anchor 'overlay' df.middle (XH / 2)
185 			set-base-anchor 'strike'  df.middle (XH / 2)
186 
187diff --git a/packages/font-glyphs/src/letter/latin/lower-e.ptl b/packages/font-glyphs/src/letter/latin/lower-e.ptl
188index 48ab2b0..d450294 100644
189--- a/packages/font-glyphs/src/letter/latin/lower-e.ptl
190+++ b/packages/font-glyphs/src/letter/latin/lower-e.ptl
191@@ -1,5 +1,7 @@
192 $$include '../../meta/macros.ptl'
193 
194+import [lowerBowl lowerWidth] from "../../../iocgn-shapes.mjs"
195+
196 import [mix linreg clamp fallback] from "@iosevka/util"
197 import [DependentSelector] from "@iosevka/glyph/relation"
198 
199@@ -227,10 +229,19 @@ glyph-block Letter-Latin-Lower-E : begin
200 	foreach { suffix { Body RevBody } } [Object.entries SmallEConfig] : do
201 		create-glyph "e.\(suffix)" : glyph-proc
202 			include : MarkSet.e
203-			include : Body [DivFrame 1] XH
204-				hook -- AHook
205-				ada  -- SmallArchDepthA
206-				adb  -- SmallArchDepthB
207+			include : if (Body == SmallEShape)
208+				glyph-proc
209+					local span : lowerWidth Width [HSwToV Stroke]
210+					local radius : (span - 20 * Width / 660) / 2
211+					local barBottom : XH * (259 / 525) - 0.47 * Stroke
212+					include : difference
213+						lowerBowl Middle Width XH [HSwToV Stroke]
214+						Rect barBottom (radius - 34.5 + 0.04 * Stroke) Middle Width
215+					include : HBar.b (Middle - span / 2) (Middle + span / 2) barBottom Stroke
216+				Body [DivFrame 1] XH
217+					hook -- AHook
218+					ada  -- SmallArchDepthA
219+					adb  -- SmallArchDepthB
220 
221 		create-glyph "eOgonek.\(suffix)" : glyph-proc
222 			include : MarkSet.e
223diff --git a/packages/font-glyphs/src/letter/latin/lower-f.ptl b/packages/font-glyphs/src/letter/latin/lower-f.ptl
224index 271bf2f..8c34af7 100644
225--- a/packages/font-glyphs/src/letter/latin/lower-f.ptl
226+++ b/packages/font-glyphs/src/letter/latin/lower-f.ptl
227@@ -2,6 +2,7 @@ $$include '../../meta/macros.ptl'
228 
229 import [mix fallback SuffixCfg] from "@iosevka/util"
230 import [MathSansSerif] from "@iosevka/glyph/relation"
231+import [roundHook] from "../../../iocgn-shapes.mjs"
232 
233 glyph-module
234 
235@@ -88,9 +89,9 @@ glyph-block Letter-Latin-Lower-F : begin
236 		include : LeaningAnchor.Above.Hook barLeft (df.rightSB + barLeft - barLeft0)
237 		set-base-anchor 'overlay' (barLeft + [HSwToV HalfStroke]) (bh / 2)
238 
239-		include : StdFShapeT dispiro df 0 barLeft0 Stroke
240+		include : roundHook (-barLeft0) 0 (O - Ascender) (132 + 0.36 * Stroke) [HSwToV Stroke] 120 true
241 		include : Translate (barLeft - barLeft0) 0
242-		include : HCrossBar.top SB [mix df.leftSB df.rightSB m] bh
243+		include : HCrossBar.top (barLeft - 80) (barLeft + 175 + 0.87 * Stroke) bh
244 
245 		include : match counterHook
246 			[Just CH-NONE]          : SetPalatalHookPos barLeft
247diff --git a/packages/font-glyphs/src/letter/latin/lower-g.ptl b/packages/font-glyphs/src/letter/latin/lower-g.ptl
248index b5da9f7..7eb6277 100644
249--- a/packages/font-glyphs/src/letter/latin/lower-g.ptl
250+++ b/packages/font-glyphs/src/letter/latin/lower-g.ptl
251@@ -2,6 +2,7 @@ $$include '../../meta/macros.ptl'
252 
253 import [mix fallback SuffixCfg] from "@iosevka/util"
254 import [MathSansSerif] from "@iosevka/glyph/relation"
255+import [roundHook] from "../../../iocgn-shapes.mjs"
256 
257 glyph-module
258 
259@@ -97,7 +98,8 @@ glyph-block Letter-Latin-Lower-G : begin
260 				g4   (df.leftSB  + offset) (Descender + SHook)
261 				if (sink == spiro-outline) { [corner df.leftSB XH] } {}
262 
263-		export : define [BentHook df y0 _ada _adb] : BentHookT dispiro df y0 0 df.mvs _ada _adb
264+		export : define [BentHook df y0 _ada _adb] : glyph-proc
265+			include : roundHook df.rightSB y0 (Descender + O) ((df.rightSB - df.leftSB) / 2) [HSwToV df.mvs] 155
266 		export : define [FlatHook df y0 _ada _adb] : begin
267 			local hd : FlatHookDepth df (9 / 8)
268 			local xTerminal : Math.min (df.rightSB - hd.x - TINY) : mix df.leftSB df.rightSB (1 / 5)
269@@ -183,7 +185,7 @@ glyph-block Letter-Latin-Lower-G : begin
270 
271 	foreach { suffix { hookShape {bodyShape hookStart} } } [Object.entries SingleStoreyConfig] : do
272 		create-glyph "g.\(suffix)" : glyph-proc
273-			local df : include : DivFrame 1
274+			local df : include : DivFrame 1 2 1.16 Stroke
275 			include : df.markSet.p
276 			set-base-anchor 'overlay' df.middle (XH / 2)
277 			set-base-anchor 'strike'  df.middle (XH / 2)
278diff --git a/packages/font-glyphs/src/letter/latin/lower-h.ptl b/packages/font-glyphs/src/letter/latin/lower-h.ptl
279index 8fd5a6c..97b184e 100644
280--- a/packages/font-glyphs/src/letter/latin/lower-h.ptl
281+++ b/packages/font-glyphs/src/letter/latin/lower-h.ptl
282@@ -1,5 +1,7 @@
283 $$include '../../meta/macros.ptl'
284 
285+import [shoulder lowerWidth] from "../../../iocgn-shapes.mjs"
286+
287 import [mix fallback SuffixCfg] from "@iosevka/util"
288 import [MathSansSerif] from "@iosevka/glyph/relation"
289 
290@@ -58,12 +60,14 @@ glyph-block Letter-Latin-Lower-H : begin
291 	foreach { suffix { fTailed {Serifs fHasTopSerif} } } [Object.entries HConfig] : do
292 		create-glyph "h.\(suffix)" : glyph-proc
293 			include : MarkSet.b
294-			include : LeaningAnchor.Above.VBar.l SB
295-			include : VBar.l SB 0 Ascender
296-			include : nShoulder.shape
297-				left -- (SB + [HSwToV Stroke])
298-				right -- RightSB
299-				bottom -- [if fTailed (XH - SmallArchDepthB + O) 0]
300+			local fitted : !fTailed && !fHasTopSerif
301+			include : LeaningAnchor.Above.VBar.l [if fitted (Middle - [lowerWidth Width [HSwToV Stroke]] / 2) SB]
302+			include : if fitted [shoulder Middle Width XH Ascender [HSwToV Stroke]] : glyph-proc
303+				include : VBar.l SB 0 Ascender
304+				include : nShoulder.shape
305+					left -- (SB + [HSwToV Stroke])
306+					right -- RightSB
307+					bottom -- [if fTailed (XH - SmallArchDepthB + O) 0]
308 			if fTailed : include : RightwardTailedBar RightSB 0 (XH - SmallArchDepthB)
309 			include : Serifs fTailed false
310 
311diff --git a/packages/font-glyphs/src/letter/latin/lower-j.ptl b/packages/font-glyphs/src/letter/latin/lower-j.ptl
312index 8751a22..ed57799 100644
313--- a/packages/font-glyphs/src/letter/latin/lower-j.ptl
314+++ b/packages/font-glyphs/src/letter/latin/lower-j.ptl
315@@ -2,6 +2,7 @@ $$include '../../meta/macros.ptl'
316 
317 import [mix linreg clamp fallback] from "@iosevka/util"
318 import [Dotless MathSansSerif] from "@iosevka/glyph/relation"
319+import [roundHook] from "../../../iocgn-shapes.mjs"
320 
321 glyph-module
322 
323@@ -47,14 +48,11 @@ glyph-block Letter-Latin-Lower-J : begin
324 
325 	define JBody : namespace
326 		export : define [BentHook df top xMiddle] : glyph-proc
327-			local hookx : Math.min ((xMiddle - df.middle) - [HSwToV HalfStroke] + OXHook) (xMiddle - [HSwToV : 1.5 * Stroke] + OXHook)
328+			local hookx : xMiddle + [HSwToV HalfStroke] - (205 + [HSwToV HalfStroke]) * df.width / 660
329 			set-base-anchor "below" [mix hookx xMiddle 0.5] Descender
330-			include : dispiro
331-				widths.rhs
332-				flat (xMiddle + [HSwToV HalfStroke]) top [heading Downward]
333-				curl (xMiddle + [HSwToV HalfStroke]) (Descender + ArchDepthA)
334-				HookEnd Descender
335-				g4 hookx (Descender + JHook)
336+			local right : xMiddle + [HSwToV HalfStroke]
337+			local radius : (right - hookx) / (1 + [Math.sin : Math.PI / 9])
338+			include : roundHook right top (Descender + O) radius [HSwToV Stroke] 110
339 
340 		export : define [NarrowBentHook df top xMiddle] : glyph-proc
341 			local pAdaptive : if (para.advanceScaleF < 1) ((1 - df.adws) / (1 - para.advanceScaleF)) 0
342diff --git a/packages/font-glyphs/src/letter/latin/lower-m.ptl b/packages/font-glyphs/src/letter/latin/lower-m.ptl
343index a647d8c..142e459 100644
344--- a/packages/font-glyphs/src/letter/latin/lower-m.ptl
345+++ b/packages/font-glyphs/src/letter/latin/lower-m.ptl
346@@ -13,7 +13,7 @@ glyph-block Letter-Latin-Lower-M : begin
347 	glyph-block-import Letter-Shared-Shapes : MidHook CyrDescender CyrCurlDescender PalatalHook EngHook
348 	glyph-block-import Letter-Shared-Shapes : UpwardHookShape SerifFrame
349 
350-	define [dfM] : DivFrame para.advanceScaleMM 3
351+	define [dfM] : if para.koelnCompactM [DivFrame para.advanceScaleMM 3 0.5] [DivFrame para.advanceScaleMM 3 0.2 Stroke]
352 
353 	define [SmallMSmoothA df _ad _sw] : [df.slice 3 2].archDepthAOf [fallback _ad SmallArchDepth] [fallback _sw df.mvs]
354 	define [SmallMSmoothB df _ad _sw] : [df.slice 3 2].archDepthBOf [fallback _ad SmallArchDepth] [fallback _sw df.mvs]
355@@ -122,9 +122,9 @@ glyph-block Letter-Latin-Lower-M : begin
356 	glyph-block-export SmallMArches
357 	define [SmallMArches df top lbot mbot rbot _sw _ada _adb] : glyph-proc
358 		local sw   : fallback _sw df.mvs
359-		local fine : sw * (ShoulderFine / Stroke)
360-		local ada  : fallback _ada : SmallMSmoothA df nothing sw
361-		local adb  : fallback _adb : SmallMSmoothB df nothing sw
362+		local fine : sw * 0.9
363+		local ada : fallback _ada : (df.rightSB - df.leftSB + [HSwToV sw]) / 4
364+		local adb : fallback _adb ada
365 		include : tagged 'barL' : VBar.l df.leftSB lbot top sw
366 		include : SmallMShoulderSpiro
367 			left      -- (df.leftSB + [HSwToV : sw - fine])
368diff --git a/packages/font-glyphs/src/letter/latin/lower-n.ptl b/packages/font-glyphs/src/letter/latin/lower-n.ptl
369index 2da55d3..a79108a 100644
370--- a/packages/font-glyphs/src/letter/latin/lower-n.ptl
371+++ b/packages/font-glyphs/src/letter/latin/lower-n.ptl
372@@ -1,5 +1,7 @@
373 $$include '../../meta/macros.ptl'
374 
375+import [shoulder lowerWidth] from "../../../iocgn-shapes.mjs"
376+
377 import [mix clamp fallback SuffixCfg] from "@iosevka/util"
378 import [MathSansSerif Joining] from "@iosevka/glyph/relation"
379 
380@@ -147,8 +149,9 @@ glyph-block Letter-Latin-Lower-N : begin
381 	foreach { suffix { Body tailed { sLT sLB sRB } } } [Object.entries NConfig] : do
382 		create-glyph "n.\(suffix)" : glyph-proc
383 			include : MarkSet.e
384-			set-base-anchor 'trailing' RightSB 0
385-			include : Body XH SB RightSB [if tailed (XH - SmallArchDepthB + O) 0] Stroke
386+			local fitted : Body == EaredBody && !tailed && !sLT && !sLB && !sRB
387+			set-base-anchor 'trailing' [if fitted (Middle + [lowerWidth Width [HSwToV Stroke]] / 2) RightSB] 0
388+			include : if fitted [shoulder Middle Width XH XH [HSwToV Stroke]] [Body XH SB RightSB [if tailed (XH - SmallArchDepthB + O) 0] Stroke]
389 			if tailed : include : EndingTail RightSB 0 (XH - SmallArchDepthB) Stroke
390 			if sLT : include : sLT [DivFrame 1] XH
391 			if sLB : include : sLB [DivFrame 1] 0
392diff --git a/packages/font-glyphs/src/letter/latin/lower-p.ptl b/packages/font-glyphs/src/letter/latin/lower-p.ptl
393index ed5c56b..e4b230a 100644
394--- a/packages/font-glyphs/src/letter/latin/lower-p.ptl
395+++ b/packages/font-glyphs/src/letter/latin/lower-p.ptl
396@@ -1,5 +1,7 @@
397 $$include '../../meta/macros.ptl'
398 
399+import [lowerBowl lowerWidth] from "../../../iocgn-shapes.mjs"
400+
401 import [mix fallback SuffixCfg] from "@iosevka/util"
402 import [MathSansSerif] from "@iosevka/glyph/relation"
403 
404@@ -70,10 +72,12 @@ glyph-block Letter-Latin-Lower-P : begin
405 
406 		create-glyph "p.\(suffix)" : glyph-proc
407 			include : MarkSet.p
408-			include : Body
409+			local fitted : Body == EaredBody && !doTS && !doBS
410+			local xStem : if fitted (Middle - [lowerWidth Width [HSwToV Stroke]] / 2) SB
411+			include : if fitted [lowerBowl Middle Width XH [HSwToV Stroke] (-1) XH Descender] [Body]
412 			include : Serifs [DivFrame 1] XH
413-			include : LeaningAnchor.Below.VBar.l SB
414-			set-base-anchor 'overlayOnExtension' (SB + [HSwToV HalfStroke]) yOverlay
415+			include : LeaningAnchor.Below.VBar.l xStem
416+			set-base-anchor 'overlayOnExtension' (xStem + [HSwToV HalfStroke]) yOverlay
417 			set-base-anchor 'strike' Middle (XH / 2)
418 
419 		create-glyph "pStrokeBottom.\(suffix)" : glyph-proc
420diff --git a/packages/font-glyphs/src/letter/latin/lower-q.ptl b/packages/font-glyphs/src/letter/latin/lower-q.ptl
421index a1c364b..3204893 100644
422--- a/packages/font-glyphs/src/letter/latin/lower-q.ptl
423+++ b/packages/font-glyphs/src/letter/latin/lower-q.ptl
424@@ -1,5 +1,7 @@
425 $$include '../../meta/macros.ptl'
426 
427+import [lowerBowl lowerWidth] from "../../../iocgn-shapes.mjs"
428+
429 import [mix fallback SuffixCfg] from "@iosevka/util"
430 import [MathSansSerif] from "@iosevka/glyph/relation"
431 
432@@ -104,10 +106,12 @@ glyph-block Letter-Latin-Lower-Q : begin
433 	foreach { suffix { Body terminal { sRT sRB } } } [Object.entries QConfig] : do
434 		create-glyph "q.\(suffix)" : glyph-proc
435 			include : MarkSet.p
436-			include : Body terminal XH Descender
437+			local fitted : Body == EaredBody && terminal == TERMINAL-NORMAL && !sRT && !sRB
438+			local xStem : if fitted (Middle + [lowerWidth Width [HSwToV Stroke]] / 2) RightSB
439+			include : if fitted [lowerBowl Middle Width XH [HSwToV Stroke] 1 XH Descender] [Body terminal XH Descender]
440 			if sRT : include : sRT XH
441 			if sRB : include : sRB Descender
442-			include : LeaningAnchor.Below.VBar.r RightSB
443+			include : LeaningAnchor.Below.VBar.r xStem
444 
445 		if (terminal === TERMINAL-NORMAL && !sRB) : begin
446 			create-glyph "qCapRTail.\(suffix)" : glyph-proc
447diff --git a/packages/font-glyphs/src/letter/latin/lower-r.ptl b/packages/font-glyphs/src/letter/latin/lower-r.ptl
448index 0db7ab7..2a6243f 100644
449--- a/packages/font-glyphs/src/letter/latin/lower-r.ptl
450+++ b/packages/font-glyphs/src/letter/latin/lower-r.ptl
451@@ -2,6 +2,7 @@ $$include '../../meta/macros.ptl'
452 
453 import [mix linreg clamp fallback SuffixCfg] from "@iosevka/util"
454 import [MathSansSerif] from "@iosevka/glyph/relation"
455+import [roundHook shoulder] from "../../../iocgn-shapes.mjs"
456 
457 glyph-module
458 
459@@ -55,8 +56,8 @@ glyph-block Letter-Latin-Lower-R : begin
460 
461 		export : local [rTopSerif y] : tagged 'serifLT'
462 			HSerif.lt rSerifX y (rSerifLeftJut + [HSwToV : 0.5 * strokeBar])
463-		export : local fine ShoulderFine
464-		local rHookXFull : df.rightSB + RBalance2 * rBalanceMultiplier - (OX - O)
465+		export : local fine : stroke * 0.9
466+		local rHookXFull : xBar - [HSwToV strokeBar] + (200 + 1.12 * [HSwToV strokeBar]) * df.width / 660
467 		local pAdaptive : if (para.advanceScaleF < 1) ((1 - df.adws) / (1 - para.advanceScaleF)) 0
468 		export : local rHookX : match mode
469 			([Just rNarrowHook] || [Just rNarrowHookSerifed]) : mix xBar rHookXFull [mix 0.85 1.15 pAdaptive]
470@@ -105,14 +106,10 @@ glyph-block Letter-Latin-Lower-R : begin
471 
472 	define [StandardShape df md doTopSerif doBottomSerif] : glyph-proc
473 		define [object xBar rBottomSerif rTopSerif fine xArchMiddle skew rHookX rHookY hookSuperness] : RDim df md
474-		include : dispiro
475-			widths.lhs
476-			g4.up.start rHookX (XH - rHookY) [heading Upward]
477-			arcvh 32 hookSuperness
478-			g4.left.mid (xArchMiddle - CorrectionOMidS * [linreg 72 0.75 108 1 Stroke]) (XH - O) [widths.lhs.heading Stroke {.y (-1) .x (-skew)}]
479-			archv 32
480-			straight.down.end (xBar - [HSwToV fine]) (XH * 0.53 + TanSlope * SmoothAdjust) [widths.lhs.heading fine Downward]
481-		include : VBar.r xBar 0 XH
482+		include : if (!doTopSerif && !doBottomSerif) [shoulder df.middle df.width XH XH [HSwToV Stroke] true] : glyph-proc
483+			local radius : (rHookX - xBar + [HSwToV Stroke]) / (1 + [Math.sin : Math.PI / 9])
484+			include : roundHook (0 - xBar + [HSwToV Stroke]) 0 (O - XH) radius [HSwToV Stroke] 110 true
485+			include : VBar.r xBar 0 XH
486 		if doBottomSerif : include : rBottomSerif 0
487 		if doTopSerif    : include : rTopSerif    XH
488 
489diff --git a/packages/font-glyphs/src/letter/latin/lower-t.ptl b/packages/font-glyphs/src/letter/latin/lower-t.ptl
490index 71ecb6c..2d4f57f 100644
491--- a/packages/font-glyphs/src/letter/latin/lower-t.ptl
492+++ b/packages/font-glyphs/src/letter/latin/lower-t.ptl
493@@ -33,14 +33,15 @@ glyph-block Letter-Latin-Lower-T : begin
494 	define yShortNeck2 : clamp [mix XH Ascender 0.5] CAP : [mix XH Ascender 0.750] - Stroke * 0.125
495 
496 	define BentHook : namespace
497+		define crossJut : (132 + 0.5 * Stroke) * Width / 660
498 		export : define [BarLeftPos df sym] : match sym
499 			[Just SYM-LEFT]        : mix df.leftSB [xSmallTBarLeftT df] 0.5
500 			[Just SYM-BALANCED]    : xSmallTBarLeftT df
501 			([Just SYM-PR-LEFT] || [Just SYM-PR-BALANCED]) : df.middle - [HSwToV HalfStroke]
502 
503 		define [xCrossBarPos df sym] : match sym
504-			([Just SYM-LEFT] || [Just SYM-PR-LEFT]) {([BarLeftPos df sym] + TanSlope * Stroke) ([xSmallTCrossRefT df] + LongJut * [Math.sqrt df.adws])}
505-			__                        {([xSmallTCrossRefT df] - LongJut * [Math.sqrt df.adws]) ([xSmallTCrossRefT df] + LongJut * [Math.sqrt df.adws])}
506+			([Just SYM-LEFT] || [Just SYM-PR-LEFT]) {([BarLeftPos df sym] + TanSlope * Stroke) ([xSmallTCrossRefT df] + crossJut * [Math.sqrt df.adws])}
507+			__                        {([xSmallTCrossRefT df] - crossJut * [Math.sqrt df.adws]) ([xSmallTCrossRefT df] + crossJut * [Math.sqrt df.adws])}
508 
509 		define [XHookTerminal df sym] : match sym
510 			[Just SYM-LEFT]        df.rightSB
511@@ -57,7 +58,8 @@ glyph-block Letter-Latin-Lower-T : begin
512 				[if (sink == spiro-outline) corner flat] (offset + xLeft) top [heading Downward]
513 				curl (offset + xLeft) (bot + adb)
514 				HookEnd (bot + offset) (sw -- sw)
515-				g4 (xHook - offset) (bot + Hook)
516+				flat (xHook - offset) (bot + (xHook - xLeft) / 2)
517+				curl (xHook - offset) (bot + (xHook - xLeft) / 2 + sw * 0.35) [heading Upward]
518 				if (sink == spiro-outline) {[corner (xHook - offset) top]} {}
519 
520 		export : define [CrossBar df sym] : begin
521diff --git a/packages/font-glyphs/src/letter/latin/lower-y.ptl b/packages/font-glyphs/src/letter/latin/lower-y.ptl
522index ee5050d..89aa6b5 100644
523--- a/packages/font-glyphs/src/letter/latin/lower-y.ptl
524+++ b/packages/font-glyphs/src/letter/latin/lower-y.ptl
525@@ -37,7 +37,7 @@ glyph-block Letter-Latin-Lower-Y : begin
526 		local l : fallback _l 0
527 		local r : fallback _r Width
528 		local m : mix l r 0.5
529-		local sb : fallback _sb SB
530+		local sb : fallback _sb (SB + Width * 0.065)
531 		local rsb : r + l - sb
532 		local sw : fallback _sw Stroke
533 
534@@ -319,7 +319,7 @@ glyph-block Letter-Latin-Lower-Y : begin
535 			include : MarkSet.p
536 			set-base-anchor 'strike' Middle (XH / 2)
537 			set-base-anchor 'yBelowDot' (RightSB - 0.5 * DotRadius) (Descender + AccentStackOffset + DotRadius)
538-			include : Shapes.SmallYShape XH Descender
539+			include : Shapes.SmallYShape XH (Descender * 0.8)
540 
541 		create-glyph "grek/lambda.\(suffix)" : glyph-proc
542 			include : MarkSet.b
543diff --git a/packages/font-glyphs/src/letter/latin/o.ptl b/packages/font-glyphs/src/letter/latin/o.ptl
544index 5a8a304..6bf535b 100644
545--- a/packages/font-glyphs/src/letter/latin/o.ptl
546+++ b/packages/font-glyphs/src/letter/latin/o.ptl
547@@ -1,5 +1,7 @@
548 $$include '../../meta/macros.ptl'
549 
550+import [lowerBowl] from "../../../iocgn-shapes.mjs"
551+
552 import [mix linreg clamp fallback] from "@iosevka/util"
553 
554 
555@@ -25,7 +27,7 @@ glyph-block Letter-Latin-O : begin
556 
557 	create-glyph 'o' 'o' : glyph-proc
558 		include : MarkSet.e
559-		include : OShape XH 0 SB RightSB nothing nothing nothing
560+		include : lowerBowl Middle Width XH [HSwToV Stroke]
561 
562 	create-glyph 'grek/Omicron' 0x39F : glyph-proc
563 		include [refer-glyph 'O'] AS_BASE ALSO_METRICS
564diff --git a/packages/font-glyphs/src/letter/latin/u.ptl b/packages/font-glyphs/src/letter/latin/u.ptl
565index 040acdb..6c0bfe6 100644
566--- a/packages/font-glyphs/src/letter/latin/u.ptl
567+++ b/packages/font-glyphs/src/letter/latin/u.ptl
568@@ -1,5 +1,7 @@
569 $$include '../../meta/macros.ptl'
570 
571+import [shoulder] from "../../../iocgn-shapes.mjs"
572+
573 import [mix fallback SuffixCfg] from "@iosevka/util"
574 import [MathSansSerif] from "@iosevka/glyph/relation"
575 
576@@ -195,7 +197,11 @@ glyph-block Letter-Latin-U : begin
577 		create-glyph "u.\(suffix)" : glyph-proc
578 			local df : include : DivFrame 1
579 			include : df.markSet.e
580-			include : Base  df XH Stroke
581+			include : if (Base == ULower.Toothed && Slabs == no-shape)
582+				glyph-proc
583+					include : shoulder Middle Width XH XH [HSwToV Stroke]
584+					include : FlipAround Middle (XH / 2)
585+				Base df XH Stroke
586 			include : Slabs df XH Stroke
587 
588 		create-glyph "grek/mu.\(suffix)" : glyph-proc
589diff --git a/packages/font-glyphs/src/letter/latin/upper-a.ptl b/packages/font-glyphs/src/letter/latin/upper-a.ptl
590index a808d85..8bca453 100644
591--- a/packages/font-glyphs/src/letter/latin/upper-a.ptl
592+++ b/packages/font-glyphs/src/letter/latin/upper-a.ptl
593@@ -51,9 +51,33 @@ glyph-block Letter-Latin-Upper-A : begin
594 			return : tagged 'crossBar' : intersection [HBar.t 0 df.width yBar sw] [Mask df bodyShape top sw]
595 
596 		export : define [Letter df bodyShape slabKind top sw] : new-glyph : glyph-proc
597-			include : Outer df bodyShape top sw
598-			include : CrossBar df bodyShape top sw
599-			include : ASerifs df top sw slabKind
600+			if (bodyShape == BODY-STRAIGHT && slabKind == SLAB-NONE) : begin
601+				# Flat roof and vertical lower legs, rather than an inverted V.
602+				local w : df.rightSB - df.leftSB
603+				local knee : top * 0.39
604+				local yBar : top * 0.455
605+				local roofHalf : w * 0.20 + [Math.max 0 (sw - 105)] * 1.4
606+				local counterHalf : w * 0.03 + [Math.max 0 (75 - sw)] * 0.9
607+				include : difference
608+					spiro-outline
609+						corner df.leftSB 0
610+						corner df.leftSB knee
611+						corner (df.middle - roofHalf) top
612+						corner (df.middle + roofHalf) top
613+						corner df.rightSB knee
614+						corner df.rightSB 0
615+					spiro-outline
616+						corner (df.leftSB + sw) 0
617+						corner (df.leftSB + sw) knee
618+						corner (df.middle - counterHalf) (top - sw)
619+						corner (df.middle + counterHalf) (top - sw)
620+						corner (df.rightSB - sw) knee
621+						corner (df.rightSB - sw) 0
622+				include : tagged 'crossBar' : HBar.t (df.leftSB + sw) (df.rightSB - sw) yBar sw
623+			: else : begin
624+				include : Outer df bodyShape top sw
625+				include : CrossBar df bodyShape top sw
626+				include : ASerifs df top sw slabKind
627 
628 		define [CuspBottomRightRemovedImpl df bodyShape slabKind top sw] : new-glyph : glyph-proc
629 			local yBar : BarPos bodyShape slabKind top
630diff --git a/packages/font-glyphs/src/letter/latin/upper-n.ptl b/packages/font-glyphs/src/letter/latin/upper-n.ptl
631index 2bb63b9..730ad82 100644
632--- a/packages/font-glyphs/src/letter/latin/upper-n.ptl
633+++ b/packages/font-glyphs/src/letter/latin/upper-n.ptl
634@@ -149,6 +149,8 @@ glyph-block Letter-Latin-Upper-N : begin
635 		create-glyph "N.\(suffix)" : glyph-proc
636 			include : MarkSet.capital
637 			include : NShape [DivFrame 1] CAP bodyType slabType
638+				# Wider ink, unchanged cell advance and stem weight.
639+				kSB    -- ((Width - [Math.min 472.35 (339 + 1.27 * Stroke)] * Width / 660) / (2 * SB))
640 				swDiag -- [AdviceStroke crDiag]
641 			set-base-anchor 'trailing' (RightSB - markHalfStroke) 0
642 
643diff --git a/packages/font-glyphs/src/letter/latin/upper-p.ptl b/packages/font-glyphs/src/letter/latin/upper-p.ptl
644index 83e04e6..f428b96 100644
645--- a/packages/font-glyphs/src/letter/latin/upper-p.ptl
646+++ b/packages/font-glyphs/src/letter/latin/upper-p.ptl
647@@ -36,17 +36,15 @@ glyph-block Letter-Latin-Upper-P : begin
648 	define [PShapeOutlineKnots top df mul bp overshoot sw offset] : begin
649 		local bowlTop : top - offset
650 		local bowlBottom : [PBarPosY top sw bp] + offset
651-		local turnRadius : BowlXDepth bowlTop bowlBottom df.leftSB df.rightSB sw
652-		local ada : ArchDepthAOf (ArchDepth * 0.9) df.width
653-		local adb : ArchDepthBOf (ArchDepth * 0.9) df.width
654 		local left : mix 0 df.leftSB mul
655-		local right : df.rightSB - offset
656-		local turn : YSmoothMidR bowlTop bowlBottom ada adb
657+		local right : left + (df.rightSB - df.leftSB) * 0.93 - offset
658+		# Quarter-turns separated by a real vertical, not one continuous oval.
659+		local turnRadius : Math.min ((bowlTop - bowlBottom) * 0.36) ((right - left) / 2)
660 		return : list
661 			flat (left - O) bowlTop [heading Rightward]
662 			curl [Arch.adjust-x.top (right - turnRadius) (sw -- sw)] bowlTop
663 			archv
664-			g4 (right - overshoot) turn
665+			flatside.rd right bowlBottom bowlTop turnRadius turnRadius 0
666 			arcvh
667 			flat [Arch.adjust-x.bot (right - turnRadius) (sw -- sw)] bowlBottom
668 			curl (left - O) bowlBottom [heading Leftward]
669@@ -133,7 +131,7 @@ glyph-block Letter-Latin-Upper-P : begin
670 
671 	set PShape.defaultMul 1.25
672 	set PShape.defaultOvershoot : OX * 2
673-	set PShape.BarPos : 1 - HBarPos
674+	set PShape.BarPos 0.40
675 	set PShape.SwBelowBar 0.25
676 
677 	set PShape.SlabMotion : function [top df sw mul] : glyph-proc
678diff --git a/packages/font-glyphs/src/letter/latin/upper-q.ptl b/packages/font-glyphs/src/letter/latin/upper-q.ptl
679index 114ea5a..cd7028f 100644
680--- a/packages/font-glyphs/src/letter/latin/upper-q.ptl
681+++ b/packages/font-glyphs/src/letter/latin/upper-q.ptl
682@@ -110,13 +110,20 @@ glyph-block Letter-Latin-Upper-Q : begin
683 
684 	glyph-block-export QCrossing
685 	define [QCrossing df top sw] : begin
686-		define k 1.5
687-		define cor : DiagCor (k * (df.rightSB - df.middle)) (df.rightSB - df.middle - OX)
688-		define shift : XH * (-0.1)
689-		return : dispiro
690-			widths.center (cor * sw)
691-			flat df.rightSB shift [heading Upward]
692-			curl (df.middle + OX) (k * (df.rightSB - df.middle) + shift) [heading Upward]
693+		# Short, near-45-degree tail with perpendicular end cuts.
694+		local tailSw : mix sw Stroke 0.75
695+		local x0 : df.middle + 0.01 * (df.rightSB - df.leftSB)
696+		local y0 : top * 0.29
697+		local x1 : df.rightSB - tailSw * 0.20
698+		local y1 : top * 0.01
699+		local length : Math.hypot (x1 - x0) (y1 - y0)
700+		local nx : (y0 - y1) * tailSw / (2 * length)
701+		local ny : (x1 - x0) * tailSw / (2 * length)
702+		return : spiro-outline
703+			corner (x0 + nx) (y0 + ny)
704+			corner (x1 + nx) (y1 + ny)
705+			corner (x1 - nx) (y1 - ny)
706+			corner (x0 - nx) (y0 - ny)
707 
708 	define [QCrossingBaseline df top sw] : begin
709 		define cor : DiagCor (0.5 * (top - Stroke)) (df.rightSB - df.middle - OX)
710diff --git a/packages/font-glyphs/src/letter/latin/upper-r.ptl b/packages/font-glyphs/src/letter/latin/upper-r.ptl
711index 7bde844..433fb24 100644
712--- a/packages/font-glyphs/src/letter/latin/upper-r.ptl
713+++ b/packages/font-glyphs/src/letter/latin/upper-r.ptl
714@@ -110,7 +110,7 @@ glyph-block Letter-Latin-Upper-R : begin
715 		local-parameter : legBottom -- 0
716 
717 		local fSlabBot : slab && slab !== PShape.SlabMotion
718-		local right : df.rightSB - O - [if slab 0.125 0] * Jut
719+		local right : [mix 0 df.leftSB mul] + (df.rightSB - df.leftSB) * 0.95 - [if slab 0.125 0] * Jut
720 		include : difference
721 			PShape top (df -- df) (mul -- mul) (overshoot -- O) (slab -- slab) (bp -- bp) (sw -- sw)
722 			if open
723diff --git a/packages/font-glyphs/src/letter/latin/w.ptl b/packages/font-glyphs/src/letter/latin/w.ptl
724index 40597f0..385c6ed 100644
725--- a/packages/font-glyphs/src/letter/latin/w.ptl
726+++ b/packages/font-glyphs/src/letter/latin/w.ptl
727@@ -292,13 +292,27 @@ glyph-block Letter-Latin-W : begin
728 		eject-contour 'strokeUp2'
729 
730 	define [WVertSides df top bodyType slabType midHClass] : glyph-proc
731-		local wMidHeight : WMidHeight df top bodyType midHClass
732-		local wMidHeightExt : WMidHeightExt wMidHeight top bodyType midHClass
733-
734-		include : new-glyph : glyph-proc
735-			include : MShape top df (form -- 2) (slabType -- 0) (middleYExt -- (top - wMidHeightExt))
736-			include : FlipAround (df.width / 2) (top / 2)
737-
738+		local sw : HSwToV Stroke
739+		local span : [if (top > XH) (496 + 1.06 * sw) [Math.min 578 (386 + 1.71 * sw)]] * df.width / 660
740+		local left : df.middle - span / 2
741+		local right : df.middle + span / 2
742+		local lean : span * 0.07
743+		local roof : top * 0.68
744+		# Flat central roof and feet; outer strokes lean slightly inward.
745+		include : spiro-outline
746+			corner left top
747+			corner (left + lean) 0
748+			corner (left + lean + 1.25 * sw) 0
749+			corner df.middle (roof - 1.15 * sw)
750+			corner (right - lean - 1.25 * sw) 0
751+			corner (right - lean) 0
752+			corner right top
753+			corner (right - sw) top
754+			corner (right - lean - 0.75 * sw) (0.75 * sw)
755+			corner (df.middle + sw / 2) roof
756+			corner (df.middle - sw / 2) roof
757+			corner (left + lean + 0.75 * sw) (0.75 * sw)
758+			corner (left + sw) top
759 		include : WSerifs df top bodyType slabType
760 
761 	define [WVSHookRightShape df top bodyType slabType midHClass] : glyph-proc
762diff --git a/packages/font-glyphs/src/letter/shared.ptl b/packages/font-glyphs/src/letter/shared.ptl
763index 1bedc6e..706f248 100644
764--- a/packages/font-glyphs/src/letter/shared.ptl
765+++ b/packages/font-glyphs/src/letter/shared.ptl
766@@ -429,6 +429,8 @@ glyph-block Letter-Shared-Shapes : begin
767 			local-parameter : ada               -- SmallArchDepthA
768 			local-parameter : adb               -- SmallArchDepthB
769 
770+			# Keep attached bowls nearly monolinear at their stem junctions.
771+			set fine : mix fine sw 0.90
772 			return : dispiro
773 				widths.lhs fine
774 				flatside.ld (left + [HSwToV : sw - fine]) bot top ada adb 0
775diff --git a/packages/font-glyphs/src/meta/aesthetics.ptl b/packages/font-glyphs/src/meta/aesthetics.ptl
776index 8397bf6..078716d 100644
777--- a/packages/font-glyphs/src/meta/aesthetics.ptl
778+++ b/packages/font-glyphs/src/meta/aesthetics.ptl
779@@ -255,11 +255,11 @@ export : define [setFontMetrics para metrics fm] : begin
780 	set fm.os2.sxHeight           XH
781 	set fm.os2.sCapHeight         CAP
782 
783-	local slope : Math.tan para.slopeAngle
784-	set fm.post.italicAngle       : Math.round (0 - para.slopeAngle)
785-	set fm.hhea.caretSlopeRise    : if para.slopeAngle (1000)                      1
786-	set fm.hhea.caretSlopeRun     : if para.slopeAngle ((-slope) * 1000)           0
787-	set fm.hhea.caretOffset       : if para.slopeAngle ((-slope) * para.symbolMid) 0
788+	local slope : Math.tan : para.slopeAngle / 180 * Math.PI
789+	set fm.post.italicAngle       : 0 - para.slopeAngle
790+	set fm.hhea.caretSlopeRise    : if para.slopeAngle 1000 1
791+	set fm.hhea.caretSlopeRun     : Math.round : slope * 1000
792+	set fm.hhea.caretOffset       : Math.round : (-slope) * para.symbolMid
793 
794 	# Fixed metrics
795 	set fm.os2.yStrikeoutPosition    para."os2.yStrikeoutPosition"
796diff --git a/packages/font-glyphs/src/number/0.ptl b/packages/font-glyphs/src/number/0.ptl
797index 7b46d70..6b083df 100644
798--- a/packages/font-glyphs/src/number/0.ptl
799+++ b/packages/font-glyphs/src/number/0.ptl
800@@ -47,8 +47,8 @@ glyph-block Digits-Zero : begin
801 		curl Width (top * (1 - 0.77))
802 
803 	define [ZeroTallSlash top] : dispiro
804-		flat 0     0   [widths.center OverlayStroke]
805-		curl Width top
806+		flat ((Width - top * 0.419) / 2) 0   [widths.center OverlayStroke]
807+		curl ((Width + top * 0.419) / 2) top
808 	define [ZeroTallRevSlash top] : dispiro
809 		flat 0     top [widths.center OverlayStroke]
810 		curl Width 0
811diff --git a/packages/font-glyphs/src/number/4.ptl b/packages/font-glyphs/src/number/4.ptl
812index aae08cc..a8a7486 100644
813--- a/packages/font-glyphs/src/number/4.ptl
814+++ b/packages/font-glyphs/src/number/4.ptl
815@@ -54,15 +54,15 @@ glyph-block Digits-Four : begin
816 		return : FourStdShape top true crossing (fine -- [AdviceStroke 2.75]) (slab -- slab)
817 
818 	define [FourOpenShape top crossing slab] : glyph-proc
819-		local yBar : top * 0.4
820-		local fine : AdviceStroke 3
821-
822-		define xVertBar : mix SB RightSB : if crossing 0.825 0.9125
823-		define xHBarTerminal : if crossing RightSB xVertBar
824-
825-		include : HBar.t SB xHBarTerminal yBar
826-		include : VBar.r xVertBar 0 [mix (yBar - Stroke) top 0.75]
827-		include : VBar.l SB yBar top
828+		local left : SB - 0.06 * (RightSB - SB)
829+		local right : RightSB + 0.06 * (RightSB - SB)
830+		local yBar : top * 0.32
831+		define xVertBar : mix left right : if crossing 0.82 0.91
832+		define xHBarTerminal : if crossing right xVertBar
833+		include : HBar.t left xHBarTerminal yBar
834+		include : VBar.r xVertBar 0 (top * 0.55)
835+		include : intersection [Rect top (yBar - Stroke) left right]
836+			ExtLineCenter (left + Stroke * 0.10) (yBar - Stroke * 0.5) [mix left right 0.65] top Stroke 2
837 		if slab : begin
838 			include : HSerif.rb (xVertBar - [HSwToV HalfStroke]) 0 Jut
839 			include : HSerif.lb (xVertBar - [HSwToV HalfStroke]) 0 MidJutSide
840diff --git a/packages/font-glyphs/src/number/6.ptl b/packages/font-glyphs/src/number/6.ptl
841index 25a2d85..8c30289 100644
842--- a/packages/font-glyphs/src/number/6.ptl
843+++ b/packages/font-glyphs/src/number/6.ptl
844@@ -1,5 +1,7 @@
845 $$include '../meta/macros.ptl'
846 
847+import [sixShape] from "../../iocgn-shapes.mjs"
848+
849 import [mix linreg clamp fallback] from "@iosevka/util"
850 
851 glyph-module
852@@ -26,18 +28,7 @@ glyph-block Digits-Six : begin
853 
854 	glyph-block-export ClosedContourSixShape
855 	define [ClosedContourSixShape top] : glyph-proc
856-		local oTop : Math.max (2 * SmallArchDepth + TINY) (top * 0.55 + HalfStroke)
857-		include : dispiro
858-			widths.rhs ShoulderFine
859-			straight.up.start (SB + OX + [HSwToV (Stroke - ShoulderFine)]) (oTop - SmallArchDepthA)
860-			Arch.rhs oTop (swBefore -- ShoulderFine)
861-			flat (RightSB - OX) (oTop - SmallArchDepthB)
862-			curl (RightSB - OX) SmallArchDepthA
863-			Arch.rhs 0
864-			flat (SB + OX) SmallArchDepthB
865-			curl (SB + OX) (top - SmallArchDepthA)
866-			HookEnd top
867-			g4 (RightSB - OX) (top - Hook)
868+		include : sixShape Middle Width top [HSwToV Stroke]
869 
870 	glyph-block-export StraightBarSixShape
871 	define [StraightBarSixShape] : with-params [charTop [sw Stroke] [bbd 0]] : glyph-proc
872diff --git a/packages/font-otl/src/gsub-locl.ptl b/packages/font-otl/src/gsub-locl.ptl
873index a2a6476..cf53781 100644
874--- a/packages/font-otl/src/gsub-locl.ptl
875+++ b/packages/font-otl/src/gsub-locl.ptl
876@@ -77,7 +77,7 @@ export : define [buildLOCL gsub para glyphStore] : begin
877 	loclNSM.addLookup : gsub.createLookup
878 		.type 'gsub_single'
879 		.substitutions : object
880-			'Eng' : glyphStore.ensureExists 'Eng.NSM'
881+			'Eng' 'Eng.NSM'
882 
883 	# PLK
884 	define loclPLK : latnPLK.addFeature : gsub.createFeature 'locl'
885@@ -90,10 +90,10 @@ export : define [buildLOCL gsub para glyphStore] : begin
886 	loclROM.addLookup : gsub.createLookup
887 		.type 'gsub_single'
888 		.substitutions : object
889-			'SCedilla' : glyphStore.ensureExists 'SComma'
890-			'sCedilla' : glyphStore.ensureExists 'sComma'
891-			'TCedilla' : glyphStore.ensureExists 'TComma'
892-			'tCedilla' : glyphStore.ensureExists 'tComma'
893+			'SCedilla' 'SComma'
894+			'sCedilla' 'sComma'
895+			'TCedilla' 'TComma'
896+			'tCedilla' 'tComma'
897 
898 	# TRK
899 	define loclTRK : gsub.createFeature 'locl'
900@@ -130,9 +130,11 @@ export : define [buildLOCL gsub para glyphStore] : begin
901 		foreach ch (viCircumflex + viBreve) : begin
902 			local u : ch.codePointAt 0
903 			local gn : glyphStore.queryNameByUnicode u
904-			local g : glyphStore.queryByNameEnsured gn
905-			local decomp : CvDecompose.get g
906-			set decompositionSubstitutions.(gn) decomp
907+			# The iocgn store omits Vietnamese letters.
908+			if gn : begin
909+				local g : glyphStore.queryByNameEnsured gn
910+				local decomp : CvDecompose.get g
911+				set decompositionSubstitutions.(gn) decomp
912 
913 		loclVIT.addLookup : gsub.createLookup
914 			.type 'gsub_chaining'
915diff --git a/packages/font/src/cleanup/glyphs.mjs b/packages/font/src/cleanup/glyphs.mjs
916index 902b3ea..9d7ad7e 100644
917--- a/packages/font/src/cleanup/glyphs.mjs
918+++ b/packages/font/src/cleanup/glyphs.mjs
919@@ -28,6 +28,8 @@ function regulateGlyphStore(cache, para, skew, glyphStore) {
920 function flattenSimpleGlyph(cache, para, _skew, g) {
921 	try {
922 		if (!g.gizmo) throw new TypeError("No gizmo");
923+		// iocgn-native has already simplified, rounded and placed these outlines.
924+		if (g.koelnFinal) return g.geometry.toContours();
925 		const gSimplified = Geom.SimplifyGeometry.wrapWithGizmo(g.geometry, g.gizmo);
926 		return gSimplified.toContours({ cache });
927 	} catch (e) {
928diff --git a/packages/param/src/metric-override.mjs b/packages/param/src/metric-override.mjs
929index ddcb431..7ea406a 100644
930--- a/packages/param/src/metric-override.mjs
931+++ b/packages/param/src/metric-override.mjs
932@@ -24,6 +24,10 @@ const validMetricOverrideFields = new Set([
933 	"ascender",
934 	"xHeight",
935 	"sb",
936+	"stroke",
937+	"contrast",
938+	"descender",
939+	"longjut",
940 	"accentWidth",
941 	"accentClearance",
942 	"accentHeight",