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

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

glyph-module

glyph-block Letter-Latin-V : begin
	glyph-block-import CommonShapes
	glyph-block-import Common-Derivatives
	glyph-block-import Letter-Shared : CreateTurnedLetter
	glyph-block-import Letter-Shared-Shapes : DiagTail SerifFrame PalatalHook VerticalHook
	glyph-block-import Letter-Blackboard : BBS BBD

	glyph-block-export VCornerHalfWidth
	define VCornerHalfWidth : HSwToV : 1.15 * HalfStroke
	define VCurviness   0.3
	define VShapeFine : Math.max
		Stroke * [if SLAB para.vtipfineSlab para.vtipfine]
		VCornerHalfWidth * 1.2
	define VShapeFineStraight : Stroke * CThin * 1.15
	define pInktrap : 2 / 3
	define VShapeMiddleWidth : Math.min [mix Stroke VShapeFineStraight pInktrap] [AdviceStroke 3]

	define StraightSbShrink : mix 1 (DesignParameters.straightVShapeSbShrink * [StrokeWidthBlend 1 0.75]) : if SLAB 0.75 1
	define [VShapeTopFlat top] : if SLAB [Math.min (top - Stroke) (top * 0.9)] (top * 0.9)

	glyph-block-export VShapeOutline
	define [VShapeOutline] : with-params [df fBarStraight top [sw Stroke]] : glyph-proc
		define cornerHW : VCornerHalfWidth * sw / Stroke
		define dgCor : DiagCor top (Width / 2) 0 (sw * 2)
		define clearance : 0 - OX

		local sbScale : if fBarStraight StraightSbShrink 1
		define vxStartL : df.leftSB * sbScale + clearance
		define vxEndL : df.middle - cornerHW + clearance
		define vxStartR : df.width - df.leftSB * sbScale - clearance
		define vxEndR : df.middle + cornerHW - clearance

		if fBarStraight : do
			include : spiro-outline
				flat [mix vxStartL vxEndL 0] [mix top 0 0]
				curl [mix vxStartL vxEndL pInktrap] [mix top 0 pInktrap]
				corner [mix vxStartL vxEndL 1] [mix top 0 1]
				corner [mix vxStartR vxEndR 1] [mix top 0 1]
				flat [mix vxStartR vxEndR pInktrap] [mix top 0 pInktrap]
				curl [mix vxStartR vxEndR 0] [mix top 0 0]
		: else : do
			include : spiro-outline
				flat vxStartL top
				curl vxStartL [VShapeTopFlat top]
				quadControls 0 VCurviness 9 unimportant
				corner vxEndL 0
				corner vxEndR 0
				quadControls 1 (1 - VCurviness) 9 unimportant
				flat vxStartR [VShapeTopFlat top]
				curl vxStartR top

	define [VBottomCapShape df fBarStraight sw] : begin
		define cornerHW : VCornerHalfWidth * sw / Stroke
		return : spiro-outline
			corner (df.middle + cornerHW) 0
			corner (df.middle - cornerHW) 0
			corner df.middle [Math.min sw : if fBarStraight VShapeFineStraight VShapeFine]

	glyph-block-export VShape
	define [VShape] : with-params [df fBarStraight top [sw Stroke]] : glyph-proc
		define cornerHW : VCornerHalfWidth * (sw / Stroke)
		define fine : Math.min sw : [if fBarStraight VShapeFineStraight VShapeFine] * (sw / Stroke)
		define dgCor : DiagCor (2 * top) Width 0 (2 * sw)

		local sbScale : if fBarStraight StraightSbShrink 1
		define vxStartL : df.leftSB * sbScale
		define vxEndL : df.middle - cornerHW
		define vxStartR : df.width - df.leftSB * sbScale
		define vxEndR : df.middle + cornerHW

		if fBarStraight : do
			define midSW : dgCor * VShapeMiddleWidth / Stroke * sw
			include : tagged 'strokeDown' : dispiro
				widths.lhs (sw * dgCor)
				flat [mix vxStartL vxEndL 0] [mix top 0 0] [heading Downward]
				curl [mix vxStartL vxEndL pInktrap] [mix top 0 pInktrap] [widths.lhs.heading midSW Downward]
				g4   [mix vxStartL vxEndL 1] [mix top 0 1] [widths.lhs.heading fine Downward]
			include : tagged 'strokeUp' : dispiro
				widths.rhs (sw * dgCor)
				flat [mix vxStartR vxEndR 0] [mix top 0 0] [heading Downward]
				curl [mix vxStartR vxEndR pInktrap] [mix top 0 pInktrap] [widths.rhs.heading midSW Downward]
				g4   [mix vxStartR vxEndR 1] [mix top 0 1] [widths.rhs.heading fine Downward]
		: else : do
			include : tagged 'strokeDown' : dispiro
				widths.lhs sw
				flat vxStartL top [heading Downward]
				curl vxStartL [VShapeTopFlat top] [heading Downward]
				quadControls 0 VCurviness 9 unimportant
				g4 vxEndL 0 [widths.lhs fine]
			include : tagged 'strokeUp' : dispiro
				widths.rhs sw
				flat vxStartR top [heading Downward]
				curl vxStartR [VShapeTopFlat top] [heading Downward]
				quadControls 0 VCurviness 9 unimportant
				g4 vxEndR 0 [widths.rhs fine]

			#bottom cap
			include : VBottomCapShape df fBarStraight sw

	define [VCursiveShapeBarPos k] : mix SB RightSB k
	define [VCursiveShape] : with-params [k top [sw Stroke]] : glyph-proc
		define xBar : VCursiveShapeBarPos k
		define xArcRight : RightSB - OX
		define yArcRight : [mix 0 top 0.6] - sw * 0.2
		define xArcEnd : [mix SB RightSB 0.8] + sw * 0.375
		define yArcEnd : top - O
		define rInY : DiagTail.DefaultInnerRadius
		define xArcMidBottom : arch.adjust-x.bot (xBar + [HSwToV sw] + [HSwToV rInY]) sw

		include : dispiro
			widths.lhs sw
			flat xBar top [heading Downward]
			curl xBar ((sw + rInY) * (1 + TanSlope))
			arcvh
			g2.right.mid xArcMidBottom O
			archv.superness 2
			g4 xArcRight yArcRight
			g4 xArcEnd yArcEnd

		set-base-anchor 'palatalHookAttach'
			mix xArcMidBottom xArcRight 0.5
			mix O yArcRight : archv.yFromX 0.5 2

	glyph-block-export VHookRightShape
	define [VHookRightShape] : with-params [df fBarStraight top [sw Stroke] [hookWidthOuter (TailX / 3)] [hookWidthInner (TailX / 3)]] : glyph-proc
		include : VShape df fBarStraight top (sw -- sw)
		eject-contour 'strokeUp'
		include : VBottomCapShape df fBarStraight sw
		include : dispiro
			widths.rhs sw
			straight.left.start (df.rightSB + hookWidthOuter) (top - sw - O)
			g4 (df.rightSB - hookWidthInner) (top - 0.5 * sw - TailY)
			quadControls 0.4 0.75 64 unimportant
			g4 (df.middle + VCornerHalfWidth * sw / Stroke) 0 [widths.rhs : VShapeFine * sw / Stroke]

	define [VLoopShape] : with-params [df fBarStraight top [sw Stroke]] : glyph-proc
		include : VShape df fBarStraight top (sw -- sw)
		eject-contour 'strokeDown'
		include : VBottomCapShape df fBarStraight sw

		define cornerHW : VCornerHalfWidth * (sw / Stroke)
		define cornerSw : VShapeFine * sw / Stroke
		define sbScale : if fBarStraight StraightSbShrink 1
		define vxStartL : df.leftSB * sbScale
		define vxEndL : df.middle - cornerHW
		define swLoop : AdviceStroke 4.5
		define xLoopL : mix df.leftSB vxEndL 0.1
		define loopSizeX : 0.5 * (df.middle - xLoopL + [HSwToV : 0.5 * swLoop])
		define loopSizeY : Math.min loopSizeX : 0.5 * (0.5 * top + 0.5 * swLoop)

		local swLoopMix1 : mix swLoop [mix sw cornerSw 0.5] 0.375
		local swLoopMix2 : mix swLoop [mix sw cornerSw 0.5] 0.75

		include : dispiro
			flat (df.leftSB * 0.5) (top - 2 * loopSizeY) [widths.lhs swLoop]
			curl (xLoopL + loopSizeX) (top - 2 * loopSizeY)
			archv
			g4 (xLoopL + 2 * loopSizeX - O) (top - loopSizeY)
			arch.lhs top (swBefore -- swLoop) (sw -- swLoopMix1) (swAfter -- swLoopMix2)
			g4 xLoopL (top - loopSizeY) [widths.lhs swLoopMix2]
			flat [mix vxStartL vxEndL : if fBarStraight 0.5 0.425] [mix top 0 0.5] [widths.lhs : mix sw cornerSw 0.5]
			curl vxEndL 0 [widths.lhs cornerSw]

	define [VSerifs df fBarStraight top] : begin
		local sbScale  : if fBarStraight StraightSbShrink 1
		local sbOffset : if fBarStraight (OX * [StrokeWidthBlend 1 2]) 0
		local sf : SerifFrame top 0 (df.leftSB * sbScale - sbOffset) (df.width - df.leftSB * sbScale + sbOffset)
		return : composite-proc sf.lt.full sf.rt.full

	define [VAutoSerifs df fBarStraight top] : if SLAB [VSerifs df fBarStraight top] [no-shape]

	define [VMotionSerifs df fBarStraight top] : begin
		local sbScale  : if fBarStraight StraightSbShrink 1
		local sbOffset : if fBarStraight (OX * [StrokeWidthBlend 1 2]) 0
		local sf : SerifFrame top 0 (df.leftSB * sbScale - sbOffset) (df.width - df.leftSB * sbScale + sbOffset)
		return : composite-proc sf.lt.outer

	define VStandardConfig : object
		straight              { VAutoSerifs   true  }
		curly                 { VAutoSerifs   false }
		straightSerifless     { no-shape      true  }
		curlySerifless        { no-shape      false }
		straightMotionSerifed { VMotionSerifs true  }
		curlyMotionSerifed    { VMotionSerifs false }
		straightSerifed       { VSerifs       true  }
		curlySerifed          { VSerifs       false }

	foreach { suffix { Serifs fStraightBar }} [Object.entries VStandardConfig] : do
		create-glyph "V.\(suffix)" : glyph-proc
			include : MarkSet.capital
			include : VShape [DivFrame 1] fStraightBar CAP Stroke
			include : Serifs [DivFrame 1] fStraightBar CAP

		create-glyph "v.\(suffix)" : glyph-proc
			include : MarkSet.e
			include : VShape [DivFrame 1] fStraightBar XH Stroke
			include : Serifs [DivFrame 1] fStraightBar XH

		create-glyph "VHookRight.\(suffix)" : glyph-proc
			include : MarkSet.capital
			include : VHookRightShape [DivFrame 1] fStraightBar CAP
			include : Serifs [DivFrame 1] fStraightBar CAP
			eject-contour 'serifRT'

		create-glyph "vHookRight.\(suffix)" : glyph-proc
			include : MarkSet.e
			include : VHookRightShape [DivFrame 1] fStraightBar XH
			include : Serifs [DivFrame 1] fStraightBar XH
			eject-contour 'serifRT'

		create-glyph "vLoop.\(suffix)" : glyph-proc
			include : MarkSet.e
			include : VLoopShape [DivFrame 1] fStraightBar XH
			include : Serifs [DivFrame 1] fStraightBar XH
			eject-contour 'serifLT'

		create-glyph "cyrl/Uk.\(suffix)" : glyph-proc
			include : MarkSet.capital
			local vPartHeight : CAP * 0.45 + HalfStroke
			include : with-transform [ApparentTranslate 0 (CAP - vPartHeight)] : glyph-proc
				include : VHookRightShape [DivFrame 1] fStraightBar vPartHeight
				include : Serifs [DivFrame 1] fStraightBar vPartHeight
				eject-contour 'serifRT'

			local oHeight : CAP - vPartHeight + Stroke + O
			include : OShape oHeight 0 SB RightSB [AdviceStroke 2.75]
			include : VBar.m Middle (0.5 * oHeight) oHeight [AdviceStroke 4]

		create-glyph "cyrl/ukUnblended.\(suffix)" : glyph-proc
			include : MarkSet.b
			local vPartHeight : Ascender * 0.45 + HalfStroke
			include : with-transform [ApparentTranslate 0 (Ascender - vPartHeight)] : glyph-proc
				include : VHookRightShape [DivFrame 1] fStraightBar vPartHeight
				include : Serifs [DivFrame 1] fStraightBar vPartHeight
				eject-contour 'serifRT'
			include : OShape (Ascender - vPartHeight + Stroke + O) 0 SB RightSB

		create-glyph "vPalatalHook.\(suffix)" : glyph-proc
			include [refer-glyph "v.\(suffix)"] AS_BASE ALSO_METRICS
			include : PalatalHook.r
				xLink -- Middle
				x -- (Middle + [HSwToV HalfStroke] + [PalatalHook.adviceGap Stroke])
				y -- 0

	define VCursiveConfig : object
		cursiveSerifless     { (1/24) false }
		cursiveSerifed       { (1/16) true  }

	foreach { suffix { pxBar fDoSerif } } [Object.entries VCursiveConfig] : do
		create-glyph "v.\(suffix)" : glyph-proc
			include : MarkSet.e
			include : VCursiveShape pxBar XH Stroke
			if fDoSerif : begin
				local xBar : VCursiveShapeBarPos pxBar
				include : tagged 'serifLT' : HSerif.lt xBar XH (SideJut + xBar - SB)

		create-glyph "vPalatalHook.\(suffix)" : glyph-proc
			include [refer-glyph "v.\(suffix)"] AS_BASE ALSO_METRICS
			local attach : currentGlyph.gizmo.unapply currentGlyph.baseAnchors.palatalHookAttach
			include : PalatalHook.r
				x -- attach.x
				y -- 0
				yAttach -- attach.y

	select-variant 'V' 'V'
	link-reduced-variant 'V/sansSerif' 'V' MathSansSerif
	select-variant 'smcpV' 0x1D20 (shapeFrom -- 'v') (follow -- 'V')

	select-variant 'v' 'v'
	select-variant 'v/nonCursive' (shapeFrom -- 'v')
	link-reduced-variant 'v/sansSerif' 'v' MathSansSerif

	select-variant "vPalatalHook" 0x1D8C (follow -- 'v')

	select-variant 'vHookRight' 0x2C71 (follow -- 'v/nonCursive')
	select-variant 'cyrl/ukUnblended' 0x1C88 (follow -- 'v/nonCursive')

	select-variant 'vLoop' 0x2C74

	select-variant 'cyrl/Izhitsa' 0x474 (follow -- 'VHookRight') (shapeFrom -- 'VHookRight')
	select-variant 'cyrl/Uk' 0xA64A (follow -- 'VHookRight')
	alias 'cyrl/izhitsa' 0x475 'vHookRight'

	CreateTurnedLetter 'turnV' 0x245 'V' HalfAdvance (CAP / 2)
	CreateTurnedLetter 'turnv' 0x28C 'v' HalfAdvance (XH / 2)

	define [VHookTopShape df top ada adb] : glyph-proc
		include : dispiro
			widths.lhs
			flat df.leftSB top [heading Downward]
			curl df.leftSB adb
			arch.lhs 0
			flat df.rightSB ada
			curl df.rightSB (top - Hook - HalfStroke) [heading Upward]
		include : VerticalHook.r
			x -- df.rightSB
			y -- (top - Hook - HalfStroke)
			xDepth -- ((-RightSB) + Middle + [HSwToV HalfStroke])
			yDepth -- (-Hook)

	create-glyph 'VHookTop.serifless' : glyph-proc
		include : MarkSet.capital
		include : VHookTopShape [DivFrame 1] CAP ArchDepthA ArchDepthB

	create-glyph 'VHookTop.serifed' : glyph-proc
		include [refer-glyph "VHookTop.serifless"] AS_BASE ALSO_METRICS
		include : tagged 'serifLT' : HSerif.lt SB CAP SideJut

	select-variant 'VHookTop' 0x1B2

	create-glyph 'vHookTop.serifless' : glyph-proc
		include : MarkSet.e
		include : VHookTopShape [DivFrame 1] XH SmallArchDepthA SmallArchDepthB

	create-glyph 'vHookTop.serifed' : glyph-proc
		include [refer-glyph "vHookTop.serifless"] AS_BASE ALSO_METRICS
		include : tagged 'serifLT' : HSerif.lt SB XH SideJut

	select-variant 'vHookTop' 0x28B

	glyph-block-export BBVShape BBVInnerMaskShape BBVOuterMaskShape
	define [BBVShape l r kd ks top] : glyph-proc
		local m : mix l r 0.5
		local bbd : BBD * kd
		local bbs : BBS * ks
		local kDiag : DiagCorDs top ((r - l) / 2) (bbd / 2)
		include : intersection
			Rect top 0 (-Width) (2 * Width)
			union
				ExtLineCenter 1 bbs  l                top (m - kDiag * bbd / 2) 0
				ExtLineCenter 1 bbs (l + kDiag * bbd) top (m + kDiag * bbd / 2) 0
				ExtLineCenter 1 bbs  r                top (m + kDiag * bbd / 2) 0
		include : HBar.t  l                    (l + kDiag * bbd)     top bbs
		include : HBar.b (m - kDiag * bbd / 2) (m + kDiag * bbd / 2) 0   bbs

	define [BBVInnerMaskShape l r kd ks top] : glyph-proc
		local m : mix l r 0.5
		local bbd : BBD * kd
		local kDiag : DiagCorDs top ((r - l) / 2) (bbd / 2)
		include : spiro-outline
			corner (l + kDiag * bbd) top
			corner  r                top
			corner (m + kDiag * bbd / 2) 0

	define [BBVOuterMaskShape l r kd ks top] : glyph-proc
		local m : mix l r 0.5
		local bbd : BBD * kd
		local kDiag : DiagCorDs top ((r - l) / 2) (bbd / 2)
		include : spiro-outline
			corner  l top
			corner  r top
			corner (m + kDiag * bbd / 2) 0
			corner (m - kDiag * bbd / 2) 0

	create-glyph 'mathbb/V' 0x1D54D : composite-proc [MarkSet.capital] [BBVShape SB RightSB 1 1 CAP]
	create-glyph 'mathbb/v' 0x1D567 : composite-proc [MarkSet.e]       [BBVShape SB RightSB 1 1 XH]
