###### COMMON GLYPH CONSTRUCTIONS
define [select-variant name unicode default featureSelector] : begin
	if (pickHash && [not pickHash.(name)]) : return nothing
	local variant : variantSelector.(name) || default
	local chosenGlyph glyphs.((name + '.' + variant))
	create-glyph name : glyph-construction
		include chosenGlyph AS_BASE
		if unicode : assign-unicode unicode
		if featureSelector : set currentGlyph.featureSelector featureSelector

define [italic-variant name unicode] : create-glyph name : glyph-construction
	if para.isItalic
		then : include glyphs.(name + '.italic') AS_BASE
		else : include glyphs.(name + '.upright') AS_BASE
	if unicode : assign-unicode unicode

define [alias newid unicode oldid] : begin
	create-glyph newid : glyph-construction
		if unicode : assign-unicode unicode
		include glyphs.(oldid) AS_BASE
		set-width glyphs.(oldid).advanceWidth
		set this.featureSelector glyphs.(oldid).featureSelector

define [composite newid] : let [parts : {}.slice.call arguments 1] : begin
	create-glyph [fallback newid ('glyph' + [set nTemp (nTemp + 1)])] : glyph-construction
		local first true
		foreach [part : items-of parts] : begin
			include part first
			if first : set-width part.advanceWidth
			set first false

define [into-unicode code] : glyph-construction
	if code : assign-unicode code

# Transformation variants
define [turned newid unicode id x y mark] : create-glyph [fallback newid : 'turn' + id] : glyph-construction
	if unicode : assign-unicode unicode
	include glyphs.(id) [if mark false AS_BASE]
	set-width glyphs.(id).advanceWidth
	if mark : include mark
	include : FlipAround x y
# Dual derivatives
define [dual newid unicode id spacing] : create-glyph [fallback newid : 'double' + id] : glyph-construction
	if unicode : assign-unicode unicode
	include glyphs.(id) AS_BASE
	apply-transform : Translate (-spacing) 0
	include glyphs.(id)
	apply-transform : Translate (spacing / 2) 0

define [vdual newid unicode id spacing] : create-glyph [fallback newid : 'double' + id] : glyph-construction
	if unicode : assign-unicode unicode
	depends-on glyphs.(id)
	include : create-glyph : glyph-construction
		include glyphs.(id)
		apply-transform : Upright
	apply-transform : Translate 0 (-spacing)
	include : create-glyph : glyph-construction
		include glyphs.(id)
		apply-transform : Upright
	apply-transform : Translate 0 (spacing / 2)
	apply-transform : Italify
# Full-width derivatives
define [fwl newid unicode id] : create-glyph [fallback newid : 'fwl' + id] : glyph-construction
	if unicode : assign-unicode unicode
	include glyphs.(id)
	set-width FULLWIDTH

define [fwr newid unicode id] : create-glyph [fallback newid : 'fwr' + id] : glyph-construction
	if unicode : assign-unicode unicode
	include glyphs.(id)
	set-width FULLWIDTH
	apply-transform : Translate (FULLWIDTH - WIDTH) 0

define [dwl newid unicode id] : create-glyph [fallback newid : 'dwl' + id] : glyph-construction
	if unicode : assign-unicode unicode
	include glyphs.(id)
	set-width UPM

define [dwr newid unicode id] : create-glyph [fallback newid : 'dwr' + id] : glyph-construction
	if unicode : assign-unicode unicode
	include glyphs.(id)
	set-width UPM
	apply-transform : Translate (UPM - WIDTH) 0

define [dwc newid unicode id] : create-glyph [fallback newid : 'dwc' + id] : glyph-construction
	if unicode : assign-unicode unicode
	include glyphs.(id)
	set-width UPM
	apply-transform : Translate ((UPM - WIDTH) / 2) 0



###### COMMON SHAPES
define [Ring u d l r transformShiftOnly] : create-glyph : glyph-construction
	local my ((u + d) / 2)
	local mx ((l + r) / 2)
	currentGlyph.gizmo = [if transformShiftOnly [Translate 0 0] globalTransform]
	include : spiro-outline
		begin [lambda : set this.gizmo currentGlyph.gizmo]
		g4 mx d
		archv
		g4 l my
		arcvh
		g4 mx u
		archv
		g4 r my
		arcvh
		close [lambda : begin [set this.angles 4] [set this.fairGizmo currentGlyph.gizmo]]
	if transformShiftOnly : begin
		local {.x mx1 .y my1} [tp globalTransform {.x mx .y my}]
		apply-transform : Translate (mx1 - mx) (my1 - my)
define [RingAt x y r] : Ring (y + r) (y - r) (x - r) (x + r)
define [DotAt x y r] : Ring (y + r) (y - r) (x - r) (x + r) true

define [OShape u d l r _width _sma _smb ai] : glyph-construction
	local middle : (l + r) / 2
	local width : fallback _width STROKE
	local sma : fallback _sma SMALLSMOOTHA
	local smb : fallback _smb SMALLSMOOTHB
	local mc : CORRECTION_OMIDX * width
	if (u - d > sma + smb) : then : begin
		include : dispiro
			widths width 0
			g4 (middle - mc) (u - O)
			archv
			[if ai flat.ai flat] (l + OX) (u - sma)
			[if ai curl.ai curl] (l + OX) (d + smb)
			arcvh
			g4 (middle + mc) (d + O)
			archv
			[if ai flat.ai flat] (r - OX) (d + sma)
			[if ai curl.ai curl] (r - OX) (u - smb)
			arcvh
			close
	: else : begin
		local ymiddlea : mix d u (smb / (sma + smb))
		local ymiddleb : mix d u (sma / (sma + smb))
		include : dispiro
			widths width 0
			g4 (middle - mc) (u - O)
			archv
			g4 (l + OX) ymiddlea
			arcvh
			g4 (middle + mc) (d + O)
			archv
			g4 (r - OX) ymiddleb
			arcvh
			close
define [OBarLeftShape _top _left] : glyph-construction
	local top : fallback _top XH
	local left : fallback _left SB
	local fine SHOULDERFINE
	local st : shoulderMidSlope fine nothing 1
	local sb : shoulderMidSlope fine nothing (-1)
	local mt : [mix left RIGHTSB 0.5] + (st - CORRECTION_OMIDX) * STROKE
	local mb : [mix left RIGHTSB 0.5] + (sb + CORRECTION_OMIDX) * STROKE
	include : dispiro
		widths.lhs
		g4   (mt) (top - O) [heading {.y (-1) .x (-st)}]
		archv
		flat (left + (STROKE - fine) * HVCONTRAST) (top - SMALLSMOOTHA) [widths fine 0]
		curl (left + (STROKE - fine) * HVCONTRAST) (0 + SMALLSMOOTHB) [widths fine 0]
		arcvh
		g4   (mb) O [widths.heading STROKE 0 {.y (1) .x (-sb)}]
		archv
		[if ((SMALLSMOOTHA + SMALLSMOOTHB) / top > 0.75) flat.ai flat] (RIGHTSB - OX) (0 + SMALLSMOOTHA)
		[if ((SMALLSMOOTHA + SMALLSMOOTHB) / top > 0.75) curl.ai curl] (RIGHTSB - OX) (top - SMALLSMOOTHB)
		arcvh
		close

define [OBarRightShape top right] : glyph-construction
	include : create-glyph [OBarLeftShape top (WIDTH - [fallback right RIGHTSB])]
	include : FlipAround MIDDLE ([fallback top XH] / 2)

define SERIF_SHIFT_X 0.6
define [LeftwardTopSerif x y length _sw] : glyph-construction
	local sw : fallback _sw STROKE
	include : dispiro
		flat (x + HALFSTROKE * HVCONTRAST) y [widths.heading sw 0 LEFTWARD]
		curl (x - length - TANSLANT * (sw * SERIF_SHIFT_X)) y

define [LeftwardBottomSerif x y length _sw] : glyph-construction
	local sw : fallback _sw STROKE
	include : dispiro
		flat (x + HALFSTROKE * HVCONTRAST) y [widths.heading 0 sw LEFTWARD]
		curl (x - length + TANSLANT * (sw * SERIF_SHIFT_X)) y

define [RightwardTopSerif x y length _sw] : glyph-construction
	local sw : fallback _sw STROKE
	include : dispiro
		flat (x - HALFSTROKE * HVCONTRAST) y [widths.heading 0 sw RIGHTWARD]
		curl (x + length - TANSLANT * (sw * SERIF_SHIFT_X)) y

define [RightwardBottomSerif x y length _sw] : glyph-construction
	local sw : fallback _sw STROKE
	include : dispiro
		flat (x - HALFSTROKE * HVCONTRAST) y [widths.heading sw 0 RIGHTWARD]
		curl (x + length + TANSLANT * (sw * SERIF_SHIFT_X)) y

define [CenterTopSerif x y length _sw] : glyph-construction
	local sw : fallback _sw STROKE
	include : dispiro
		flat (x + length - TANSLANT * (sw * SERIF_SHIFT_X)) y [widths sw 0]
		curl (x - length - TANSLANT * (sw * SERIF_SHIFT_X)) y

define [CenterBottomSerif x y length _sw] : glyph-construction
	local sw : fallback _sw STROKE
	include : dispiro
		flat (x + length + TANSLANT * (sw * SERIF_SHIFT_X)) y [widths 0 sw]
		curl (x - length + TANSLANT * (sw * SERIF_SHIFT_X)) y

define [DownwardRightSerif x y length sw] : glyph-construction
	include : dispiro
		widths.rhs sw
		flat x y [heading DOWNWARD]
		curl x (y - length) [heading DOWNWARD]
define [UpwardRightSerif x y length sw] : glyph-construction
	include : dispiro
		widths.lhs sw
		flat x y [heading UPWARD]
		curl x (y + length) [heading UPWARD]
define [DownwardLeftSerif x y length sw] : glyph-construction
	include : dispiro
		widths.lhs sw
		flat x y [heading DOWNWARD]
		curl x (y - length) [heading DOWNWARD]
define [UpwardLeftSerif x y length sw] : glyph-construction
	include : dispiro
		widths.rhs sw
		flat x y [heading UPWARD]
		curl x (y + length) [heading UPWARD]

define sideSerifK 0.5
define [AIVSerifs top _left _right] : glyph-construction
	local left : fallback _left SB
	local right : fallback _right RIGHTSB
	if SLAB : begin
		include : CenterTopSerif (left + STROKE * sideSerifK * HVCONTRAST) top JUT
		tag-contour 'serifLT'
		include : CenterTopSerif (right - STROKE * sideSerifK * HVCONTRAST) top JUT
		tag-contour 'serifRT'
define [AIHSerifs top _left _right] : glyph-construction
	local left : fallback _left SB
	local right : fallback _right RIGHTSB
	if SLAB : begin
		include : AIVSerifs top _left _right
		include : CenterBottomSerif (left + STROKE * sideSerifK * HVCONTRAST) 0 JUT
		include : CenterBottomSerif (right - STROKE * sideSerifK * HVCONTRAST) 0 JUT
define [AINSerifs top _left _right sw xn] : glyph-construction
	local left : fallback _left SB
	local right : fallback _right RIGHTSB
	local jut : JUT * [fallback xn 1]
	if SLAB : begin
		include : LeftwardTopSerif (left + sw * (sideSerifK - 0.5) * HVCONTRAST) top (jut - sw / 2 * HVCONTRAST)
		include : CenterTopSerif (right - sw * sideSerifK * HVCONTRAST) top jut
		include : CenterBottomSerif (left + sw * sideSerifK * HVCONTRAST) 0 jut
		tag-contour 'serifLB'
		#include : CenterdBottomSerif (right - STROKE * (sideSerifK - 0.5) * HVCONTRAST) 0 (JUT / 2)
define [AICyrISerifs top _left _right] : glyph-construction
	local left : fallback _left SB
	local right : fallback _right RIGHTSB
	if SLAB : begin
		include : LeftwardBottomSerif left 0 SIDEJUT
		include : RightwardTopSerif right top SIDEJUT
		include : CenterTopSerif (left + STROKE * sideSerifK * HVCONTRAST) top JUT
		include : CenterBottomSerif (right - STROKE * sideSerifK * HVCONTRAST) 0 JUT
		tag-contour 'serifRB'
define [AIMSerifs top _left _right] : glyph-construction
	local left : fallback _left SB
	local right : fallback _right RIGHTSB
	if SLAB : begin
		include : LeftwardTopSerif (left + STROKE * (sideSerifK - 0.5) * HVCONTRAST) top SIDEJUT
		include : RightwardTopSerif (right - STROKE * (sideSerifK - 0.5) * HVCONTRAST) top SIDEJUT
		include : CenterBottomSerif (left + STROKE * sideSerifK * HVCONTRAST) 0 JUT
		include : CenterBottomSerif (right - STROKE * sideSerifK * HVCONTRAST) 0 JUT


define [halfXStrand _leftx lefty rightx righty turn straight tension _fine] : glyph-construction
	local leftx : _leftx + (HALFSTROKE * HVCONTRAST * [if (rightx > _leftx) 1 (-1)])
	local fine  : (_fine || STROKE) * 0.5
	
	local turnyleft : mix lefty righty turn
	local cyleft : mix turnyleft righty tension
	
	local straightxleft : mix leftx rightx straight
	local straightyleft : mix cyleft righty straight
	
	include : dispiro
		widths.center
		flat leftx lefty [heading [if (lefty < righty) UPWARD DOWNWARD]]
		curl leftx turnyleft [heading [if (lefty < righty) UPWARD DOWNWARD]]
		quadcontrols 0 ((cyleft - turnyleft) / (straightyleft - turnyleft)) 24
		flat straightxleft straightyleft
		curl rightx righty
		end [function : set this.cleanmore true]


define [xStrand _leftx lefty _rightx righty turn straight tension] : glyph-construction
	local middlex : mix _leftx _rightx 0.5
	local middley : mix lefty righty 0.5
	
	include : halfXStrand _leftx lefty middlex middley turn straight tension
	include : halfXStrand _rightx righty middlex middley turn straight tension

define [nShoulderKnots] : params [left right [fine SHOULDERFINE] [top XH] [bottom 0] [sma SMALLSMOOTHA] [smb SMALLSMOOTHB] [stroke STROKE]] : begin
	local slope : shoulderMidSlope fine stroke
	local middle : [mix (left - stroke * HVCONTRAST) right 0.5] + (slope - CORRECTION_OMIDX) * stroke
	return : list
		flat left (top - sma - 2) [widths fine 0]
		curl left (top - sma)
		arcvh
		g4   middle (top - O) [widths.heading 0 stroke {.y (1) .x (slope)}]
		archv
		flat right (top - smb)
		curl right bottom [heading DOWNWARD]

define [nShoulder] : begin
	local a arguments
	glyph-construction
		include : dispiro : nShoulderKnots.apply null a


define [mShoulderSpiro] : params [left right top bottom width fine] : glyph-construction
	local fix : TANSLANT * STROKE * HVCONTRAST * width / STROKE
	local sm : SMALLSMOOTH * 0.75
	include : spiro-outline
		corner (right - width * HVCONTRAST) bottom
		curl   (right - width * HVCONTRAST) (top - sm + fix)
		arcvh 8 'no-tiny'
		g2     [mix left (right - width * HVCONTRAST) 0.5] (top - O - width)
		archv 8 'no-tiny'
		flat   left (top - sm - fix)
		corner left (top - sm - fix - 1)
		corner (left - fine) (top - sm - 1)
		curl   (left - fine) (top - sm)
		arcvh 8 'no-tiny'
		g2     [mix (left - fine * HVCONTRAST) right 0.5] (top - O)
		archv 8 'no-tiny'
		flat   right (top - sm)
		corner right bottom
		close

define [HBar xleft xright y _fine] : glyph-construction
	include : dispiro
		widths.center [fallback _fine STROKE]
		flat xleft y [heading RIGHTWARD]
		curl xright y [heading RIGHTWARD]

define [HBarTop xl xr y _fine] : HBar xl xr (y - [fallback _fine STROKE] * 0.5) _fine
define [HBarBottom xl xr y _fine] : HBar xl xr (y + [fallback _fine STROKE] * 0.5) _fine
define [HOverlayBar xleft xright y s] : dispiro
	widths.center [fallback s OVERLAYSTROKE]
	flat xleft y
	curl xright y
define [VBar x ydown yup _fine] : glyph-construction
	local fine : fallback _fine STROKE
	include : dispiro
		widths.center fine
		flat x ydown [heading [if (ydown < yup) UPWARD DOWNWARD]]
		curl x yup [heading [if (ydown < yup) UPWARD DOWNWARD]]

define [VBarLeft x yd yu _fine] : VBar (x + [fallback _fine STROKE] * 0.5 * HVCONTRAST) yd yu _fine
define [VBarRight x yd yu _fine] : VBar (x - [fallback _fine STROKE] * 0.5 * HVCONTRAST) yd yu _fine

define [VerticalHook x y extend depth fine strg] : glyph-construction
	include : dispiro
		widths.center [fallback fine STROKE]
		flat x (y + [fallback strg 0]) [heading [if (depth > 0) DOWNWARD UPWARD]]
		curl x (y - [if (depth > 0) 0.01 (-0.01)]) [heading [if (depth > 0) DOWNWARD UPWARD]]
		arcvh
		flat (x + extend - [if (extend > 0) 0.01 (-0.01)]) (y - depth)
		curl (x + extend) (y - depth)

define [LegShape] : params [[ztop nothing (xt <> top)] [zbot nothing (xs <> bottom)] xb [fine STROKE]] : glyph-construction
	include : dispiro
		widths.lhs fine
		flat xt top [heading DOWNWARD]
		curl xb (bottom + LONGJUT)
		alsothruthem {{0.5 0.94}}
		g4.left.end xs (bottom + fine) [heading LEFTWARD]

define [LeftHook x y xextend] : glyph-construction
	local fine : adviceBlackness 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.15) ([adviceBlackness 4.25] * 1.5)]

define [HooktopLeftBar stroke bottom] : glyph-construction
	include : dispiro
		widths.lhs [fallback stroke STROKE]
		g4 RIGHTSB (CAP - HOOK)
		hookstart CAPO
		flat SB (CAP - SMALLSMOOTHA)
		curl SB [fallback bottom 0] [heading DOWNWARD]

define [CurlyTail] : params [fine rinner xleft bottom right x2 y2 [adj 0.4] [adj2 0.4] [adj3 0]] : begin
	local ltr : right > xleft
	set right : right - fine * [if ltr 1 (-1)]
	local mid : mix [mix xleft right 0.5] (right - rinner * [if ltr 1 (-1)]) adj
	local midu : mix [mix xleft right 0.5] (right - rinner * [if ltr 1 (-1)]) adj2
	return : list
		g4.[if ltr 'right' 'left'].mid (mid + CORRECTION_OMIDX * fine * adj3 * [if ltr 1 (-1)]) (bottom + fine + O) [widths [if ltr 0 fine] [if ltr fine 0]]
		archv 2
		g4   right (bottom + fine + rinner - 0.1)
		g4   right (bottom + fine + rinner + 0.1)
		arcvh 2
		g4   mid (bottom + fine + rinner * 2 - O)
		alsothruthem {{0.25 0.06} {0.52 0.25}} important
		g4   x2 y2

define [HCurlyTail fine wide rinner left m1 _right x1 x2 y2] : glyph-construction
	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

define [FlatSlashShape middlex middle fine kx ky] : glyph-construction
	include : dispiro
		flat (middlex - LONGJUT * [fallback kx 0.8]) (middle - LONGJUT * [fallback ky 0.4]) [widths fine fine]
		curl (middlex + LONGJUT * [fallback kx 0.8]) (middle + LONGJUT * [fallback ky 0.4])

# Spiro shapes
define [determineMixR w v u sw] : begin
	local r : piecewise
		(w <= v)   0.5
		true     : 1 / ([Math.pow (1 - [Math.pow (1 - v / w) SUPERNESS]) (1 / SUPERNESS)] + 1)
	local idepth : w - sw
	local iwidth : u * r - sw
	if (iwidth > 0 && idepth > 0 && iwidth / idepth >= 2) : begin
		local adjust : clamp 0.975 1 (1 - (iwidth / idepth - 2) * 0.0125)
		#console.log iwidth idepth (iwidth / idepth) adjust
		r = r * adjust
	if (r < 0.5) : set r 0.5
	return r

define nHookSegments 12
define [HookShape toStraight toFinish isStart y tight s kkaf dontadjust] : begin
	local atBottom : toStraight.y > y
	local sw : fallback s STROKE
	local ltr : if isStart (toFinish.x < toStraight.x) (toFinish.x > toStraight.x)
	local dtu : if isStart (y > toFinish.y) (y < toFinish.y)
	
	if [not dontadjust] : begin
		toFinish.x = toFinish.x + OXHOOK * [if ltr (-1) 1] * [if isStart (-1) 1]
		if (atBottom && ltr && !isStart) : begin
			toFinish.x = toFinish.x + TAILADJX * TANSLANT
			toFinish.y = toFinish.y - TAILADJY * TANSLANT

	local w : Math.abs (toStraight.y - y)
	local v : Math.abs (toFinish.y - y)
	local u : Math.abs (toFinish.x - toStraight.x)
	local mixr : determineMixR w v u sw
	local mx ([mix toStraight.x toFinish.x mixr] + ([if (tight && tight.shift) tight.shift (1 - (tight || 0))] * [if atBottom 1 (-1)] * CORRECTION_OMIDX) * sw)
	local keyKnot : g4.[if ltr "right" "left"].mid mx y [fallback kkaf : if tight [let [s : if ltr RIGHTWARD LEFTWARD] [heading {.x (s.x * [fallback tight.skew 1]) .y s.y}]] nothing]
	
	local faf toFinish.af
	set toFinish.af : lambda [] : begin
		local rad : Math.min w (mixr * u)
		local skew0 : [clamp 0 w (w - v)] / rad + ([clamp 1 1.5 (mixr * u / w)] - 1) * 0.5
		local depth : v + skew0 * sw - sw
		local shallowLimit (sw * 0.5)
		local skew : clamp 0 (1 / 2) : skew0 + [clamp 0 shallowLimit (shallowLimit - depth)] / rad
		if faf : faf.apply this arguments
		this.heads-to {
			.x (CONTRAST / [Math.sqrt : 1 + skew * skew] * [if dtu (-1) 1])
			.y (skew / [Math.sqrt : 1 + skew * skew] * [if ltr 1 (-1)])
		}
	
	local segBefore {}
	local segAfter {}
	foreach [j : range 1 nHookSegments] : begin
		local fraction : j / nHookSegments
		local fractionAfter : fraction * (1 - mixr) / mixr
		local myfinal : superxy ((1 - mixr) / mixr)
		segBefore.push : g4 [mix mx toStraight.x fraction] [mix y toStraight.y (1 - [superxy fraction])] unimportant
		segAfter.push : g4 [mix mx toFinish.x fraction] [mix y toFinish.y ((1 - [superxy fractionAfter]) / (1 - myfinal))] unimportant
		if (!tight && w < u * mixr) : set segAfter {}
	if isStart
	: then : return : list
		segAfter.reverse
		* keyKnot
		* segBefore
	: else : return : list
		segBefore.reverse
		* keyKnot
		* segAfter

define [hookstart] : params [y tight sw kkaf dontadjust] : return {
	.type 'interpolate'
	.af [lambda [before after] [HookShape after before true y tight sw kkaf dontadjust]]
}
define [hookend] : params [y tight sw kkaf dontadjust] : return {
	.type 'interpolate'
	.af [lambda [before after] [HookShape before after false y tight sw kkaf dontadjust]]
}

define [WaveShape] : params [l r cy extendy tension sw] : glyph-construction
	local cx : mix l r 0.5
	local wavex : (r - l) * tension
	local endwavey : extendy * 0.97
	include : dispiro
		widths.center sw
		g4 l (cy - endwavey)
		bezcontrols.absolute (l + wavex) (cy + extendy) (cx - wavex * 0.8) (cy + extendy) 8 important
		g4 cx cy
		bezcontrols.absolute (cx + wavex * 0.8) (cy - extendy) (r - wavex) (cy - extendy) 8 important
		g4 r (cy + endwavey)

define [CyrDescender x shift connex] : glyph-construction
	local descenderOverflow : if SLAB SIDEJUT ((RIGHTSB - SB) * [fallback shift 0.1])
	include : VBarRight (x + descenderOverflow + 0.25 * STROKE) (HALFSTROKE - LONGJUT) STROKE
	if (!SLAB && descenderOverflow > STROKE * 0.75 || connex) : include : HBarTop (x - HALFSTROKE * HVCONTRAST) (x + descenderOverflow) STROKE

# Derived subfonts
define [refair g] : begin
	foreach [j : range 0 g.contours.length] : begin
		set g.contours.(j) : fairify g.contours.(j) globalTransform g.dense
	return nothing
define [Fork gs ps] : begin
	# BFS construct ShouldBuildList
	local sbh {.}
	local found true
	local PENDING 1
	local CHECKED 2
	foreach [glyphid : items-of gs] : set sbh.(glyphid) PENDING
	while found : begin
		set found false
		foreach [glyphid : items-of : Object.keys sbh] : if (sbh.(glyphid) === PENDING) : begin
			set sbh.(glyphid) CHECKED
			if dependencyProfile.(glyphid) : foreach [k : items-of dependencyProfile.(glyphid)] : if [not sbh.(k)] : begin
				set sbh.(k) PENDING
				set found true
	
	local shouldBuildList : Object.keys sbh :.filter ([x] => [not [not x]])
	#console.log shouldBuildList
	local shouldBuildUnicodes : shouldBuildList.map ([x] => [if (glyphs.(x) && glyphs.(x).unicode) glyphs.(x).unicode.0 nothing])
		:.filter ([x] => [not [not x]])
	
	local p : Object.create ps
	try : begin
		local forkFont : buildFont.call [TempFont] p shouldBuildList shouldBuildUnicodes
	: ex
	: begin
		if ex.glyfMap : return ex.glyfMap
		: else : throw ex
	return forkFont.glyfMap

define [Miniature] : params [glyphs crowd scale [slantAngle para.slantAngle] unfair [sbscale 0.5]] : begin
	local forkedPara : Object.create para
	forkedPara.stroke = [adviceBlackness crowd] / scale
	forkedPara.ess = para.ess * forkedPara.stroke / para.stroke
	forkedPara.sb = SB * sbscale
	forkedPara.slantAngle = slantAngle
	forkedPara.unfair = unfair
	return : Fork glyphs forkedPara

define [Thinner glyphs p] : begin
	local forkedPara : Object.create para
	forkedPara.width = WIDTH * p
	forkedPara.accentx = ACCENTX * p
	forkedPara.jut = JUT * p
	forkedPara.longjut = LONGJUT * p
	#forkedPara.hookx = HOOKX * p
	return : Fork glyphs forkedPara

define [Widen glyphs p psb] : begin
	local forkedPara : Object.create para
	forkedPara.width = WIDTH * p
	forkedPara.sb = SB * [fallback psb p]
	forkedPara.accentx = ACCENTX * p
	forkedPara.jut = JUT * p
	forkedPara.longjut = LONGJUT * p
	forkedPara.hookx = HOOKX * p
	forkedPara.smoothadjust = para.smoothadjust * p
	return : Fork glyphs forkedPara

# Composite transformations
define [FlipAround x y sx sy] : glyph-construction
	apply-transform : Upright
	apply-transform : Translate (-x) (-y)
	apply-transform : Scale [fallback sx (-1)] [fallback sy sx (-1)]
	apply-transform : Translate x y
	apply-transform : Italify