###### Other symbols
$$include '../meta/macros.ptl'

import [mix clamp fallback] from "@iosevka/util"
import [Joining NeqLigationSlashDotted] from "@iosevka/glyph/relation"
import [DesignParameters] from "../meta/aesthetics.mjs"

glyph-module

glyph-block Symbol-Ligation : begin
	glyph-block-import CommonShapes
	glyph-block-import Common-Derivatives
	glyph-block-import Symbol-Math-Relation-Common : LessSlope EqualHalfSpace EqualHoleWidth
	glyph-block-import Symbol-Math-Relation-Equal : EqualShape EqualHole IdentShape IdentHole
	glyph-block-import Symbol-Math-Arith : PlusShape JunctDiamond

	local arrowheadsKern : (2 / 3) * [clamp 0 (Width * 0.4) (Width - OperatorStroke * 3)]

	define [SetJoiningKind lk rk] : glyph-proc
		local k 0
		if (lk !== 'f') : set k : k + Joining.Classes.Left
		if (rk !== 'f') : set k : k + Joining.Classes.Right
		Joining.set currentGlyph k

	define RodBarHGap : Math.max (Width / 8) [AdviceStroke 6]
	define RodBarHOffset : 0.5 * Width - [HSwToV HalfStroke] - RodBarHGap

	# Arrow parameters
	define arrowheadSlope : 1 / LessSlope

	local arrowExtend : clamp 0 Width (RightSB - 0.5 * OperatorStroke * arrowheadSlope)
	local arrowJ      : clamp 0 Width (SB + 0.5 * OperatorStroke * arrowheadSlope)

	local dblExtend : clamp 0 Width (RightSB - EqualHalfSpace * arrowheadSlope)
	local dblArrowJ : clamp 0 Width (SB + EqualHalfSpace * arrowheadSlope)

	define [HyphenNotch x] : union
		VBar.m x (SymbolMid + OperatorStroke / 3) (SymbolMid + OperatorStroke) EqualHoleWidth
		VBar.m x (SymbolMid - OperatorStroke / 3) (SymbolMid - OperatorStroke) EqualHoleWidth


	do "Arrow Bar"
		define [ArrowBarConfig extend kern join doubleBar] : begin
			define cleft   0
			define cright  Width
			define arrowr : if doubleBar
				Width + SB + [HSwToV OperatorStroke]
				Width + extend
			define arrowl : if doubleBar
				-Width + RightSB - [HSwToV OperatorStroke]
				0 - extend
			define zleft : cleft - Width + RightSB
			define zright : cright + SB

			define lk : object
				f   { SB                      false } # Free end
				x   { (SB - Width)            false } # !='s bar shape, extension to left
				y   { (-join - Width)         false } # -!-'s second bar, more to left
				l   { arrowl                  false } # <-
				l1  { (arrowl - kern)         false } # <<-
				lx  { [mix arrowl 0 0.5]      false } # Bar right after <!--'s exclam
				m   { (0 - RodBarHOffset)     false } # |-
				j   { (-join)                 false } # >-
				j1  { (-join - kern)          false } # >>-
				c   { cleft                   true  } # Connected rod
				z   { zleft                   true  } # Connected rod

			define rk : object
				f   { RightSB                 false } # Free end
				p   { (arrowr - Width)        false } # bar in :> when ">" is turned into an arrow
				r   { arrowr                  false } # ->
				r1  { (arrowr + kern)         false } # ->>
				m   { (Width + RodBarHOffset) false } # -|
				j   { (Width + join)          false } # -<
				j1  { (Width + join + kern)   false } # -<<
				c   { cright                  true  } # Connected rods
				z   { zright                  true  } # Connected rods

			define result {}
			foreach [l : items-of : Object.keys lk] : foreach [r : items-of : Object.keys rk]
				result.push { l r lk.(l) rk.(r) }
			return result

		define [HyphenShape l r] : HBar.m l r SymbolMid OperatorStroke
		define [HyphenShape.joinCap x] : JunctDiamond x SymbolMid OperatorStroke

		define Shapes : object
			'plus'   { PlusShape   HyphenNotch { arrowExtend arrowheadsKern arrowJ    0 } }
			'hyphen' { HyphenShape HyphenNotch { arrowExtend arrowheadsKern arrowJ    0 } }
			'equal'  { EqualShape  EqualHole   { dblExtend   arrowheadsKern dblArrowJ 1 } }
			'ident'  { IdentShape  IdentHole   { dblExtend   arrowheadsKern dblArrowJ 1 } }

		define NotchConfig : object
			'withoutNotch' { false }
			'withNotch'    { true  }

		foreach { prefix { Shape Notch { extend kern join fDB } } } [Object.entries Shapes] : do
			foreach { lS rS { left capLeft } { right capRight } } [items-of : ArrowBarConfig extend kern join fDB] : do
				foreach { suffix { fNotch } } [Object.entries NotchConfig] : do
					create-glyph "\(prefix).lig.\(lS)\(rS).\(suffix)" : glyph-proc
						include : SetJoiningKind lS rS
						include : difference
							union
								Shape left right
								if capLeft  [Shape.joinCap left]  [no-shape]
								if capRight [Shape.joinCap right] [no-shape]
							if (fNotch && left < (SB - Width))       [Notch (-Width)]    [no-shape]
							if (fNotch && left < SB)                 [Notch 0]           [no-shape]
							if (fNotch && right > RightSB)           [Notch Width]       [no-shape]
							if (fNotch && right > (RightSB + Width)) [Notch (2 * Width)] [no-shape]

				select-variant "\(prefix).lig.\(lS)\(rS)"
					follow -- "lig-\(prefix)"
				select-variant "\(prefix).arrowBar.\(lS)\(rS)"
					follow -- "lig-arrowBar-\(prefix)"
					shapeFrom -- "\(prefix).lig.\(lS)\(rS)"

	do "Waves"
		glyph-block-import Shared-Symbol-Shapes : CreateWaveShape
		define WaveShape : CreateWaveShape (EqualHalfSpace + 0.5 * OperatorStroke) OperatorStroke (-1 / 4)

		define LR  (2  / 32)
		define LR1 (9  / 32)
		define Z   (1  / 4)
		define F   (-1 / 4)
		define C   0
		define J   (-1 / 8)

		define lk : object
			l    { LR   (-arrowExtend)                           false }
			l1   { LR1  (-arrowExtend - arrowheadsKern)          false }
			f    { F    nothing                                  false }
			z    { Z    nothing                                  false }
			c    { C    nothing                                  false }
			m    { J    (0 - RodBarHOffset)                       true }
			j    { J    (-arrowJ)                                 true }
			j1   { J    (-arrowJ - arrowheadsKern)                true }

		define rk : object
			r    { LR   (Width + arrowExtend)                    false }
			r1   { LR1  (Width + arrowExtend + arrowheadsKern)   false }
			f    { F    nothing                                  false }
			z    { Z    nothing                                  false }
			c    { C    nothing                                  false }
			m    { J    (Width + RodBarHOffset)                   true }
			j    { J    (Width + arrowJ)                          true }
			j1   { J    (Width + arrowJ + arrowheadsKern)         true }

		foreach [lS : items-of : Object.keys lk] : foreach [rS : items-of : Object.keys rk] : create-glyph"wave.lig.\(lS)\(rS)" : glyph-proc
			include : SetJoiningKind lS rS
			local {tL jL djL} lk.(lS)
			local {tR jR djR} rk.(rS)
			include : WaveShape
				left  -- tL
				right -- tR
				xsJoin -- jL
				xfJoin -- jR
				diagJoinS -- djL
				diagJoinF -- djR


	do "Arrowheads"
		glyph-block-import Symbol-Math-Relation-Common : dH
		glyph-block-import Symbol-Math-Relation-Inequality : LigationLessShape LigationGreaterShape

		create-glyph 'less.lig.dblhead' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Right
			include : LigationLessShape (SymbolMid + dH) (SymbolMid - dH) SB RightSB OperatorStroke OperatorStroke (2 * EqualHalfSpace)
			create-aliased-glyph 'less.lig.dblhead.mid'
			create-forked-glyph 'less.lig.dblhead.shift1' : glyph-proc
				Joining.set currentGlyph Joining.Classes.Mid
				include : Translate (-arrowheadsKern) 0

		create-glyph 'greater.lig.dblhead' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Left
			include : LigationGreaterShape (SymbolMid + dH) (SymbolMid - dH) SB RightSB OperatorStroke OperatorStroke (2 * EqualHalfSpace)
			create-aliased-glyph 'greater.lig.dblhead.mid'
			create-forked-glyph 'greater.lig.dblhead.shift1' : glyph-proc
				Joining.set currentGlyph Joining.Classes.Mid
				include : Translate (+arrowheadsKern) 0

		derive-glyphs 'exclam.lig.htmlcommentstart' null 'exclam' : function [src gr] : glyph-proc
			Joining.set currentGlyph Joining.Classes.Mid
			include : refer-glyph src
			include : Translate (((RightSB - Width) + (Width - arrowExtend / 2)) / 2 - Middle) 0
			include : HBar.m (-arrowExtend) (RightSB - Width) SymbolMid OperatorStroke

		# Right-shifted >
		define [ArrowShiftTranslate k] : glyph-proc
			include : Translate (arrowheadsKern * k) 0
			if (k > 0) : Joining.set currentGlyph Joining.Classes.Right
			if (k < 0) : Joining.set currentGlyph Joining.Classes.Left

		create-glyph 'greater.lig.shift0' : glyph-proc
			include [refer-glyph 'greater'] AS_BASE ALSO_METRICS
			create-aliased-glyph 'greater.lig.shift0.head'
			create-aliased-glyph 'greater.lig.shift0.mid'
			create-aliased-glyph 'greater.lig.shift0.anti'
			create-aliased-glyph 'greater.lig.shiftN0'
			create-aliased-glyph 'greater.lig.shiftN0.mid'
			create-forked-glyph 'greater.lig.shift0h'      : ArrowShiftTranslate   0.5
			create-forked-glyph 'greater.lig.shift1'       : ArrowShiftTranslate   1.0
			create-forked-glyph 'greater.lig.shift1.head'  : ArrowShiftTranslate   1.0
			create-forked-glyph 'greater.lig.shift1h'      : ArrowShiftTranslate   1.5
			create-forked-glyph 'greater.lig.shift2'       : ArrowShiftTranslate   2.0
			create-forked-glyph 'greater.lig.shiftN0h'     : ArrowShiftTranslate (-0.5)
			create-forked-glyph 'greater.lig.shiftN1'      : ArrowShiftTranslate (-1.0)
			create-forked-glyph 'greater.lig.shiftN1.anti' : ArrowShiftTranslate (-1.0)
			create-forked-glyph 'greater.lig.shiftN1h'     : ArrowShiftTranslate (-1.5)
			create-forked-glyph 'greater.lig.shiftN2'      : ArrowShiftTranslate (-2.0)

		create-glyph 'less.lig.shift0' : glyph-proc
			include [refer-glyph 'less'] AS_BASE ALSO_METRICS
			create-aliased-glyph 'less.lig.shift0.head'
			create-aliased-glyph 'less.lig.shift0.mid'
			create-aliased-glyph 'less.lig.shift0.anti'
			create-aliased-glyph 'less.lig.shiftN0'
			create-aliased-glyph 'less.lig.shiftN0.mid'
			create-forked-glyph 'less.lig.shift0h'      : ArrowShiftTranslate (-0.5)
			create-forked-glyph 'less.lig.shift1'       : ArrowShiftTranslate (-1.0)
			create-forked-glyph 'less.lig.shift1.head'  : ArrowShiftTranslate (-1.0)
			create-forked-glyph 'less.lig.shift1h'      : ArrowShiftTranslate (-1.5)
			create-forked-glyph 'less.lig.shift2'       : ArrowShiftTranslate (-2.0)
			create-forked-glyph 'less.lig.shiftN0h'     : ArrowShiftTranslate   0.5
			create-forked-glyph 'less.lig.shiftN1'      : ArrowShiftTranslate   1.0
			create-forked-glyph 'less.lig.shiftN1.anti' : ArrowShiftTranslate   1.0
			create-forked-glyph 'less.lig.shiftN1h'     : ArrowShiftTranslate   1.5
			create-forked-glyph 'less.lig.shiftN2'      : ArrowShiftTranslate   2.0

		define [ArrowHeadHole] : Rect (SymbolMid + EqualHalfSpace - 0.5 * OperatorStroke) (SymbolMid - EqualHalfSpace + 0.5 * OperatorStroke) (-Width) (2 * Width)

		create-glyph 'less.lig.hole' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Left
			include : difference
				glyph-proc : include : refer-glyph "less"
				ArrowHeadHole

		create-glyph 'greater.lig.hole' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Right
			include : difference
				glyph-proc : include : refer-glyph "greater"
				ArrowHeadHole

		create-glyph 'less.lig.hole.shiftN1' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Mid
			include : difference
				glyph-proc : include : refer-glyph "less.lig.shiftN1"
				ArrowHeadHole

		create-glyph 'greater.lig.hole.shiftN1' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Mid
			include : difference
				glyph-proc : include : refer-glyph "greater.lig.shiftN1"
				ArrowHeadHole

	do "bottom sign derivatives"
		glyph-block-import Symbol-Punctuation-Dashes : UnderScoreConfig

		foreach { suffix { yBar } } [Object.entries UnderScoreConfig] : do
			# ___ shapes
			create-glyph "underscore.lig.fc.\(suffix)" : glyph-proc
				Joining.set currentGlyph Joining.Classes.Left
				include : HBar.b SB Width yBar
				include : JunctDiamond Width (yBar + HalfStroke) Stroke
			create-glyph "underscore.lig.cf.\(suffix)" : glyph-proc
				Joining.set currentGlyph Joining.Classes.Left
				include : HBar.b 0 RightSB yBar
				include : JunctDiamond 0 (yBar + HalfStroke) Stroke
			create-glyph "underscore.lig.cc.\(suffix)" : glyph-proc
				Joining.set currentGlyph Joining.Classes.Left
				include : HBar.b 0 Width yBar
				include : JunctDiamond 0     (yBar + HalfStroke) Stroke
				include : JunctDiamond Width (yBar + HalfStroke) Stroke

			# _|_ shapes
			create-glyph "underscore.lig.fm.\(suffix)" : glyph-proc
				Joining.set currentGlyph Joining.Classes.Right
				include : HBar.b SB (Width + RodBarHOffset) yBar
			create-glyph "underscore.lig.mf.\(suffix)" : glyph-proc
				Joining.set currentGlyph Joining.Classes.Left
				include : HBar.b (0 - RodBarHOffset) RightSB yBar
			create-glyph "bar.lig.bottomMid.\(suffix)"
				VBar.m Middle yBar ParenTop

		select-variant "underscore.lig.fc" (follow -- 'underscore')
		select-variant "underscore.lig.cc" (follow -- 'underscore')
		select-variant "underscore.lig.cf" (follow -- 'underscore')
		select-variant "underscore.lig.fm" (follow -- 'underscore')
		select-variant "underscore.lig.mf" (follow -- 'underscore')
		select-variant "bar.lig.bottomMid" (follow -- 'underscore')

	do "Inequality"
		define Neq : namespace
			export : define Sw   OperatorStroke
			export : define Dr : Sw / Stroke * DotRadius
			export : define DotGap : Math.max ((ParenTop - ParenBot) / 8) [AdviceStroke 5]

			export : define PlacementSuffixes : object
				"1l" { 0   Joining.Classes.Right }
				"2l" { 1   Joining.Classes.Right }
				"3l" { 2   Joining.Classes.Right }
				"4l" { 3   Joining.Classes.Right }
				"1m" { 0   Joining.Classes.Mid   }
				"2m" { 1   Joining.Classes.Mid   }
				"3m" { 2   Joining.Classes.Mid   }
				"4m" { 3   Joining.Classes.Mid   }

			export : define BarShapeSuffixes : object
				vertical              {  0      false  }
				slightlySlanted       {  0.375  false  }
				moreSlanted           {  0.75   false  }
				verticalDotted        {  0      true   }
				slightlySlantedDotted {  0.375  true   }
				moreSlantedDotted     {  0.75   true   }

			export : define [DependentGlyphBuilder src] : glyph-proc
				local { bar dot } src
				include [refer-glyph bar] AS_BASE ALSO_METRICS
				local dotted : NeqLigationSlashDotted.get [query-glyph bar]
				if dotted : include [refer-glyph dot]

		foreach { suffix { DrawAt kdr overshoot } } [Object.entries DotVariants] : do
			create-glyph "neq/dotPart.\(suffix)" : glyph-proc
				set-width 0
				set-mark-anchor 'cvDecompose' 0 0
				include : DrawAt 0 0 (Neq.Dr - overshoot)

		select-variant 'neq/dotPart' (follow -- 'punctuationDot')

		foreach { place { shift joinCls } } [Object.entries Neq.PlacementSuffixes] : do
			foreach { barSuffix { slope fDotted } } [Object.entries Neq.BarShapeSuffixes] : do
				create-glyph "neq.\(place)/barPart.\(barSuffix)" : glyph-proc
					define yUp     BgOpTop
					define yDown : BgOpBot + [if fDotted (2 * Neq.Dr + Neq.DotGap) 0]

					define xCenter : Width * (1 / 2 + shift / 2)
					define xUp     : xCenter + slope * (yUp   - SymbolMid)
					define xDown   : xCenter + slope * (yDown - SymbolMid)

					include : dispiro
						widths.center Neq.Sw
						corner xUp yUp
						corner xDown yDown

					if fDotted : begin
						NeqLigationSlashDotted.set currentGlyph
						define yDotCenter : BgOpBot + Neq.Dr
						define xDotCenter : xCenter + slope * (yDotCenter - SymbolMid)
						set-base-anchor 'cvDecompose' xDotCenter yDotCenter

			select-variant "neq.allow-dot.\(place)/barPart"
				follow    -- "neq.allow-dot"
				shapeFrom -- "neq.\(place)/barPart"
			select-variant "neq.bar-only.\(place)/barPart"
				follow    -- "neq.bar-only"
				shapeFrom -- "neq.\(place)/barPart"

			derive-multi-part-glyphs "neq.allow-dot.\(place)" null { "neq.allow-dot.\(place)/barPart" "neq/dotPart" } Neq.DependentGlyphBuilder
			derive-multi-part-glyphs "neq.bar-only.\(place)"  null { "neq.bar-only.\(place)/barPart"  "neq/dotPart" } Neq.DependentGlyphBuilder

	do "<| , |> and <>"
		glyph-block-import Symbol-Math-Relation-Inequality : LessShape GreaterShape
		glyph-block-import Symbol-Punctuation-Slashes-And-Number-Sign : slashDefautLeft slashDefaultRight

		define koTriangle     : 1 / 6
		define koTag            0

		define kiShrunk         0
		define kiExtend         1
		define kiExtend2        2

		local [trigLeft k]   : mix SB RightSB k
		local [trigRight k]  : mix RightSB (Width * 1.5 - [HSwToV : 1.5 * OperatorStroke]) k
		local [dHTriangle kOut kIn] : LessSlope * ([trigRight kIn] - [trigLeft kOut])

		define [TrigLeftShape  kOut kIn shift] : LessShape (SymbolMid + [dHTriangle kOut kIn]) (SymbolMid - [dHTriangle kOut kIn]) ([trigLeft kOut] + shift) ([trigRight kIn] + shift)
		define [TrigRightShape kOut kIn shift] : GreaterShape (SymbolMid + [dHTriangle kOut kIn]) (SymbolMid - [dHTriangle kOut kIn]) (Width - [trigRight kIn] + shift) (Width - [trigLeft kOut] + shift)

		create-glyph 'less.lig.trig' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Right
			include : TrigLeftShape koTriangle kiExtend 0

		create-glyph 'bar.lig.trig' : glyph-proc
			include : VBar.m Middle (SymbolMid + [dHTriangle koTriangle kiExtend] + OperatorStroke) (SymbolMid - [dHTriangle koTriangle kiExtend] - OperatorStroke) OperatorStroke

		create-glyph 'greater.lig.trig' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Left
			include : TrigRightShape koTriangle kiExtend 0

		create-glyph 'less.lig.diamond' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Right
			include : intersection
				TrigLeftShape koTriangle kiExtend2 0
				union
					Rect ParenTop ParenBot 0 Width
					TrigRightShape koTriangle kiExtend2 Width

		create-glyph 'greater.lig.diamond' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Left
			include : intersection
				TrigRightShape koTriangle kiExtend2 0
				union
					Rect ParenTop ParenBot 0 Width
					TrigLeftShape koTriangle kiExtend2 (-Width)

		create-glyph 'less.lig.diamond.tag' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Right
			include : intersection
				TrigLeftShape koTag kiExtend2 0
				union
					Rect ParenTop ParenBot 0 Width
					TrigRightShape koTag kiExtend2 Width

		create-glyph 'greater.lig.diamond.tag' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Left
			include : intersection
				TrigRightShape koTag kiExtend2 0
				union
					Rect ParenTop ParenBot 0 Width
					TrigLeftShape koTag kiExtend2 (-Width)

		create-glyph 'less.lig.tag-slash' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Right
			include : intersection
				MaskAbove SymbolMid
				TrigLeftShape koTag kiShrunk 0
			include : intersection
				MaskBelow SymbolMid
				TrigLeftShape koTag kiExtend2 0
				MaskLeftLine (slashDefautLeft + Width) ParenBot (slashDefaultRight + Width) ParenTop

		create-glyph 'greater.lig.tag-slash' : glyph-proc
			Joining.set currentGlyph Joining.Classes.Left
			include : intersection
				MaskBelow SymbolMid
				TrigRightShape koTag kiShrunk 0
			include : intersection
				MaskAbove SymbolMid
				TrigRightShape koTag kiExtend2 0
				MaskRightLine (slashDefautLeft - Width) ParenBot (slashDefaultRight - Width) ParenTop

	do "Chaining Plus (shifted middle bars)"
		define NotchConfig : object
			'withoutNotch' { false }
			'withNotch'    { true  }

		foreach { suffix { fNotch } } [pairs-of NotchConfig] : do
			create-glyph "plus.lig.fc.s.\(suffix)" : glyph-proc
				Joining.set currentGlyph Joining.Classes.Right
				include : difference
					union
						PlusShape SB Width SB
						PlusShape.joinCap Width
					if fNotch [HyphenNotch Width] [no-shape]
			create-glyph "plus.lig.cf.s.\(suffix)" : glyph-proc
				Joining.set currentGlyph Joining.Classes.Left
				include : difference
					union
						PlusShape 0 RightSB (-SB)
						PlusShape.joinCap 0
					if fNotch [HyphenNotch 0] [no-shape]

		select-variant 'plus.lig.fc.s' (follow -- 'lig-plus')
		select-variant 'plus.lig.cf.s' (follow -- 'lig-plus')

	do 'Less / Greater as arrow'
		create-glyph 'greaterArrow' : composite-proc
			refer-glyph 'hyphen.lig.jp'
			refer-glyph 'greater'
