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

import [mix linreg clamp fallback] from "@iosevka/util"
import [MathSansSerif DependentSelector] from "@iosevka/glyph/relation"

glyph-module

glyph-block Letter-Latin-Upper-H : begin
	glyph-block-import CommonShapes
	glyph-block-import Common-Derivatives
	glyph-block-import Mark-Shared-Metrics : markExtend
	glyph-block-import Mark-Adjustment : LeaningAnchor
	glyph-block-import Mark-Below : belowMarkMid
	glyph-block-import Letter-Blackboard : BBS BBD
	glyph-block-import Letter-Shared : SetGrekUpperTonos
	glyph-block-import Letter-Shared : CreateSelectorVariants DefineSelectorGlyph
	glyph-block-import Letter-Shared-Shapes : SerifFrame RightwardTailedBar
	glyph-block-import Letter-Shared-Shapes : LeftHook MidHook EngHook UpwardHookShape
	glyph-block-import Letter-Shared-Shapes : CyrDescender CyrTailDescender PalatalHook
	glyph-block-import Letter-Latin-Upper-F : xMidBarShrink

	define SLAB-NONE                   0
	define SLAB-TOP-LEFT               1
	define SLAB-TOP-LEFT-BOTTOM-RIGHT  2
	define SLAB-TAILED-CYRILLIC        3
	define SLAB-ALL                    4
	define SLAB-ALL-BGR                5
	define SLAB-TAILED-CYRILLIC-BGR    6

	define [HSerifs slabType t b l r sw] : begin
		local sf : SerifFrame t b l r (swRef -- [fallback sw Stroke])
		return : match slabType
			[Just SLAB-NONE] : glyph-proc
			[Just SLAB-TOP-LEFT] : begin sf.lt.outer
			[Just SLAB-TOP-LEFT-BOTTOM-RIGHT] : composite-proc sf.lt.outer sf.rb.outer
			[Just SLAB-TAILED-CYRILLIC] : composite-proc sf.lt.full sf.rt.full sf.lb.full
			[Just SLAB-ALL] : composite-proc sf.lt.full sf.rt.full sf.lb.full sf.rb.full
			[Just SLAB-ALL-BGR] : composite-proc sf.lt.outer sf.rt.inner sf.lb.full sf.rb.full
			[Just SLAB-TAILED-CYRILLIC-BGR] : composite-proc sf.lt.outer sf.rt.inner sf.lb.full

	define [LeftHalfHSerifs slabType t b l r sw] : begin
		local sf : SerifFrame t b l r (swRef -- [fallback sw Stroke])
		return : match slabType
			[Just SLAB-NONE] : glyph-proc
			[Just SLAB-TOP-LEFT] : begin sf.lt.outer
			[Just SLAB-TOP-LEFT-BOTTOM-RIGHT] : begin sf.lt.outer
			[Just SLAB-TAILED-CYRILLIC] : composite-proc sf.lt.fullSide sf.lb.fullSide
			[Just SLAB-ALL] : composite-proc sf.lt.fullSide sf.lb.fullSide
			[Just SLAB-ALL-BGR] : composite-proc sf.lt.outer sf.lb.fullSide
			[Just SLAB-TAILED-CYRILLIC-BGR] : composite-proc sf.lt.outer sf.lb.fullSide

	define [RightHalfHSerifs slabType t b l r sw] : begin
		local sf : SerifFrame t b l r (swRef -- [fallback sw Stroke])
		return : match slabType
			[Just SLAB-NONE] : glyph-proc
			[Just SLAB-TOP-LEFT] : glyph-proc
			[Just SLAB-TOP-LEFT-BOTTOM-RIGHT] : begin sf.rb.outer
			[Just SLAB-TAILED-CYRILLIC] : begin sf.rt.fullSide
			[Just SLAB-ALL] : composite-proc sf.rt.fullSide sf.rb.fullSide
			[Just SLAB-ALL-BGR] : composite-proc sf.rt.inner sf.rb.fullSide
			[Just SLAB-TAILED-CYRILLIC-BGR] : begin sf.rt.inner

	define [TurnedHSerifs slabType t b l r sw] : begin
		local sf : SerifFrame t b l r (swRef -- [fallback sw Stroke])
		return : match slabType
			[Just SLAB-NONE] : glyph-proc
			[Just SLAB-TOP-LEFT] : begin sf.lt.outer
			[Just SLAB-TOP-LEFT-BOTTOM-RIGHT] : composite-proc sf.lt.outer sf.rb.outer
			[Just SLAB-TAILED-CYRILLIC] : composite-proc sf.lt.full sf.rt.full
			[Just SLAB-ALL] : composite-proc sf.lt.full sf.rt.full sf.rb.fullSide
			[Just SLAB-ALL-BGR] : composite-proc sf.lt.outer sf.rt.inner sf.rb.fullSide
			[Just SLAB-TAILED-CYRILLIC-BGR] : composite-proc sf.lt.outer sf.rt.inner

	define [HShape l r top _sw] : glyph-proc
		local sw : fallback _sw Stroke
		include : tagged 'strokeL' : VBar.l l 0 top sw
		include : tagged 'strokeR' : VBar.r r 0 top sw
		include : HBar.m (l - O) (r + O) (top * HBarPos) sw

	define [TurnedHShape l r top _sw] : glyph-proc
		local sw : fallback _sw Stroke
		include : LeaningAnchor.Below.VBar.r r
		include : tagged 'strokeL' : VBar.l l (top * HBarPos - sw / 2) top sw
		include : tagged 'strokeR' : VBar.r r 0 top sw
		include : HBar.m (l - O) (r + O) (top * HBarPos) sw

	define [LeftHalfHShape l r top _sw] : glyph-proc
		local sw : fallback _sw Stroke
		include : LeaningAnchor.Above.VBar.l l
		include : LeaningAnchor.Below.VBar.l l
		include : tagged 'strokeL' : VBar.l l 0 top sw
		include : HBar.m (l - O) r (top * HBarPos) sw

	define [RightHalfHShape l r top _sw] : glyph-proc
		local sw : fallback _sw Stroke
		include : LeaningAnchor.Above.VBar.r r
		include : LeaningAnchor.Below.VBar.r r
		include : tagged 'strokeR' : VBar.r r 0 top sw
		include : HBar.m l (r + O) (top * HBarPos) sw

	define [TailedHShape l r top _sw] : glyph-proc
		local sw : fallback _sw Stroke
		include : tagged 'strokeL' : VBar.l l 0 top sw
		include : tagged 'strokeR' : RightwardTailedBar r 0 top (sw -- sw)
		include : HBar.m (l - O) (r + O) (top * HBarPos) sw

	define [EnGheShape Body df top slabType vSlab] : glyph-proc
		local sw : AdviceStroke 2.75
		local xm : Math.min (Width - df.leftSB) : if SLAB
			[mix df.leftSB df.rightSB 0.625] + [HSwToV : 0.25 * df.mvs]
			mix df.leftSB df.rightSB : if (df.adws > 1) (2 / 3) (3 / 4)
		local xTopBarRightEnd : mix df.width df.rightSB : if vSlab 0.25 0.375

		include : Body df.leftSB xm top sw
		include : HBar.t (xm + O) xTopBarRightEnd top

		include : HSerifs slabType top 0 df.leftSB xm sw
		if vSlab
			then : include : VSerif.dr xTopBarRightEnd top VJut [VSwToH df.mvs]
			else : eject-contour 'serifRT'

	define [HwairShape df top yend slabType] : glyph-proc
		include : VBar.l df.leftSB 0 top df.mvs
		include : HBar.m SB df.middle (top / 2)
		include : UpwardHookShape
			left   -- (df.middle - [HSwToV : 0.5 * df.mvs])
			right  -- df.rightSB
			ybegin -- top
			yend   -- yend
			ada    -- (SmallArchDepthA * 0.6 * df.adws)
			adb    -- (SmallArchDepthB * 0.6 * df.adws)
			sw     -- df.mvs
		include : HSerifs slabType top 0 df.leftSB (df.middle + [HSwToV : 0.5 * df.mvs]) df.mvs

		local sf2 : [SerifFrame.fromDf df yend 0].slice 1 2
		if SLAB : include sf2.rt.full

	define [OverlayStrokeShape top slabType] : begin
		local yb : top * HBarPos + HalfStroke
		local yt : top - [if slabType Stroke 0]
		return : HOverlayBar [mix SB 0 0.7] [mix RightSB Width 0.7]
			mix yb yt 0.5
			Math.min OverlayStroke : 0.625 * (yt - yb)

	define HConfig : object
		serifless                        { HShape       TurnedHShape LeftHalfHShape RightHalfHShape SLAB-NONE                  }
		tailedSerifless                  { TailedHShape TurnedHShape LeftHalfHShape RightHalfHShape SLAB-NONE                  }
		topLeftSerifed                   { HShape       TurnedHShape LeftHalfHShape RightHalfHShape SLAB-TOP-LEFT              }
		tailedTopLeftSerifed             { TailedHShape TurnedHShape LeftHalfHShape RightHalfHShape SLAB-TOP-LEFT              }
		topLeftBottomRightSerifed        { HShape       TurnedHShape LeftHalfHShape RightHalfHShape SLAB-TOP-LEFT-BOTTOM-RIGHT }
		serifed                          { HShape       TurnedHShape LeftHalfHShape RightHalfHShape SLAB-ALL                   }
		tailedSerifed                    { TailedHShape TurnedHShape LeftHalfHShape RightHalfHShape SLAB-TAILED-CYRILLIC       }
		serifedExceptBottomRight         { HShape       TurnedHShape LeftHalfHShape RightHalfHShape SLAB-TAILED-CYRILLIC       }
		serifedBGR                       { HShape       TurnedHShape LeftHalfHShape RightHalfHShape SLAB-ALL-BGR               }
		tailedSerifedBGR                 { TailedHShape TurnedHShape LeftHalfHShape RightHalfHShape SLAB-TAILED-CYRILLIC-BGR   }

	define EnGheGheConfig : object
		serifless       false
		topRightSerifed true

	foreach { suffix { Body TurnedBody LeftHalfBody RightHalfBody slabType } } [Object.entries HConfig] : do
		create-glyph "H.\(suffix)" : glyph-proc
			include : MarkSet.capital
			include : Body SB RightSB  CAP
			include : HSerifs slabType CAP 0 SB RightSB

		create-glyph "grek/Eta.\(suffix)" : glyph-proc
			include [refer-glyph "H.\(suffix)"] AS_BASE ALSO_METRICS
			include : SetGrekUpperTonos [if (slabType === SLAB-NONE) 0 (-SideJut)]

		create-glyph "HTurned.\(suffix)" : glyph-proc
			include : MarkSet.capital
			include : TurnedBody SB RightSB  CAP
			include : TurnedHSerifs slabType CAP 0 SB RightSB

		create-glyph "smcpH.\(suffix)" : glyph-proc
			include : MarkSet.e
			include : Body SB RightSB  XH
			include : HSerifs slabType XH 0 SB RightSB

		create-glyph "leftHalfH.\(suffix)" : glyph-proc
			include : MarkSet.capital
			local xMockLeft : SB * 1.5
			local xMockRight : RightSB - [xMidBarShrink (slabType === SLAB-ALL)]
			local shift : Math.abs : Middle - [mix (xMockLeft - [if (slabType === SLAB-NONE) 0 SideJut]) xMockRight 0.5]
			local xLeft : xMockLeft + shift
			local xRight : xMockRight + shift
			include : LeftHalfBody xLeft xRight CAP
			include : LeftHalfHSerifs slabType CAP 0 xLeft xRight

		create-glyph "rightHalfH.\(suffix)" : glyph-proc
			include : MarkSet.capital
			local xMockLeft : SB + [xMidBarShrink (slabType === SLAB-ALL)]
			local xMockRight : Width - SB * 1.5
			local shift : Math.abs : Middle - [mix xMockLeft (xMockRight + [if (slabType === SLAB-NONE) 0 SideJut]) 0.5]
			local xLeft : xMockLeft - shift
			local xRight : xMockRight - shift
			include : RightHalfBody xLeft xRight CAP
			include : RightHalfHSerifs slabType CAP 0 xLeft xRight

		create-glyph "leftHalfSmcpH.\(suffix)" : glyph-proc
			include : MarkSet.e
			local xMockLeft : SB * 1.5
			local xMockRight : RightSB - [xMidBarShrink (slabType === SLAB-ALL)]
			local shift : Math.abs : Middle - [mix (xMockLeft - [if (slabType === SLAB-NONE) 0 SideJut]) xMockRight 0.5]
			local xLeft : xMockLeft + shift
			local xRight : xMockRight + shift
			include : LeftHalfBody xLeft xRight XH
			include : LeftHalfHSerifs slabType XH 0 xLeft xRight

		create-glyph "rightHalfSmcpH.\(suffix)" : glyph-proc
			include : MarkSet.e
			local xMockLeft : SB + [xMidBarShrink (slabType === SLAB-ALL)]
			local xMockRight : Width - SB * 1.5
			local shift : Math.abs : Middle - [mix xMockLeft (xMockRight + [if (slabType === SLAB-NONE) 0 SideJut]) 0.5]
			local xLeft : xMockLeft - shift
			local xRight : xMockRight - shift
			include : RightHalfBody xLeft xRight XH
			include : RightHalfHSerifs slabType XH 0 xLeft xRight

		define enGheDf : DivFrame para.advanceScaleM 3

		DefineSelectorGlyph "cyrl/EnGhe" suffix enGheDf 'capital'
		DefineSelectorGlyph "cyrl/enghe" suffix enGheDf 'e'

		foreach { suffixGhe enGheVSlab } [Object.entries EnGheGheConfig] : do
			create-glyph "cyrl/EnGhe.\(suffix).\(suffixGhe)" : glyph-proc
				set-width 0
				set-mark-anchor 'cvDecompose' 0 0
				include : EnGheShape Body enGheDf CAP slabType enGheVSlab

			create-glyph "cyrl/enghe.\(suffix).\(suffixGhe)" : glyph-proc
				set-width 0
				set-mark-anchor 'cvDecompose' 0 0
				include : EnGheShape Body enGheDf XH slabType enGheVSlab

		select-variant "cyrl/EnGhe.\(suffix)" (follow -- 'cyrl/EnGhe/GhePart')
		select-variant "cyrl/enghe.\(suffix)" (follow -- 'cyrl/enghe/ghePart')

		create-glyph "Hwair.\(suffix)" : glyph-proc
			local df : include : DivFrame para.advanceScaleMM 3
			include : df.markSet.capital
			include : HwairShape df CAP XH slabType

		create-glyph "cyrl/NjeKomi.\(suffix)" : glyph-proc
			local df : include : DivFrame para.advanceScaleMM 3
			include : df.markSet.capital
			include : HwairShape df CAP (CAP / 2 + HalfStroke) slabType

		create-glyph "cyrl/njeKomi.\(suffix)" : glyph-proc
			local df : include : DivFrame para.advanceScaleMM 3
			include : df.markSet.e
			include : HwairShape df XH (XH / 2 + HalfStroke) slabType

		create-glyph "HHookTop.\(suffix)" : glyph-proc
			include [refer-glyph "H.\(suffix)"] AS_BASE ALSO_METRICS
			eject-contour "serifLT"
			include : LeftHook SB CAP

		create-glyph "HStroke.\(suffix)" : glyph-proc
			include [refer-glyph "H.\(suffix)"] AS_BASE ALSO_METRICS
			include : OverlayStrokeShape CAP slabType

		create-glyph "smcpHStroke.\(suffix)" : glyph-proc
			include [refer-glyph "smcpH.\(suffix)"] AS_BASE ALSO_METRICS
			include : OverlayStrokeShape XH slabType

		create-glyph "cyrl/EnMidHook.\(suffix)" : glyph-proc
			local df : include : DivFrame para.advanceScaleMM 3
			include : df.markSet.capDesc

			local xm : df.middle + [HSwToV : 0.5 * df.mvs]
			include : Body df.leftSB xm CAP df.mvs
			include : difference
				HSerifs slabType CAP 0 df.leftSB xm df.mvs
				intersection
					MaskBelow Stroke
					MaskRight [mix xm (df.rightSB - [HSwToV df.mvs]) 0.625]
			include : MidHook.m df CAP

		create-glyph "cyrl/enMidHook.\(suffix)" : glyph-proc
			local df : include : DivFrame para.advanceScaleMM 3
			include : df.markSet.p

			local xm : df.middle + [HSwToV : 0.5 * df.mvs]
			include : Body df.leftSB xm XH df.mvs
			include : difference
				HSerifs slabType XH 0 df.leftSB xm df.mvs
				intersection
					MaskBelow Stroke
					MaskRight [mix xm (df.rightSB - [HSwToV df.mvs]) 0.625]
			include : MidHook.m df XH

	select-variant 'H' 'H'
	link-reduced-variant 'H/sansSerif' 'H' MathSansSerif
	select-variant 'H/descBase' (shapeFrom -- 'H')
	select-variant 'grek/Eta' 0x397 (follow -- 'H')
	select-variant 'HTurned' 0xA78D (follow -- 'H')
	link-reduced-variant 'grek/Eta/sansSerif' 'grek/Eta' MathSansSerif (follow -- 'H/sansSerif')
	select-variant 'cyrl/En' 0x41D (shapeFrom -- 'H')
	select-variant 'cyrl/En/descBase' (shapeFrom -- 'H')
	select-variant 'leftHalfH' 0x2C75
	select-variant 'rightHalfH' 0xA7F5

	select-variant 'smcpH' 0x29C (follow -- 'H')
	select-variant 'leftHalfSmcpH' 0x2C76 (follow -- 'leftHalfH')
	select-variant 'rightHalfSmcpH' 0xA7F6 (follow -- 'rightHalfH')
	select-variant 'cyrl/en' 0x43D (shapeFrom -- 'smcpH')
	select-variant 'cyrl/en/descBase' (shapeFrom -- 'smcpH')
	select-variant 'cyrl/en.BGR' (shapeFrom -- 'smcpH')

	alias 'grek/Heta' 0x370 'leftHalfH'
	alias 'grek/heta' 0x371 : if SLAB 'leftHalfSmcpH.topLeftSerifed' 'leftHalfSmcpH.serifless'

	derive-composites 'HDescender' 0x2C67 'H/descBase' [CyrDescender.rSideJut RightSB 0]

	derive-composites 'cyrl/EnDescender' 0x4A2 'cyrl/En/descBase' [CyrDescender.rSideJut RightSB 0]
	derive-composites 'cyrl/enDescender' 0x4A3 'cyrl/en/descBase' [CyrDescender.rSideJut RightSB 0]

	derive-composites 'cyrl/EnTail' 0x4C9 'cyrl/En/descBase' [CyrTailDescender.rSideJut RightSB 0]
	derive-composites 'cyrl/enTail' 0x4CA 'cyrl/en/descBase' [CyrTailDescender.rSideJut RightSB 0]

	CreateSelectorVariants 'cyrl/EnGhe' 0x4A4 [Object.keys HConfig] (follow -- 'cyrl/En')
	CreateSelectorVariants 'cyrl/enghe' 0x4A5 [Object.keys HConfig] (follow -- 'cyrl/en')

	select-variant 'Hwair' 0x1F6
	select-variant 'HHookTop' 0xA7AA

	select-variant 'HStroke' 0x126 (follow -- 'H')
	select-variant 'smcpHStroke' (follow -- 'H')

	select-variant 'cyrl/EnMidHook' 0x0522 (follow -- 'cyrl/En')
	select-variant 'cyrl/enMidHook' 0x0523 (follow -- 'cyrl/en')

	select-variant 'cyrl/NjeKomi' 0x050A
	select-variant 'cyrl/njeKomi' 0x050B

	derive-glyphs 'HCedilla' 0x1E28 'H' : lambda [src gr] : glyph-proc
		local shift : Width + SB - Middle + [HSwToV HalfStroke]
		include [refer-glyph 'cedillaBelow']
		include : Translate shift 0
		include [refer-glyph src]
		include : MarkSet.capDesc
		set-base-anchor 'belowBraceL' ((-Middle) + shift - 0.5 * markExtend) belowMarkMid
		set-base-anchor 'belowBraceR' ((-Middle) + shift + 0.5 * markExtend) belowMarkMid

	define [DProcCapitalHeng src sel] : glyph-proc
		include : MarkSet.capDesc
		include : refer-glyph src
		eject-contour 'serifRB'
		include : EngHook RightSB 0 Descender

	define [DProcSmallHeng src sel] : glyph-proc
		include : MarkSet.p
		include : refer-glyph src
		eject-contour 'serifRB'
		include : EngHook RightSB 0 Descender

	derive-glyphs 'Heng' 0xA726 'H/descBase' DProcCapitalHeng
	derive-glyphs 'cyrl/EnHook' 0x4C7 'cyrl/En/descBase' DProcCapitalHeng
	derive-glyphs 'cyrl/enHook' 0x4C8 'cyrl/en/descBase' DProcSmallHeng

	derive-glyphs 'cyrl/EnHookLeft' 0x528 'cyrl/En' : lambda [src srl] : glyph-proc
		include [refer-glyph src] AS_BASE ALSO_METRICS
		eject-contour 'serifLB'
		include : PalatalHook.lExt SB 0

	derive-glyphs 'cyrl/enHookLeft' 0x529 'cyrl/en' : lambda [src srl] : glyph-proc
		include [refer-glyph src] AS_BASE ALSO_METRICS
		eject-contour 'serifLB'
		include : PalatalHook.lExt SB 0

	create-glyph 'mathbb/H' 0x210D : glyph-proc
		include : MarkSet.capital
		include : VBar.l SB 0 CAP BBS
		include : VBar.r RightSB 0 CAP BBS
		include : VBar.l (SB + BBD) 0 CAP BBS
		include : VBar.r (RightSB - BBD) 0 CAP BBS
		include : HBar.m (SB + BBD) (RightSB - BBD) (CAP * HBarPos) BBS
		include : HBar.t SB (SB + BBD) CAP BBS
		include : HBar.t (RightSB - BBD) RightSB CAP BBS
		include : HBar.b SB (SB + BBD) 0 BBS
		include : HBar.b (RightSB - BBD) RightSB 0 BBS
