$$include '../meta/macros.ptl'

import [mix clamp fallback] from "@iosevka/util"
import [FunctionInterpolator] from "@iosevka/geometry/spiro-control"
import [Dotless CvDecompose] from "@iosevka/glyph/relation"
import [RightDependentTrigger RightDependentLink DependentSelector] from "@iosevka/glyph/relation"
import [DesignParameters] from "../meta/aesthetics.mjs"

glyph-module

glyph-block Letter-Shared : begin
	glyph-block-import CommonShapes
	glyph-block-import Common-Derivatives
	glyph-block-import Mark-Adjustment : TurnMarks LeaningAnchorMap
	glyph-block-import Letter-Accent-Builder : TransformGlyphCompositionSequence

	glyph-block-export CreateAccentedComposition
	define [CreateAccentedComposition dst u srcGid accentGid]
		CreateMultiAccentedComposition dst u srcGid { accentGid }

	glyph-block-export CreateMultiAccentedComposition
	define [CreateMultiAccentedComposition dst u gnSrc gnAccents]
		derive-multi-part-glyphs dst u { gnSrc :: gnAccents } : function [gns gr] : glyph-proc
			local glyphParts : gns.map : function [gn] : query-glyph gn
			TransformGlyphCompositionSequence glyphParts

			include glyphParts.0 AS_BASE ALSO_METRICS
			foreach part [items-of : glyphParts.slice 1] : if part : include part

			if (!gr) : begin
				if (gns.length === 2 && [gns.1.endsWith 'tittleAbove'])
				: then : Dotless.set currentGlyph gns.0
				: else : CvDecompose.set currentGlyph gns

	glyph-block-export CreateCommaCaronComposition
	define [CreateCommaCaronComposition dst u sourceGid offset]
		derive-multi-part-glyphs dst u { sourceGid 'commaTR' } : function [gns gr] : glyph-proc
			local { base comma } gns
			define baseGlyph : query-glyph base
			define commaOffset : fallback offset : (Width / 2) * ((baseGlyph.advanceWidth / Width * 2) ** (2/3))
			include : refer-glyph comma
			include : ApparentTranslate commaOffset 0
			include [refer-glyph base] AS_BASE ALSO_METRICS

	glyph-block-export CreateDependentComposite
	define [CreateDependentComposite gidDst unicode gidPart1 gidPart2Map] : begin
		local sourceGidList { gidPart1 }
		local keyToIndexMap {.}
		foreach { key g } [pairs-of gidPart2Map] : begin
			set keyToIndexMap.(key) sourceGidList.length
			sourceGidList.push g

		derive-multi-part-glyphs gidDst unicode sourceGidList : function [src] : glyph-proc
			local a src.0
			local selector : DependentSelector.get : query-glyph a
			local b src.(keyToIndexMap.(selector))

			include [refer-glyph a] AS_BASE ALSO_METRICS
			include [refer-glyph b]

	glyph-block-export CreateSelectorVariants
	define [CreateSelectorVariants] : with-params [name code selectors [follow name]] : begin
		select-variant "\(name)/selector" (follow -- follow)
		local obj {.}
		foreach item [items-of selectors] : set obj.(item) "\(name).\(item)"
		CreateDependentComposite name code "\(name)/selector" obj

	glyph-block-export DefineSelectorGlyph
	define [DefineSelectorGlyph name selector df mk] : begin
		create-glyph "\(name)/selector.\(selector)" : glyph-proc
			include df
			include : df.markSet.(mk)
			set-base-anchor 'cvDecompose' 0 0
			DependentSelector.set currentGlyph selector

	glyph-block-export SetGrekUpperTonos
	define [SetGrekUpperTonos kern] : glyph-proc
		set-base-anchor 'grekUpperTonos' kern (CAP - 0.75 * AccentStackOffset)

	glyph-block-export CreateTurnedLetter
	define [CreateTurnedLetter dstGid unicode srcGid _cx _cy _df] : begin
		derive-glyphs dstGid unicode srcGid : lambda [src gr] : glyph-proc
			include [refer-glyph src] AS_BASE ALSO_METRICS
			define cx : if (_cx <@ Function) [_cx.call currentGlyph] _cx
			define cy : if (_cy <@ Function) [_cy.call currentGlyph] _cy
			include : FlipAround cx cy
			include : TurnMarks cx cy _df

glyph-block Letter-Blackboard : begin
	glyph-block-import CommonShapes

	glyph-block-export BBS BBD
	define BBS : AdviceStroke 6
	define BBD : clamp (Width / 5.5) (Width / 4) (BBS * 2)

	glyph-block-export BBBarLeft
	define [BBBarLeft] : with-params [x yBot yTop [bbs BBS] [bbd BBD]] : union
		VBar.l x         yBot yTop bbs
		VBar.l (x + bbd) yBot yTop bbs
		HBar.t x (x + bbd) yTop bbs
		HBar.b x (x + bbd) yBot bbs

	glyph-block-export BBBarCenter
	define [BBBarCenter] : with-params [x yBot yTop [bbs BBS] [bbd BBD]] : union
		VBar.m (x - bbd / 2) yBot yTop bbs
		VBar.m (x + bbd / 2) yBot yTop bbs
		HBar.t (x - bbd / 2) (x + bbd / 2) yTop bbs
		HBar.b (x - bbd / 2) (x + bbd / 2) yBot bbs

	glyph-block-export BBBarRight
	define [BBBarRight] : with-params [x yBot yTop [bbs BBS] [bbd BBD]] : union
		VBar.r x         yBot yTop bbs
		VBar.r (x - bbd) yBot yTop bbs
		HBar.t x (x - bbd) yTop bbs
		HBar.b x (x - bbd) yBot bbs

	glyph-block-import Mark-Shared-Metrics : markMiddle
	glyph-block-import Mark-Above : aboveMarkStack
	create-glyph 'mathbb/dotAbove' : glyph-proc
		set-width 0
		set-mark-anchor 'above' markMiddle XH markMiddle aboveMarkStack
		set-base-anchor 'aboveBraceL' markMiddle (XH + AccentStackOffset)
		set-base-anchor 'aboveBraceR' markMiddle (XH + AccentStackOffset)
		include : DotStrokeAt markMiddle (XH + AccentStackOffset) (BBD / 2 + BBS) BBS

glyph-block Letter-Shared-Metrics : begin
	glyph-block-export BowlXDepth
	define [BowlXDepth top bottom left right sw] : begin
		local trShrink : Math.sqrt : (right - left) / (top - bottom)
		return : Math.max
			HSwToV : 1.25 * sw
			trShrink * [Math.min ((top - bottom) * 0.45) ((right - left + [HSwToV sw]) * 0.875)]

glyph-block Letter-Shared-Shapes : begin
	glyph-block-import CommonShapes
	glyph-block-import Common-Derivatives
	glyph-block-import Mark-Adjustment : ExtendAboveBaseAnchors ExtendBelowBaseAnchors

	glyph-block-export RightwardTailedBar
	define [RightwardTailedBar] : with-params [x low high [sw Stroke]] : begin
		local hookDepth : Math.max SideJut [AdviceStroke 8] (SB * 0.625)
		local hookTurn  : Math.max [AdviceStroke 16] (hookDepth - [AdviceStroke 16])
		local overshoot : O * 1
		return : dispiro
			flat (x - [HSwToV sw]) high [widths.lhs.heading sw Downward]
			curl (x - [HSwToV sw]) (low + overshoot + sw + hookTurn) [heading Downward]
			arcvh
			flat (x + hookTurn)  (low + overshoot) [heading Rightward]
			curl (x + hookDepth + sw * TanSlope) (low + overshoot)

	glyph-block-export InvRightwardTailedBar
	define [InvRightwardTailedBar] : with-params [x low high [sw Stroke]] : begin
		local hookDepth : Math.max SideJut [AdviceStroke 8] (SB * 0.625)
		local hookTurn  : Math.max [AdviceStroke 16] (hookDepth - [AdviceStroke 16])
		local overshoot : O * 1
		return : dispiro
			flat (x - [HSwToV sw]) low [widths.rhs.heading sw Upward]
			curl (x - [HSwToV sw]) (high - overshoot - sw - hookTurn) [heading Upward]
			arcvh
			flat (x + hookTurn)  (high - overshoot) [heading Rightward]
			curl (x + hookDepth + sw * TanSlope) (high - overshoot)

	glyph-block-export CurlyTail
	define CurlyTail : namespace
		define [normalBlender before _after args] : begin
			local ltr : args.xOuter > before.x
			local rInner : 0.5 * [Math.abs : args.xOuter - before.x] - [HSwToV args.fine]
			local top : fallback args.yLoopTop : args.bottom + 2 * (args.fine + rInner)
			local yOuter : [if ltr YSmoothMidR YSmoothMidL] top args.bottom

			return : list
				arch.[if ltr "lhs" "rhs"] args.bottom (sw -- args.fine) (swBefore -- args.swBefore)
				g4 args.xOuter yOuter
				if args.flat
				: then : list
					flat [arch.adjust-x.top : mix args.xOuter before.x 0.5] top
					curl args.x2 top
				: else : begin
					local terminalDeltaY 0.01
					local terminalDeltaX : terminalDeltaY * args.terminalSlopeAdj * ([mix before.x args.xOuter 0.5] - args.x2) / (top - args.y2)
					list
						arch.[if ltr "lhs" "rhs"] top (sw -- args.fine)
							mockPost  -- {.x [mix args.x2 args.xOuter 0.33] .y args.bottom}
							blendPost -- {}
						g2 (args.x2 + terminalDeltaX) (args.y2 + terminalDeltaY)
						g2 args.x2 args.y2

		export : define flex-params [n] : begin
			local-parameter : fine
			local-parameter : bottom
			local-parameter : xOuter
			local-parameter : x2
			local-parameter : y2
			local-parameter : yLoopTop
			local-parameter : swBefore             -- Stroke
			local-parameter : terminalSlopeAdj     -- 0.5

			return : new FunctionInterpolator normalBlender
				object [flat false] fine bottom xOuter x2 y2 yLoopTop swBefore terminalSlopeAdj

		export : define flex-params [f] : begin
			local-parameter : fine
			local-parameter : bottom
			local-parameter : xOuter
			local-parameter : x2
			local-parameter : yLoopTop
			local-parameter : swBefore             -- Stroke
			local-parameter : terminalSlopeAdj     -- 0.5

			return : new FunctionInterpolator normalBlender
				object [flat true] fine bottom xOuter x2 yLoopTop swBefore terminalSlopeAdj

	glyph-block-export HCurlyTail
	define [HCurlyTail fine wide rinner left m1 _right x1 x2 y2] : glyph-proc
		local right : _right - fine
		local mid : right - rinner + O
		include : dispiro
			widths.rhs wide
			flat left wide [heading Rightward]
			curl m1 wide [heading Rightward]
			archv 8
			g4   right (wide + rinner - O / 2) [widths.heading 0 fine {.x (-HVContrast) .y ((wide - fine) / (wide + rinner * 2 - O))}]
			arcvh 8
			g4.left.mid   mid (wide + rinner * 2 - O) [heading Leftward]
			quadControls ((x1 - mid) / (x2 - mid)) 0 8
			g4   x2 y2

	glyph-block-export nShoulder
	define nShoulder : namespace
		export : define flex-params [knots] : begin
			local-parameter : left
			local-parameter : right
			local-parameter : fine              -- ShoulderFine
			local-parameter : top               -- XH
			local-parameter : bottom            -- 0
			local-parameter : ada               -- SmallArchDepthA
			local-parameter : adb               -- SmallArchDepthB
			local-parameter : stroke            -- Stroke
			local-parameter : fMask             -- false
			local-parameter : leftY0            -- (top - ada - TINY)

			return : list
				flat (left - [HSwToV fine]) leftY0 [widths.rhs fine]
				curl (left - [HSwToV fine]) (top - ada)
				arch.rhs top (sw -- stroke) (swBefore -- fine)
				flat right (top - adb) [widths.rhs stroke]
				[if fMask corner curl] right bottom [widths.rhs.heading stroke Downward]
				if [not fMask] {} {[corner left bottom]}

		export : define [shape] : begin
			local a : Array.prototype.slice.call arguments 0
			glyph-proc
				include : dispiro : knots.apply null a

		export : define [mask] : begin
			local a : Array.prototype.slice.call arguments 0
			glyph-proc
				include : spiro-outline : knots.apply null [a.concat { (fMask -- true) }]

	glyph-block-export uBowl
	define uBowl : namespace
		export : define flex-params [knots] : begin
			local-parameter : left
			local-parameter : right
			local-parameter : fine              -- ShoulderFine
			local-parameter : top               -- XH
			local-parameter : bottom            -- 0
			local-parameter : ada               -- SmallArchDepthA
			local-parameter : adb               -- SmallArchDepthB
			local-parameter : stroke            -- Stroke
			local-parameter : fMask             -- false
			local-parameter : rightY0           -- (bottom + ada + TINY)

			return : list
				flat (right + [HSwToV fine]) rightY0 [widths.rhs fine]
				curl (right + [HSwToV fine]) (bottom + ada)
				arch.rhs bottom (sw -- stroke) (swBefore -- fine)
				flat left (bottom + adb) [widths.rhs stroke]
				[if fMask corner curl] left top [widths.rhs.heading stroke Upward]
				if fMask {[corner right top]} {}
		export : define [shape] : begin
			local a : Array.prototype.slice.call arguments 0
			glyph-proc
				include : dispiro : knots.apply null a
		export : define [mask] : begin
			local a : Array.prototype.slice.call arguments 0
			glyph-proc
				include : spiro-outline : knots.apply null [a.concat { (fMask -- true) }]

	glyph-block-export cheBowl
	define cheBowl : namespace
		export : define flex-params [shape] : begin
			local-parameter : left
			local-parameter : right
			local-parameter : top
			local-parameter : bottom
			local-parameter : adb       -- ArchDepthB
			local-parameter : sw        -- Stroke
			local-parameter : fine      -- sw

			define xMid : mix left right 0.5
			define rise   DToothlessRise

			return : dispiro
				flat left top [widths.lhs.heading sw Downward]
				curl left (bottom + adb)
				arch.lhs.centerAt.ltr.b (xMid + [HSwToV : 0.2 * sw]) bottom
				g4 right (bottom + rise + 0.25 * sw) [widths.lhs fine]

	glyph-block-export : OBarLeft
	define OBarLeft : namespace
		define kSkewShift 0.5
		export : define [arcStart] : with-params [
				[top XH] [left SB] [right RightSB] [sw Stroke] [fine ShoulderFine]
				[ada SmallArchDepthA] [adb SmallArchDepthB]
				[ystart (top - ada - TINY)]
			] : begin
			local xstart : left + [HSwToV : sw - fine]
			return : list
				flat xstart ystart [widths.rhs fine]
				curl xstart (top - ada)
				arch.rhs top (sw -- sw) (swBefore -- fine)

		export : define [arcEnd] : with-params [
				[bot 0] [left SB] [right RightSB] [sw Stroke] [fine ShoulderFine]
				[ada SmallArchDepthA] [adb SmallArchDepthB]
				[yend (bot + ada + TINY)]
			] : begin
			local xend : left + [HSwToV : sw - fine]
			return : list
				arch.rhs bot (sw -- sw) (swAfter -- fine)
				flat xend (bot + adb) [widths.rhs fine]
				curl xend yend

		export : define [shape] : with-params [
				[top XH] [bot 0] [left SB] [right RightSB] [sw Stroke] [fine ShoulderFine]
				[ada SmallArchDepthA] [adb SmallArchDepthB]
			] : begin
			return : dispiro
				widths.lhs fine
				flatside.ld (left + [HSwToV : sw - fine]) bot top ada adb 0
				arch.lhs bot (sw -- sw) (swBefore -- fine)
				flatside.ru right bot top ada adb
				arch.lhs top (sw -- sw) (swAfter -- fine)
				flatside.ld (left + [HSwToV : sw - fine]) bot top ada adb 0 [widths.lhs fine]

		export : define [toothless] : with-params [
				[top XH] [bot 0] [left SB] [right RightSB] [rise SHook] [sw Stroke] [fine ShoulderFine]
				[mBlend Math.SQRT1_2] [ada SmallArchDepthA] [adb SmallArchDepthB]
			] : begin
			return : dispiro
				g4 left (bot + rise) [widths.lhs sw]
				alsoThru.g2 0.5 mBlend important
				arch.lhs.centerAt.ltr.b [mix left right 0.5] bot (sw -- sw)
				archv
				flatside.ru right bot top ada adb
				arch.lhs top (sw -- sw) (swAfter -- fine)
				flat (left + [HSwToV : sw - fine]) (top - ada) [widths.lhs fine]
				curl (left + [HSwToV : sw - fine]) (top - ada - TINY) [widths.lhs fine]

		export : define [rounded] : with-params [
				[top XH] [bot 0] [left SB] [right RightSB] [yTerminal CAP] [sw Stroke] [fine ShoulderFine]
				[ada SmallArchDepthA] [adb SmallArchDepthB]
			] : begin
			return : dispiro
				flat left yTerminal [widths.lhs.heading sw Downward]
				curl left [Math.min adb (yTerminal - TINY)]
				arch.lhs bot (sw -- sw)
				flatside.ru right bot top ada adb
				arch.lhs top (sw -- sw) (swAfter -- fine)
				flat (left + [HSwToV : sw - fine]) (top - ada + TINY) [widths.lhs fine]
				curl (left + [HSwToV : sw - fine]) (top - ada) [widths.lhs fine]

		export : define [toothlessTop] : with-params [
				[top XH] [bot 0] [left SB] [right RightSB] [rise SHook] [sw Stroke] [fine ShoulderFine]
				[mBlend Math.SQRT1_2] [ada SmallArchDepthA] [adb SmallArchDepthB]
			] : begin
			return : dispiro
				flat (left + [HSwToV : sw - fine]) (bot + adb + TINY) [widths.lhs fine]
				curl (left + [HSwToV : sw - fine]) (bot + adb) [widths.lhs fine]
				arch.lhs bot (sw -- sw) (swBefore -- fine)
				flatside.ru right bot top ada adb
				arcvh
				arch.lhs.centerAt.rtl.t [mix left right 0.5] top (sw -- sw)
				alsoThru.g2 0.5 (1 - mBlend) important
				g4 left (top - rise) [widths.lhs sw]

		export : define [roundedTop] : with-params [
				[top XH] [bot 0] [left SB] [right RightSB] [yTerminal Descender] [sw Stroke]
				[fine ShoulderFine] [ada SmallArchDepthA] [adb SmallArchDepthB]
			] : begin
			return : dispiro
				flat (left + [HSwToV : sw - fine]) (bot + adb + TINY) [widths.lhs fine]
				curl (left + [HSwToV : sw - fine]) (bot + adb) [widths.lhs fine]
				arch.lhs bot (sw -- sw) (swBefore -- fine)
				flatside.ru right bot top ada adb
				arch.lhs top (sw -- sw)
				flat left [Math.max (yTerminal + TINY - TanSlope * Stroke) (top - ada)]
				curl left yTerminal [widths.lhs.heading sw Downward]

	glyph-block-export : OBarRight
	define OBarRight : namespace
		define kSkewShift 0.5
		export : define [arcStart] : with-params [
				[top XH] [left SB] [right RightSB] [sw Stroke] [fine ShoulderFine]
				[ada SmallArchDepthA] [adb SmallArchDepthB]
				[ystart (top - ada - TINY)]
			] : begin
			local xstart : right - [HSwToV : sw - fine]
			return : list
				flat xstart ystart [widths.lhs fine]
				curl xstart (top - adb)
				arch.lhs top (sw -- sw) (swBefore -- fine)

		export : define [arcEnd] : with-params [
				[bot 0] [left SB] [right RightSB] [sw Stroke] [fine ShoulderFine]
				[ada SmallArchDepthA] [adb SmallArchDepthB]
				[yend (bot + ada + TINY)]
			] : begin
			local xend : right - [HSwToV : sw - fine]
			return : list
				arch.lhs bot (sw -- sw) (swAfter -- fine)
				flat xend (bot + ada) [widths.lhs fine]
				curl xend yend

		export : define [shape] : with-params [
				[top XH] [bot 0] [left SB] [right RightSB] [sw Stroke] [fine ShoulderFine]
				[ada SmallArchDepthA] [adb SmallArchDepthB]
			] : new-glyph : glyph-proc
			include : OBarLeft.shape
				top   -- top
				bot   -- bot
				left  -- left
				right -- right
				sw    -- sw
				fine  -- fine
				ada   -- ada
				adb   -- adb
			include : FlipAround [mix left right 0.5] [mix bot top 0.5]

		export : define [toothless] : with-params [
				[top XH] [bot 0] [left SB] [right RightSB] [rise SHook] [sw Stroke] [fine ShoulderFine]
				[mBlend Math.SQRT1_2] [ada SmallArchDepthA] [adb SmallArchDepthB]
			] : new-glyph : glyph-proc
			include : OBarLeft.toothlessTop
				top    -- top
				bot    -- bot
				left   -- left
				right  -- right
				rise   -- rise
				sw     -- sw
				fine   -- fine
				mBlend -- mBlend
				ada    -- ada
				adb    -- adb
			include : FlipAround [mix left right 0.5] [mix bot top 0.5]

		export : define [rounded] : with-params [
				[top XH] [bot 0] [left SB] [right RightSB] [sw Stroke] [fine ShoulderFine]
				[yTerminal CAP] [ada SmallArchDepthA] [adb SmallArchDepthB]
			] : new-glyph : glyph-proc
			include : OBarLeft.roundedTop
				top       -- top
				bot       -- bot
				left      -- left
				right     -- right
				sw        -- sw
				fine      -- fine
				yTerminal -- (top - yTerminal)
				ada       -- ada
				adb       -- adb
			include : FlipAround [mix left right 0.5] [mix bot top 0.5]

	glyph-block-export FlatHookDepth
	define [FlatHookDepth df s] : object
		x : [fallback s 1] * [FlatHookDepthImpl [Math.min 1 : Math.sqrt df.adws] HVContrast]
		y : [fallback s 1] * [FlatHookDepthImpl [Math.min 1 : Math.sqrt df.adws]          1]
	define [FlatHookDepthImpl sHook sStroke] : begin
		define kFlathook : 15 / 16
		return : Math.max
			kFlathook * sHook * Hook
			sStroke * Stroke * 1.375
			Math.min
				kFlathook * sHook * Hook
				sStroke * Stroke * 1.625

	glyph-block-import Mark-Shared-Metrics : markMiddle
	glyph-block-export ConnectedCedilla
	define [ConnectedCedilla src sel] : glyph-proc
		include [refer-glyph src] AS_BASE ALSO_METRICS
		local mk : currentGlyph.baseAnchors.leaningBelow || currentGlyph.baseAnchors.below
		local tfm : ApparentTranslate (mk.x - markMiddle) (mk.y - 0)
		include : difference
			with-transform tfm [refer-glyph 'cedillaExtShapeBelow']
			with-transform [ApparentTranslate 0 (Stroke * 0.25)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 0.50)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 0.75)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 1.00)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 1.25)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 1.50)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 1.75)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 2.00)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 2.25)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 2.50)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 2.75)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 3.00)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 3.25)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 3.50)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 3.75)] [refer-glyph src]
			with-transform [ApparentTranslate 0 (Stroke * 4.00)] [refer-glyph src]
		include : refer-glyph 'blankBelow'
		include : refer-glyph 'blankLeaningBelow'

	glyph-block-export SerifedArcStart
	define SerifedArcStart : namespace
		export : define [RtlLhs sx cy sw hook origBar] : begin
			local barSw : if origBar sw [ArcStartSerifWidth sw]
			local fine : barSw * [mix CThinB (ShoulderFine / Stroke) 0.5]
			return : list
				g4.up.start
					sx - [HSwToV : barSw - fine]
					cy - [ArcStartSerifDepth hook]
					widths.lhs.heading fine Upward
				arch.lhs cy (sw -- sw) (swBefore -- fine)

		export : define [LtrRhs sx cy sw hook origBar] : begin
			local barSw : if origBar sw [ArcStartSerifWidth sw]
			local fine : barSw * [mix CThinB (ShoulderFine / Stroke) 0.5]
			return : list
				g4.up.start
					sx + [HSwToV : barSw - fine]
					cy - [ArcStartSerifDepth hook]
					widths.rhs.heading fine Upward
				arch.rhs cy (sw -- sw) (swBefore -- fine)

	glyph-block-export SerifedArcEnd
	define SerifedArcEnd : namespace
		export : define [RtlRhs ex cy sw hook origBar] : begin
			local barSw : if origBar sw [ArcStartSerifWidth sw]
			local fine : barSw * [mix CThinB (ShoulderFine / Stroke) 0.5]
			return : list
				arch.rhs cy (sw -- sw) (swAfter -- fine)
				g4.up.end
					ex + [HSwToV : barSw - fine]
					cy + [ArcStartSerifDepth hook]
					widths.rhs.heading fine Upward

		export : define [LtrLhs ex cy sw hook origBar] : begin
			local barSw : if origBar sw [ArcStartSerifWidth sw]
			local fine : barSw * [mix CThinB (ShoulderFine / Stroke) 0.5]
			return : list
				arch.lhs cy (sw -- sw) (swAfter -- fine)
				g4.up.end
					ex - [HSwToV : barSw - fine]
					cy + [ArcStartSerifDepth hook]
					widths.lhs.heading fine Upward

	glyph-block-export InwardSlabArcStart
	define InwardSlabArcStart : namespace
		export : define [RtlLhs ex cy sw _hook] : begin
			return : list
				g2 ex (cy - DToothlessRise) [widths.lhs sw]
				arch.lhs cy (sw -- sw) (blendPre -- {})

		export : define [LtrRhs ex cy sw _hook] : begin
			return : list
				g2 ex (cy - DToothlessRise) [widths.rhs sw]
				arch.rhs cy (sw -- sw) (blendPre -- {})

	glyph-block-export InwardSlabArcEnd
	define InwardSlabArcEnd : namespace
		export : define [RtlRhs sx cy sw _hook] : begin
			return : list
				arch.rhs cy (sw -- sw) (blendPost -- {})
				g2 sx (cy + DToothlessRise) [widths.rhs sw]
		export : define [LtrLhs sx cy sw _hook] : begin
			return : list
				arch.lhs cy (sw -- sw) (blendPost -- {})
				g2 sx (cy + DToothlessRise) [widths.lhs sw]

	glyph-block-export ArcStartSerifWidth
	define [ArcStartSerifWidth stroke] : clamp (stroke * 0.875) stroke VJutStroke

	glyph-block-export ArcStartSerifDepth
	define [ArcStartSerifDepth hook] : hook - 0

	define [ArcStartInwardSerifDepth hook stroke] : Math.max hook : DToothlessRise + stroke

	glyph-block-export : ArcStartSerif
	define ArcStartSerif : namespace
		export : define [L cx cy stroke hook overflow] : begin
			return : tagged 'arcStartSerifL' : VBar.l cx (cy - [ArcStartSerifDepth hook]) (cy + [fallback overflow 0]) [ArcStartSerifWidth stroke]
		export : define [R cx cy stroke hook overflow] : begin
			return : tagged 'arcStartSerifR' : VBar.r cx (cy - [ArcStartSerifDepth hook]) (cy + [fallback overflow 0]) [ArcStartSerifWidth stroke]

		export : define [InwardL cx cy stroke hook] : begin
			return : tagged 'arcStartSerifL' : VBar.l cx (cy - [ArcStartInwardSerifDepth hook stroke]) (cy - DToothlessRise) [ArcStartSerifWidth stroke]
		export : define [InwardR cx cy stroke hook] : begin
			return : tagged 'arcStartSerifR' : VBar.r cx (cy - [ArcStartInwardSerifDepth hook stroke]) (cy - DToothlessRise) [ArcStartSerifWidth stroke]

	glyph-block-export : ArcEndSerif
	define ArcEndSerif : namespace
		export : define [L cx cy stroke hook overflow] : begin
			return : tagged 'arcEndSerifL' : VBar.l cx (cy + [ArcStartSerifDepth hook]) (cy - [fallback overflow 0]) [ArcStartSerifWidth stroke]
		export : define [R cx cy stroke hook overflow] : begin
			return : tagged 'arcEndSerifR' : VBar.r cx (cy + [ArcStartSerifDepth hook]) (cy - [fallback overflow 0]) [ArcStartSerifWidth stroke]

		export : define [InwardL cx cy stroke hook] : begin
			return : tagged 'arcEndSerifL' : VBar.l cx (cy + [ArcStartInwardSerifDepth hook stroke]) (cy + DToothlessRise) [ArcStartSerifWidth stroke]
		export : define [InwardR cx cy stroke hook] : begin
			return : tagged 'arcEndSerifR' : VBar.r cx (cy + [ArcStartInwardSerifDepth hook stroke]) (cy + DToothlessRise) [ArcStartSerifWidth stroke]

	glyph-block-export DiagTail
	define DiagTail : namespace

		export : define DefaultAngle 40

		export : define [StdDepth df sw] : Math.max (0.5 * sw)
			df.adws * para.unitWidthScalar * [Math.hypot HookX Hook] - 0.25 * sw

		export : define [DefaultInnerRadius] : Math.max (XH / 32) (0.5 * [AdviceStroke2 24 32 XH])

		define [FineSw sw] : begin
			define mocFine : [AdviceStroke 3] * (sw / Stroke)
			return : mocFine / [mix 1 HVContrast 0.375]

		define DiagTailSuperness DesignParameters.superness

		export : define [F sign cx cy rIn angle depth sw] : begin
			define tailAngle : angle / 180 * Math.PI
			define {cosAngle sinAngle} : superEllipse tailAngle
			define {dCosAngle dSinAngle} : superEllipseDerivative tailAngle

			define fine : FineSw sw
			define r : rIn + 0.5 * fine
			define dxTurn : [HSwToV : 0.5 * sw] + rIn + 0.5 * sign * TanSlope * fine
			define dxTailStart : dxTurn + sinAngle * (r * [mix 1 HVContrast sinAngle])
			define dyTailStart : (rIn + fine) - cosAngle * r
			define dxDepth : (depth - 0.25 * sw) * (+dSinAngle)
			define dyDepth : (depth - 0.25 * sw) * (-dCosAngle)
			return : list
				g4.[if (sign > 0) "right" "left"].mid
					cx + sign * dxTurn
					cy + O + 0.5 * fine
					widths.center fine
				alsoThruThem : FArc tailAngle 4
				flat (cx + sign *  dxTailStart)            (cy + O + dyTailStart) [widths.center fine]
				curl (cx + sign * (dxTailStart + dxDepth)) (cy + O + dyTailStart + dyDepth)

		define [superEllipse theta] : list
			[Math.cos theta] ** (2 / DiagTailSuperness)
			[Math.sin theta] ** (2 / DiagTailSuperness)

		define [superEllipseDerivative theta] : begin
			local dc : (2 / DiagTailSuperness) * [Math.sin (-theta)] * ([Math.cos theta] ** (2 / DiagTailSuperness - 1))
			local ds : (2 / DiagTailSuperness) * [Math.cos (-theta)] * ([Math.sin theta] ** (2 / DiagTailSuperness - 1))
			local h : Math.hypot dc ds
			return : list (dc / h) (ds / h)

		define [FArc tailAngle n] : begin
			local results {}
			foreach i [range 1 n] : begin
				local t : i / n
				local {tc ts} : superEllipse (t * tailAngle)
				local {ec es} : superEllipse tailAngle
				results.push : list (ts / es) ((1 - tc) / (1 - ec))
			return results

		export : define [R cx cy depth sw] : begin
			define rInY : DefaultInnerRadius
			return : list
				curl cx (cy + [FineSw sw] + rInY)
				arcvh 8 DiagTailSuperness
				F (+1) cx cy rInY DefaultAngle depth sw

		export : define [L cx cy depth sw] : begin
			define rInY : DefaultInnerRadius
			return : list
				curl cx (cy + [FineSw sw] + rInY)
				arcvh 8 DiagTailSuperness
				F (-1) cx cy rInY DefaultAngle depth sw

	define [JutIn left right jut swRef hSplit] : begin
		local ink : HSwToV swRef
		local gap : (right - left - hSplit * ink) / (hSplit - 1)
		return : Math.min jut : 0.5 * ink + [Math.max (Stroke * TanSlope) (0.375 * gap)]

	class CSerifFrame
		public [new top bot left right swRef swSerif adws hSplit fForceSymmetric] : begin
			set this.top             top
			set this.bot             bot
			set this.left            left
			set this.right           right
			set this.swRef           swRef
			set this.swSerif         swSerif
			set this.adws            adws
			set this.hSplit          hSplit
			set this.fForceSymmetric fForceSymmetric

			local ink : HSwToV swRef
			local gap : (right - left - hSplit * ink) / (hSplit - 1)


			local jutFS   MidJutSide
			local jut     : mix [HSwToV : 0.5 * swRef] Jut : Math.min 1 : adws * 2.25 / hSplit
			local sideJut : jut - 0.5 * ink

			local jutIn     : if fForceSymmetric jut : JutIn left right jut swRef hSplit
			local sideJutIn : jutIn - 0.5 * ink

			local lBarCenter : left + 0.5 * ink
			local lBarInner  : left + 1.0 * ink
			local rBarCenter : right - 0.5 * ink
			local rBarInner  : right - 1.0 * ink

			set this.jut     jut
			set this.sideJut sideJut

			set this.enoughSpaceForFullSerifs : 0.5 * ink + 0.375 * gap > para.refJut

			set this.lt : object
				full        : tagged 'serifLT' : HSerif.mtAsymmetric lBarCenter top jut jutIn swSerif
				[fullExt s] : tagged 'serifLT' : HSerif.mtAsymmetric lBarCenter top jut [JutIn left right jut swRef s] swSerif
				fullSide    : tagged 'serifLT' : HSerif.mtAsymmetric lBarCenter top jut jutFS swSerif
				outer       : tagged 'serifLT' : HSerif.lt left top sideJut swSerif
				inner       : tagged 'serifLT' : HSerif.rt lBarInner top sideJutIn swSerif
			set this.rt : object
				full        : tagged 'serifRT' : HSerif.mtAsymmetric rBarCenter top jutIn jut swSerif
				[fullExt s] : tagged 'serifRT' : HSerif.mtAsymmetric rBarCenter top [JutIn left right jut swRef s] jut swSerif
				fullSide    : tagged 'serifRT' : HSerif.mtAsymmetric rBarCenter top jutFS jut swSerif
				outer       : tagged 'serifRT' : HSerif.rt right top sideJut swSerif
				inner       : tagged 'serifRT' : HSerif.lt rBarInner top sideJutIn swSerif
			set this.lb : object
				full        : tagged 'serifLB' : HSerif.mbAsymmetric lBarCenter bot jut jutIn swSerif
				[fullExt s] : tagged 'serifLB' : HSerif.mbAsymmetric lBarCenter bot jut [JutIn left right jut swRef s] swSerif
				fullSide    : tagged 'serifLB' : HSerif.mbAsymmetric lBarCenter bot jut jutFS swSerif
				outer       : tagged 'serifLB' : HSerif.lb left bot sideJut swSerif
				inner       : tagged 'serifLB' : HSerif.rb lBarInner bot sideJutIn swSerif
			set this.rb : object
				full        : tagged 'serifRB' : HSerif.mbAsymmetric rBarCenter bot jutIn jut swSerif
				[fullExt s] : tagged 'serifRB' : HSerif.mbAsymmetric rBarCenter bot [JutIn left right jut swRef s] jut swSerif
				fullSide    : tagged 'serifRB' : HSerif.mbAsymmetric rBarCenter bot jutFS jut swSerif
				outer       : tagged 'serifRB' : HSerif.rb right bot sideJut swSerif
				inner       : tagged 'serifRB' : HSerif.lb rBarInner bot sideJutIn swSerif

			set this.mb : object
				full : tagged 'serifMB' : HSerif.mbAsymmetric [mix lBarCenter rBarCenter 0.5] bot jutIn jutIn swSerif
				[fullAt x] : tagged 'serifMB' : HSerif.mbAsymmetric x bot jutIn jutIn swSerif
				left : tagged 'serifMB' : HSerif.mbAsymmetric [mix lBarCenter rBarCenter 0.5] bot jutIn 0 swSerif
				[leftAt x] : tagged 'serifMB' : HSerif.mbAsymmetric x bot jutIn 0 swSerif
				right : tagged 'serifMB' : HSerif.mbAsymmetric [mix lBarCenter rBarCenter 0.5] bot 0 jutIn swSerif
				[rightAt x] : tagged 'serifMB' : HSerif.mbAsymmetric x bot 0 jutIn swSerif
			set this.mt : object
				full : tagged 'serifMT' : HSerif.mtAsymmetric [mix lBarCenter rBarCenter 0.5] top jutIn jutIn swSerif
				[fullAt x] : tagged 'serifMT' : HSerif.mtAsymmetric x top jutIn jutIn swSerif
				left : tagged 'serifMT' : HSerif.mtAsymmetric [mix lBarCenter rBarCenter 0.5] top jutIn 0 swSerif
				[leftAt x] : tagged 'serifMT' : HSerif.mtAsymmetric x top jutIn 0 swSerif
				right : tagged 'serifMT' : HSerif.mtAsymmetric [mix lBarCenter rBarCenter 0.5] top 0 jutIn swSerif
				[rightAt x] : tagged 'serifMT' : HSerif.mtAsymmetric x top 0 jutIn swSerif

		public [slice l r] : begin
			local ink : HSwToV this.swRef
			local gap : (this.right - this.left - this.hSplit * ink) / (this.hSplit - 1)
			local l1 : this.left + (ink + gap) * l
			local r1 : this.left + (ink + gap) * r + ink
			return : new CSerifFrame this.top this.bot l1 r1 this.swRef this.swSerif this.adws (r - l + 1)

	glyph-block-export SerifFrame
	define flex-params [SerifFrame] : begin
		local-parameter : top
		local-parameter : bot
		local-parameter : left
		local-parameter : right
		local-parameter : swRef   -- Stroke
		local-parameter : swSerif -- swRef
		local-parameter : adws    -- 1
		local-parameter : hSplit  -- 2
		local-parameter : fForceSymmetric -- false
		return : new CSerifFrame top bot left right swRef swSerif adws hSplit fForceSymmetric

	define SerifFrame.fromDf : function [] : with-params [df top bot [swSerif df.mvs] [fForceSymmetric false]] : begin
		return : SerifFrame top bot df.leftSB df.rightSB
			swRef   -- df.mvs
			adws    -- df.adws
			hSplit  -- [Math.max 2 df.hPack]
			swSerif -- swSerif
			fForceSymmetric -- fForceSymmetric


	glyph-block-export WithSerifOverflowMask
	define [WithSerifOverflowMask fEnable top bottom left right s] : begin
		if [not fEnable] : return s

		local leftCenter : left + [HSwToV HalfStroke]
		local rightCenter : right - [HSwToV HalfStroke]
		local adj : TanSlope * Stroke * DesignParameters.serifShiftX
		return : intersection s : union
			Rect top [mix top bottom 0.5] (leftCenter - Jut) (rightCenter + Jut - adj)
			Rect [mix top bottom 0.5] bottom (leftCenter - Jut + adj) (rightCenter + Jut)

	glyph-block-export LegShape
	define [LegShape] : with-params [ztop zbot xb [fine Stroke]] : glyph-proc
		include : dispiro
			widths.lhs fine
			flat ztop.x ztop.y [heading Downward]
			curl xb [mix (zbot.y + LongJut) ztop.y 0.25]
			alsoThruThem {{0.2 0.76} {0.3 0.85} {0.5 0.94}}
			straight.left.end zbot.x (zbot.y + fine) [heading Leftward]

	glyph-block-export UpwardHookShape
	define [UpwardHookShape] : with-params [left right ybegin yend [bottom O] ada adb [sw Stroke]] : glyph-proc
		include : dispiro
			widths.lhs sw
			flat left ybegin [heading Downward]
			curl left [Math.min adb : ybegin - TINY]
			arcvh
			g4 [mix left right 0.5] bottom [heading Rightward]
			archv
			flat right ada
			curl right yend [heading Upward]

	glyph-block-export RhoticHookShape
	define [RhoticHookShape] : with-params [left right y rise [sw [AdviceStroke 5]] [doHook false]] : glyph-proc
		local mid : mix left right 0.5
		include : dispiro
			widths.rhs sw
			g2 (left - [HSwToV : 0.5 * sw]) (y + 0)
			g2 (mid  - [HSwToV : 0.5 * sw]) (y + rise)
		include : dispiro
			widths.center sw
			flat mid (y + rise) [heading Downward]
			curl mid (y + [if doHook 0 (rise - 1)]) [heading Downward]
			if doHook {[hookend (y - rise) (sw -- sw)]} {[arcvh]}
			g4 (right - [if doHook sw 0]) (y - [if doHook (rise * 0.5) rise]) [if doHook nothing [heading Rightward]]

	# Generic "connected" vertical hooks
	glyph-block-export VerticalHook
	define VerticalHook : namespace
		export : define [m] : with-params [x y xDepth yDepth [sw Stroke] [yExtension 0]] : begin
			local hd : FlatHookDepth [DivFrame 1]
			local hdX : if (xDepth < 0) (-hd.x) hd.x
			local hdY : if (yDepth < 0) (-hd.y) hd.y

			local y2 : if (yDepth > 0)
				Math.min (y - yDepth + hd.y - 0.25 * sw) (y - TINY)
				Math.max (y - yDepth - hd.y + 0.25 * sw) (y + TINY)

			local x3 : if (xDepth > 0)
				Math.min (x + xDepth - TINY) (x + hd.x - [HSwToV : 0.25 * sw])
				Math.max (x + xDepth + TINY) (x - hd.x + [HSwToV : 0.25 * sw])

			dispiro [widths.center sw]
				flat x (y + yExtension) [heading : if (yDepth > 0) Downward Upward]
				curl x  y2              [heading : if (yDepth > 0) Downward Upward]
				arcvh
				flat x3           (y - yDepth)
				curl (x + xDepth) (y - yDepth)

		export : define [l] : with-params [x y xDepth yDepth [sw Stroke] [yExtension 0]]
			m
				x      -- (x + [HSwToV : 0.5 * sw])
				y      -- y
				xDepth -- xDepth
				yDepth -- yDepth
				sw     -- sw
				yExtension -- yExtension

		export : define [r] : with-params [x y xDepth yDepth [sw Stroke] [yExtension 0]]
			m
				x      -- (x - [HSwToV : 0.5 * sw])
				y      -- y
				xDepth -- xDepth
				yDepth -- yDepth
				sw     -- sw
				yExtension -- yExtension

	do "Descender shapes"
		define [xLinkStroke xLink x yAttach sw]
			if (xLink == nothing) [no-shape] : HBar.b
				Math.min xLink : x - [HSwToV : 0.5 * sw]
				Math.max xLink : x + [HSwToV : 0.5 * sw]
				begin yAttach

		define [Descenders Impl] : namespace
			export : define Sw ArcStartSerifWidth
			export : define [adviceGap refSw] : [HSwToV : Sw refSw] + [Math.max (Width / 16) [AdviceStroke 12]]

			export : define [m] : with-params [x y xLink [yAttach y] [yOverflow 0] [refSw Stroke] [maskOut null]] : begin
				local sw : Sw refSw
				return : Impl x y xLink yAttach yOverflow sw maskOut
			export : define [l] : with-params [x y xLink [yAttach y] [yOverflow 0] [refSw Stroke] [maskOut null]] : begin
				local sw : Sw refSw
				return : Impl (x + [HSwToV : 0.5 * sw]) y xLink yAttach yOverflow sw maskOut
			export : define [r] : with-params [x y xLink [yAttach y] [yOverflow 0] [refSw Stroke] [maskOut null]] : begin
				local sw : Sw refSw
				return : Impl (x - [HSwToV : 0.5 * sw]) y xLink yAttach yOverflow sw maskOut

			export : define [lExt] : with-params [x y xLink [yAttach y] [yOverflow 0] [sw Stroke] [maskOut null]] : begin
				return : Impl (x + [HSwToV : 0.5 * sw]) y xLink yAttach yOverflow sw maskOut
			export : define [mExt] : with-params [x y xLink [yAttach y] [yOverflow 0] [sw Stroke] [maskOut null]] : begin
				return : Impl x y xLink yAttach yOverflow sw maskOut
			export : define [rExt] : with-params [x y xLink [yAttach y] [yOverflow 0] [sw Stroke] [maskOut null]] : begin
				return : Impl (x - [HSwToV : 0.5 * sw]) y xLink yAttach yOverflow sw maskOut

			export : define [lSideJut] : with-params [x y [yOverflow 0] [refSw Stroke] [jut Jut] [sideJut nothing]] : begin
				local sj : fallback sideJut (jut - [HSwToV : 0.5 * refSw])
				local sw : Sw refSw
				local xLink : x + [HSwToV : 0.5 * refSw] - TanSlope * sw
				local xPos : x + [HSwToV : 0.5 * sw] - sj + sw * TanSlope * (DesignParameters.serifShiftX - 1)
				return : Impl xPos y xLink y yOverflow sw

			export : define [rSideJut] : with-params [x y [yOverflow 0] [refSw Stroke] [jut Jut] [sideJut nothing]] : begin
				local sj : fallback sideJut (jut - [HSwToV : 0.5 * refSw])
				local sw : Sw refSw
				local xLink : x - [HSwToV : 0.5 * refSw]
				local xPos : x - [HSwToV : 0.5 * sw] + sj + sw * TanSlope * (DesignParameters.serifShiftX + 1)
				return : Impl xPos y xLink y yOverflow sw

		# Diacritical descender of cyrillics
		glyph-block-export CyrDescender
		define CyrDescender : Descenders : function [x y xLink yAttach yOverflow sw] : glyph-proc
			local extension : (-LongVJut) + QuarterStroke
			include : ExtendBelowBaseAnchors (y + extension)
			include : union
				xLinkStroke xLink x yAttach sw
				VBar.m x yAttach (y + extension) sw

		glyph-block-export CyrTailDescender
		define CyrTailDescender : Descenders : function [x y xLink yAttach yOverflow sw] : glyph-proc
			local extension : (-LongVJut) + QuarterStroke
			include : ExtendBelowBaseAnchors (y + extension)
			include : union
				xLinkStroke xLink x yAttach sw
				intersection
					MaskBelow (yAttach + Stroke)
					MaskAbove (y + extension)
					ExtLineCenter 16 sw (x + 0.24 * Descender) (y + 0.5 * sw + Descender) x y

		# Palatal Hooks
		glyph-block-export PalatalHook
		define PalatalHook : Descenders : function [x y xLink yAttach yOverflow sw maskOut] : glyph-proc
			local fullDepth : (-Descender) - 0.5 * sw - O
			include : ExtendBelowBaseAnchors (y + Descender)
			include : difference
				union
					xLinkStroke xLink x yAttach sw
					VerticalHook.m
						x      -- x
						y      -- (y - (fullDepth - TailY))
						xDepth -- (-TailX)
						yDepth -- TailY
						sw     -- sw
						yExtension -- [Math.max 0 : yAttach + yOverflow - y + (fullDepth - TailY)]
				if maskOut maskOut [no-shape]

		# Retroflex hooks
		glyph-block-export RetroflexHook
		define RetroflexHook : Descenders : function [x y xLink yAttach yOverflow sw] : glyph-proc
			local fullDepth : (-Descender) - 0.5 * sw - O
			include : ExtendBelowBaseAnchors (y + Descender)
			include : union
				xLinkStroke xLink x yAttach sw
				VerticalHook.m
					x      -- x
					y      -- (y - (fullDepth - TailY))
					xDepth -- TailX
					yDepth -- TailY
					sw     -- sw
					yExtension -- [Math.max 0 : yAttach + yOverflow - y + (fullDepth - TailY)]

		# Cyrillic "Middle Hook" Characters
		glyph-block-export MidHook
		define MidHook : namespace
			export : define [general] : with-params [left right top [bottom 0] ada adb [sw Stroke] [xDepth (-HookX)]] : composite-proc
				nShoulder.shape
					left   -- left
					right  -- right
					top    -- top
					bottom -- bottom
					ada    -- ada
					adb    -- adb
					stroke -- sw
				VerticalHook.r right bottom xDepth Hook sw

			# "Standard" version for El, Pe, En with MidHook
			export : define [m df top] : begin
				local xm : df.middle + [HSwToV : 0.5 * df.mvs]
				general
					left   -- xm
					right  -- df.rightSB
					top    -- (top * 0.625 + df.mvs / 4)
					ada    -- ArchDepthA
					adb    -- ArchDepthB
					sw     -- df.mvs
					xDepth -- (0 - [Math.max [HSwToV df.mvs] : Math.min HookX : 0.5 * (df.rightSB - df.leftSB) - [HSwToV df.mvs]])

		# Hook for Eng shape
		glyph-block-export EngHook
		define [EngHook] : with-params [x yStart yEnd [sw Stroke]] : begin
			return : VerticalHook.r x (yEnd + Hook + 0.5 * sw) (-HookX) Hook
				yExtension -- [Math.max 0 : yStart - (yEnd + Hook + 0.5 * sw)]
				sw -- sw

		# Upward hook shape
		glyph-block-export TopHook
		define TopHook : namespace
			define [ward sign] : namespace
				# Reference point at a bar's left edge, hook placed above yTop
				export : define [lBarOuter] : with-params [x yBot yTop [sw Stroke]] : glyph-proc
					local fullDepth : (Ascender - XH) - 0.5 * sw - O
					local yHookStart : yTop + (fullDepth - TailY)
					include : ExtendAboveBaseAnchors (yTop + (Ascender - XH))
					include : union
						VBar.l x yBot yHookStart sw
						VerticalHook.l x yHookStart (sign * TailX) (-TailY) (sw -- sw)

				# Reference point at a bar's left edge, hook placed below yTop
				export : define [lBarInner] : with-params [x yBot yTop [sw Stroke]] : glyph-proc
					local yHookStart : yTop - O - TailY - 0.5 * sw
					include : union
						VBar.l x yBot yHookStart sw
						VerticalHook.l x yHookStart (sign * TailX) (-TailY) (sw -- sw)

				# Reference point at a bar's right edge, hook placed above yTop
				export : define [rBarOuter] : with-params [x yBot yTop [sw Stroke]] : begin
					return : lBarOuter (x - [HSwToV sw]) yBot yTop (sw -- sw)
				# Reference point at a bar's right edge, hook placed below yTop
				export : define [rBarInner] : with-params [x yBot yTop [sw Stroke]] : begin
					return : lBarInner (x - [HSwToV sw]) yBot yTop (sw -- sw)

				# Reference point at a bar's centerline, hook placed above yTop
				export : define [mBarOuter] : with-params [x yBot yTop [sw Stroke]] : begin
					return : lBarOuter (x - [HSwToV : 0.5 * sw]) yBot yTop (sw -- sw)
				# Reference point at a bar's centerline, hook placed below yTop
				export : define [mBarInner] : with-params [x yBot yTop [sw Stroke]] : begin
					return : lBarInner (x - [HSwToV : 0.5 * sw]) yBot yTop (sw -- sw)

				# Special case for arc-start shapes
				export : define [arcStart] : with-params [cx cy hookY [refSw Stroke]] : begin
					local sw : ArcStartSerifWidth refSw
					local fullDepth : (Ascender - XH) - 0.5 * sw - O
					local yHookStart : cy + (fullDepth - TailY)
					return : union
						VBar.r cx (cy - hookY + O * 2) yHookStart sw
						VerticalHook.r cx yHookStart (sign * TailX) (-TailY) sw

			export : define toLeft : ward (-1)
			export : define toRight : ward (+1)

		# Leftward hook
		glyph-block-export LeftHook
		define [LeftHook x y xextend] : glyph-proc
			local fine : AdviceStroke 4.25
			include : dispiro
				widths.lhs fine
				flat [fallback xextend : x + 1] y
				curl x y
				archv 8
				g4.down.end (x - LeftHook.extension) (y - HookX) [heading Downward]
		set LeftHook.extension [Math.max (Width * 0.2) ([AdviceStroke 4.25] * 1.5)]

	do "Belt overlays"
		define [BeltOverlayAt x y] : begin
			local fine : AdviceStroke 4.5
			local r : XH * 0.05
			return : dispiro
				widths.rhs fine
				flat x (y + r) [heading Leftward]
				curl (x - HalfStroke - r * 1.5) (y + r)
				archv
				g4.down.mid (x - HalfStroke - r * 2.5) y [heading Downward]
				arcvh
				flat (x - HalfStroke - r * 1.5) (y - r)
				curl (x + HalfStroke + r * 1.5 + fine) (y - r)

		glyph-block-export BeltOverlay
		define [BeltOverlay top xMiddle] : BeltOverlayAt xMiddle (0.5 * top)
		set BeltOverlay.at BeltOverlayAt

	do "Letter bar overlays"
		glyph-block-export LetterBarOverlay LetterObliqueBarOverlay
		define [BarOverlayImpl] : with-params [barFunc x y space refSw pXInSw sw] : begin
			local {xLeftSpace xRightSpace} space
			local xLeftEdge  : x - (0 + pXInSw) * [HSwToV refSw]
			local xRightEdge : x + (1 - pXInSw) * [HSwToV refSw]
			local p : (xLeftEdge - xLeftSpace) / ((xRightSpace - xRightEdge) + (xLeftEdge - xLeftSpace))
			local xC : mix xLeftEdge xRightEdge : mix 0.5 (1 - p) 0.5
			local jut : 0.75 * LongJut
			return : barFunc
				Math.min (xLeftEdge - SideJut)
					Math.max (xC - jut) : mix xLeftSpace xLeftEdge 0.3
				Math.max (xRightEdge + SideJut)
					Math.min (xC + jut) : mix xRightSpace xRightEdge 0.3
				begin y
				begin sw

		define [calcYAndSw bot top py sw] : begin
			local y : mix bot top py
			local sw1 : Math.min sw
				1.25 * (top - bot) * (0 + py)
				1.25 * (top - bot) * (1 - py)
			return { y sw1 }

		define [LetterBarOverlay] : with-params [x y space refSw pXInSw sw]
			BarOverlayImpl HOverlayBar x y space refSw pXInSw sw
		define [LetterObliqueBarOverlay] : with-params [x y space refSw pXInSw sw]
			BarOverlayImpl HOverlayObliqueBar x y space refSw pXInSw sw

		foreach base {LetterBarOverlay LetterObliqueBarOverlay} : let [base] : begin
			set base.l : function []
				with-params [x y [space {0 Width}] [refSw Stroke] [sw OverlayStroke]] : begin
					(base) x y (space -- space) (refSw -- refSw) (pXInSw -- 0) (sw -- sw)
			set base.m : function []
				with-params [x y [space {0 Width}] [refSw Stroke] [sw OverlayStroke]] : begin
					(base) x y (space -- space) (refSw -- refSw) (pXInSw -- 0.5) (sw -- sw)
			set base.r : function []
				with-params [x y [space {0 Width}] [refSw Stroke] [sw OverlayStroke]] : begin
					(base) x y (space -- space) (refSw -- refSw) (pXInSw -- 1) (sw -- sw)

			set base.l.in : function []
				with-params [x bot top [py 0.5] [space {0 Width}] [refSw Stroke] [sw OverlayStroke]]
				: begin
					local { y sw1 } : calcYAndSw bot top py sw
					(base) x y (space -- space) (refSw -- refSw) (pXInSw -- 0) (sw -- sw1)
			set base.m.in : function []
				with-params [x bot top [py 0.5] [space {0 Width}] [refSw Stroke] [sw OverlayStroke]]
				: begin
					local { y sw1 } : calcYAndSw bot top py sw
					(base) x y (space -- space) (refSw -- refSw) (pXInSw -- 0.5) (sw -- sw1)
			set base.r.in : function []
				with-params [x bot top [py 0.5] [space {0 Width}] [refSw Stroke] [sw OverlayStroke]]
				: begin
					local { y sw1 } : calcYAndSw bot top py sw
					(base) x y (space -- space) (refSw -- refSw) (pXInSw -- 1) (sw -- sw1)
