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

import [mix clamp fallback linreg SuffixCfg] from "@iosevka/util"
import [Dotless MathSansSerif HintClass] from "@iosevka/glyph/relation"
import [maskBit maskOffBit] from "@iosevka/util/mask-bit"

glyph-module

glyph-block Letter-Latin-K : begin
	glyph-block-import CommonShapes
	glyph-block-import Common-Derivatives
	glyph-block-import Mark-Shared-Metrics : markExtend
	glyph-block-import Mark-Above : aboveMarkMid
	glyph-block-import Mark-Adjustment : ExtendBelowBaseAnchors LeaningAnchor
	glyph-block-import Letter-Shared : CreateTurnedLetter
	glyph-block-import Letter-Shared-Shapes : DiagTail CyrDescender
	glyph-block-import Letter-Shared-Shapes : LetterBarOverlay PalatalHook TopHook

	local [KBalance slabLT straightBar]        : if straightBar (Width / 32) 0
	local [KBalanceRight slabLegs straightBar] : if slabLegs 0 : if straightBar (Width / 32) 0
	local [KO slabLegs straightBar top stroke] : if straightBar (([if slabLegs (0) (-4)] * OX - stroke / 3) * (XH / top)) 0

	# The mode parameter of KLegSlabs is a bitmasked interger, with the following bits [F T B]
	# F: Whether the serif is full
	# B: Bottom serif type
	# T: Top serif type
	define [HasRtSerif mode] : maskBit mode 1
	define [HasRbSerif mode] : maskBit mode 0

	define flex-params [KLegSlabs] : glyph-proc
		local-parameter : mode          -- 0
		local-parameter : straightBar   -- false
		local-parameter : top           -- XH
		local-parameter : left          -- SB
		local-parameter : right         -- RightSB
		local-parameter : stroke        -- Stroke
		local-parameter : attachment    -- nothing
		local-parameter : maskRT        -- no-shape
		local-parameter : maskRB        -- no-shape

		local Ok             : KO mode true top stroke
		local kshRight       : right + [KBalanceRight true straightBar]
		local sideJutAdj     : Ok + [HSwToV stroke]
		local symJutExtraAdj : HSwToV (0.5 * stroke)

		local slabIsFull : maskBit mode 2

		if [HasRtSerif mode] : include : tagged 'serifRT' : if slabIsFull
			then : union
				HSerif.rt (kshRight - sideJutAdj) top (SideJut + sideJutAdj)
				HSerif.lt (kshRight - sideJutAdj) top (SideJut)
			else : difference
				HSerif.rt (kshRight - sideJutAdj) top (SideJut + sideJutAdj)
				maskRT

		if [HasRbSerif mode] : include : tagged 'serifRB' : if slabIsFull
			then : union
				HSerif.rb (kshRight - sideJutAdj) 0   (SideJut + sideJutAdj)
				HSerif.lb (kshRight - sideJutAdj) 0   (SideJut)
			else : difference
				HSerif.rb (kshRight - sideJutAdj) 0   (SideJut + sideJutAdj)
				maskRB

		if attachment : begin
			include : difference
				attachment.rSideJut
					x   -- (kshRight - sideJutAdj)
					y   -- 0
					jut -- (Jut + sideJutAdj)
				maskRB

	define KLegs : namespace
		export : define [Straight fHookTop left right stroke top slabLT slabLegs attachment] : glyph-proc
			local fine : AdviceStroke 3.5
			local Ok : KO slabLegs true top stroke
			local kshLeft : left + [KBalance slabLT true]
			local kshRightBot : right + [KBalanceRight slabLegs true]
			local kshRightTop : if fHookTop (kshRightBot - HookX * 0.5 + [HSwToV : 0.5 * stroke]) kshRightBot

			local attach  : top * 0.42 - stroke
			local attach2 : top * 0.72 + stroke

			set-base-anchor 'trailing' (kshRightBot - Ok) 0

			local kshRightSerifs : right + [KBalanceRight true true]
			local serifLengthAdj : Ok + [HSwToV stroke]

			define TopMask : object
				forStroke : function [offset] : begin
					local xRight : if [HasRtSerif slabLegs] (kshRightSerifs + offset + SideJut - TanSlope * Stroke) VERY-FAR
					return : Rect top 0 kshLeft xRight
				forSerifs : function [] : intersection
					TopMask.forStroke (-0.1)
					HalfRectTriangle (kshRightTop - Ok - TINY) top (kshLeft + stroke - TINY) attach

			define BottomMask : object
				forStroke : function [offset] : begin
					local xRight : if [HasRbSerif slabLegs] (kshRightSerifs + offset + SideJut + TanSlope * Stroke) VERY-FAR
					return : Rect top 0 kshLeft xRight
				forSerifs : function []
					HalfRectTriangle (kshRightBot - Ok - TINY) 0 (kshLeft + stroke - TINY) attach2

			if fHookTop
			: then : begin
				define kHookTopMix 0.5
				if fHookTop : include : dispiro
					widths.rhs stroke
					straight.left.start (kshRightBot + [if [HasRtSerif slabLegs] SideJut 0] - TanSlope * stroke) (top - stroke)
					flat [mix (kshRightTop - Ok) (kshLeft + stroke) kHookTopMix] [mix top attach kHookTopMix] [widths.rhs : mix stroke fine kHookTopMix]
					curl (kshLeft + stroke) attach [widths.rhs fine]
			: else : begin
				set-base-anchor 'armOverlay' [mix kshLeft kshRightTop : StrokeWidthBlend 0.5 0.65] [mix attach top : StrokeWidthBlend 0.5 0.7]
				include : intersection
					TopMask.forStroke 0
					dispiro
						widths.rhs stroke
						flat (kshRightTop - Ok) top
						curl (kshLeft + stroke) attach [widths.rhs fine]


			set-base-anchor 'legOverlay' [mix kshLeft kshRightBot : StrokeWidthBlend 0.5 0.65] [mix attach2 0 : StrokeWidthBlend 0.5 0.7]
			include : intersection
				BottomMask.forStroke (-0.1)
				spiro-outline
					corner (kshLeft + stroke) 0
					corner (kshLeft + stroke) (attach + 1)
					corner (kshRightTop - Ok - TINY) top
					corner (kshRightBot - Ok) top
					corner (kshRightBot - Ok) 0
				dispiro
					flat (kshRightBot - Ok) 0 [widths.lhs stroke]
					curl (kshLeft + stroke) attach2 [widths.lhs fine]

			include : KLegSlabs
				mode        -- slabLegs
				top         -- top
				left        -- left
				right       -- right
				stroke      -- stroke
				straightBar -- true
				attachment  -- attachment
				maskRT	    -- TopMask.forSerifs
				maskRB	    -- BottomMask.forSerifs

		export : define [Symmetric leadGap hookDepth] : function [fHookTop left right stroke top slabLT slabLegs attachment] : glyph-proc
			local fine : AdviceStroke [if leadGap 3.5 3]
			local Ok : KO slabLegs true top stroke

			local kshLeft : left + [KBalance slabLT true]
			local kshRight : right + [KBalanceRight slabLegs true]

			local xAttach : kshLeft + [HSwToV stroke] + (leadGap || fine)
			local yAttach : top * [if leadGap 0.42 0.49] - stroke * [if leadGap 1 (-0.1)]
			local coYAttach : top - yAttach

			if [not hookDepth] : set-base-anchor 'trailing' (kshRight - Ok) 0

			define [StrokeMask fTop t b offset] : begin
				local hasSerif : if fTop [HasRtSerif slabLegs] [HasRbSerif slabLegs]
				return : Rect t b kshLeft [if hasSerif (kshRight + offset) (2 * Width)]

			if fHookTop
			: then : begin
				define kHookTopMix 0.5
				define kshRightHookTop : kshRight - HookX * 0.5 + [HSwToV : 0.5 * stroke]
				include : tagged 'strokeRT' : intersection
					Rect top (0.5 * top) kshLeft (2 * Width)
					dispiro
						widths.rhs stroke
						straight.left.start (kshRight + [if [HasRtSerif slabLegs] SideJut 0] - TanSlope * stroke) (top - stroke)
						flat [mix (kshRightHookTop - Ok) xAttach kHookTopMix] [mix top yAttach kHookTopMix] [widths.rhs : mix stroke fine kHookTopMix]
						curl [mix (kshRightHookTop - Ok) xAttach 2] [mix top yAttach 2] [widths.rhs fine]
			: else : begin
				local xRef : linreg yAttach xAttach top kshRight (top * 0.75)
				set-base-anchor 'armOverlay' (xRef - [HSwToV : 0.5 * Stroke]) (top * 0.75)
				include : tagged 'strokeRT' : intersection
					StrokeMask 1 top (0.5 * top) 0
					dispiro
						widths.rhs stroke
						flat (kshRight - Ok) top
						curl [mix (kshRight - Ok) xAttach 2] [mix top yAttach 2] [widths.rhs fine]

			if hookDepth
			: then : begin
				include : ExtendBelowBaseAnchors hookDepth
				include : tagged 'strokeRB' : dispiro
					flat kshLeft (0.5 * top + stroke / 2) [widths.rhs.heading stroke Rightward]
					curl [mix kshLeft right 0.5] (0.5 * top + stroke / 2)
					archv
					flat right (0.5 * top + stroke / 2 - ArchDepthB)
					curl right (hookDepth + Hook + stroke / 2)
					arcvh
					straight.left.end (right - HookX - [HSwToV : 0.5 * stroke]) hookDepth
			: else : begin
				local xRef : linreg coYAttach xAttach 0 kshRight (top * 0.25)
				set-base-anchor 'legOverlay' (xRef - [HSwToV : 0.5 * Stroke]) (top * 0.25)
				include : tagged 'strokeRB' : intersection
					StrokeMask 0 (0.5 * top) 0 0
					dispiro
						flat (kshRight - Ok) 0 [widths.lhs stroke]
						curl [mix (kshRight - Ok) xAttach 2] [mix 0 coYAttach 2] [widths.lhs fine]

				if leadGap : include : intersection
					HBar.m kshLeft (2 * Width) (0.5 * top) stroke
					union
						Rect top 0 kshLeft xAttach
						spiro-outline
							corner ([if fHookTop kshRightHookTop kshRight] - Ok - 1) top
							corner (xAttach - 1) yAttach
							corner (xAttach - 1) top
						spiro-outline
							corner (kshRight - Ok - 1) 0
							corner (xAttach - 1) coYAttach
							corner (xAttach - 1) 0

			define [TopSerifMask] : intersection
				StrokeMask 1 top (0.5 * top) (-0.1)
				HalfRectTriangle (kshRight - Ok - TINY) top ([mix (kshRight - Ok) xAttach 2] - TINY) [mix top yAttach 2]

			define [BotSerifMask] : intersection
				StrokeMask 0 (0.5 * top) 0 (-0.1)
				HalfRectTriangle (kshRight - Ok - TINY) 0   ([mix (kshRight - Ok) xAttach 2] - TINY) [mix 0 coYAttach 2]

			include : KLegSlabs
				mode        -- slabLegs
				top         -- top
				left        -- left
				right       -- right
				stroke      -- stroke
				straightBar -- true
				attachment  -- attachment
				maskRT	    -- TopSerifMask
				maskRB	    -- BotSerifMask

		export : define [Curly fHookTop left right stroke top slabLT slabLegs attachment] : glyph-proc
			local turn : top * 0.99
			local fine : AdviceStroke 3.5
			local kshLeft : left + [KBalance slabLT false]
			local kshRight : right + [KBalanceRight slabLegs false]

			set-base-anchor 'trailing' (kshRight - O) 0

			define [upperCurvature] : bezControls 0 0.3 0.5 0.65 8
			define [upperCurvatureHT] : bezControls 0.5 0 0.5 0.65 8 : object
				blend : function [t] : widths.rhs : mix stroke fine t
			define [lowerCurvature] : quadControls 0 0.3 8

			local xAttach1 : kshLeft + [HSwToV stroke]
			local yAttach1 : top * [if slabLegs 0.325 0.375]
			local xAttach2 : kshLeft + [HSwToV stroke]
			local yAttach2 : top * 0.75
			local kDiag : mix 1 [DiagCorDs (top - yAttach1) (kshRight - kshLeft) stroke] 0.5
			set-base-anchor 'armOverlay' [mix xAttach1 kshRight : StrokeWidthBlend 0.7 0.6] [mix yAttach1 top : StrokeWidthBlend 0.6 0.65]
			include : intersection
				Rect top 0 kshLeft (2 * Width)
				if fHookTop
					dispiro
						straight.left.start (kshRight + [if [HasRtSerif slabLegs] SideJut 0] - TanSlope * stroke) (top - stroke) [widths.rhs stroke]
						upperCurvatureHT
						g4 xAttach1 yAttach1 [widths.rhs fine]
					dispiro
						g4.down.start (kshRight) top [widths.rhs.heading stroke Downward]
						upperCurvature
						g4 xAttach1 yAttach1 [widths.rhs fine]
			set-base-anchor 'legOverlay' [mix xAttach2 kshRight : StrokeWidthBlend 0.7 0.6] [mix yAttach2 0 : StrokeWidthBlend 0.6 0.65]
			include : difference
				dispiro
					g4.up.start (kshRight - O) 0 [widths.lhs.heading stroke Upward]
					lowerCurvature
					g4 xAttach2 yAttach2 [widths.center fine]
				if fHookTop
					spiro-outline
						straight.left.start (kshRight + [if [HasRtSerif slabLegs] SideJut 0] - TanSlope * stroke) (top - stroke + TINY)
						upperCurvatureHT
						corner (xAttach1 - TINY) yAttach1
						corner (-Width) yAttach1
						corner (-Width) (top * 2)
						corner (2 * Width) (top * 2)
						corner (2 * Width) (top - stroke + TINY)
					spiro-outline
						corner.down.start (kshRight - TINY) top
						upperCurvature
						corner (kshLeft + stroke) (yAttach1 + TINY)
						corner kshLeft 0
						corner kshLeft top

			define [TopSerifMask] : HalfRectTriangle kshRight top xAttach1 yAttach1
			define [BotSerifMask] : HalfRectTriangle (kshRight - O - [HSwToV : 0.5 * stroke]) 0 xAttach2 yAttach2

			include : KLegSlabs
				mode        -- slabLegs
				top         -- top
				left        -- left
				right       -- right
				stroke      -- stroke
				straightBar -- false
				attachment  -- attachment
				maskRT	    -- TopSerifMask
				maskRB	    -- BotSerifMask

		define [CursiveDimen left right top stroke slabLT slabLegs] : begin
			define kshLeft  : left + [KBalance slabLegs true]
			define kshRight : right + [KBalanceRight slabLegs true]
			define Ok       : KO slabLegs true top stroke

			define arcFine ShoulderFine
			define arcStroke : AdviceStroke2 2 3 top
			define arcTerminalFine : AdviceStroke2 3 4 top
			define expansion : Width / (UPM / 2) - 1

			define pArcStartY    : 0.46 + 0.1 * (arcStroke / Width)
			define pArcTopX      : 0.625 - 0.05 * (arcStroke / Width) - 0 * expansion * (arcStroke / UPM)
			define pArcRightX    : 0.925 - TanSlope * 0.25 + ([if SLAB 0 0.05] + 0.75 * TanSlope) * (arcStroke / Width)
			define pArcRightY    : 0.575 - 0.625 * (arcStroke / Width) - 0.5 * expansion * (arcStroke / UPM)
			define pArcTerminalX : 0.2 - 2.25 * (arcStroke / Width)
			define pArcBottomX   : 0.15 + 0.0 * (arcStroke / Width)
			define pArcBottomY   : 0.45 + 0.5 * (arcStroke / Width)

			define arcRightSlope : 0.05 + 0.2 * (arcStroke / Width) + 1 * expansion * (arcStroke / UPM)

			define arcStartX    : kshLeft + [HSwToV (stroke - arcFine)]
			define arcStartY    : top * pArcStartY
			define arcTerminalX : mix arcStartX kshRight pArcTerminalX
			define arcBottomX   : mix arcStartX kshRight pArcBottomX
			define arcBottomY   : mix 0 top pArcBottomY
			define arcTerminalY : arcBottomY + arcStroke * 0.125 - O
			define arcRightX    : kshRight * pArcRightX + [HSwToV : 0.2 * stroke]
			define arcRightY    : mix arcBottomY top pArcRightY

			return : object Ok arcStartX arcStartY arcFine arcRightX arcRightY arcRightSlope arcStroke arcBottomX arcBottomY arcTerminalX arcTerminalY arcTerminalFine kshLeft kshRight pArcTopX

		define [CursiveLoopT sink offset left right stroke top slabLT slabLegs] : begin
			define dim : CursiveDimen left right top stroke slabLT slabLegs
			return : sink
				g4.up.start (dim.arcStartX + offset) dim.arcStartY [widths.rhs.heading dim.arcFine Upward]
				arch.rhs (top - offset)
					sw       -- dim.arcStroke
					swBefore -- dim.arcFine
					swAfter  -- dim.arcStroke
					p        -- dim.pArcTopX

				g4.down.mid (dim.arcRightX - offset) (dim.arcRightY - 0.5 * dim.arcRightSlope * [HSwToV dim.arcStroke])
					heading {.y dim.arcRightSlope .x HVContrast}
				arcvh
				g4 dim.arcBottomX (dim.arcBottomY - dim.arcStroke + offset) [widths.rhs.heading dim.arcTerminalFine Leftward]
				g4 dim.arcStartX (dim.arcTerminalY - dim.arcStroke + offset) [widths.rhs.heading dim.arcStroke Leftward]

		export : define [Cursive fHookTop left right stroke top slabLT slabLegs attachment] : glyph-proc
			define dim : CursiveDimen left right top stroke slabLT slabLegs

			define [BottomStrokeMask] : Rect XH 0 0 [if slabLegs (dim.kshRight + SideJut + TanSlope * Stroke) (Width * 2)]

			include : CursiveLoopT dispiro 0 left right stroke top slabLT slabLegs
			set-base-anchor 'legOverlay' [mix dim.arcTerminalX dim.kshRight : StrokeWidthBlend 0.5 0.6] [mix dim.arcTerminalY 0 : StrokeWidthBlend 0.6 0.65]
			include : difference
				intersection [BottomStrokeMask] : dispiro
					flat dim.arcTerminalX dim.arcTerminalY [widths.lhs]
					curl (dim.kshRight - dim.Ok) 0 [widths.rhs]
				CursiveLoopT spiro-outline (-O) left right stroke top slabLT slabLegs

			define [BotSerifMask] : HalfRectTriangle (dim.kshRight - dim.Ok - TINY) 0 (dim.arcTerminalX - TINY) dim.arcTerminalY

			include : KLegSlabs
				mode        -- [maskOffBit slabLegs 1]
				top         -- top
				left        -- left
				right       -- right
				stroke      -- stroke
				straightBar -- true
				attachment  -- attachment
				maskRT	    -- no-shape
				maskRB	    -- BotSerifMask

		export : define [CursiveTailed fHookTop left right stroke top slabLT slabLegs attachment] : glyph-proc
			define dim : CursiveDimen left right top stroke slabLT slabLegs

			include : CursiveLoopT dispiro 0 left right stroke top slabLT slabLegs

			define swDiagTail : AdviceStroke 2 (1 - (dim.kshLeft - SB) / Width)
			define swDiagTailAdj : swDiagTail / [mix 1 HVContrast 0.375]
			define xDTGap : 0.10 * (RightSB - SB) - (0.125 + [clamp 0 0.375 : 0.5 * (Width / UPM * 2 - 1)]) * swDiagTail
			define xDTStart : dim.arcTerminalX + [HSwToV swDiagTail] + xDTGap
			define xDTEnd : dim.kshRight - 0.8 * Hook - [HSwToV : 0.25 * swDiagTail] + xDTGap * 0.625
			define tailAngle : Math.min 85 (50 + [Math.atan2 (0.75 * swDiagTail) Hook] / Math.PI * 180)
			define dtInnerRadius : [clamp 0.125 1 : mix 1 (Width / UPM * 2) 3] * [DiagTail.DefaultInnerRadius]

			set-base-anchor 'legOverlay' [mix xDTStart xDTEnd : StrokeWidthBlend 0.65 0.75] [mix dim.arcTerminalY 0 : StrokeWidthBlend 0.6 0.65]
			include : difference
				dispiro
					flat xDTStart dim.arcTerminalY [widths.center swDiagTailAdj]
					curl (xDTEnd + 0.125 * dtInnerRadius) (0.9 * swDiagTail + 0.5 * dtInnerRadius)
					DiagTail.F 1 xDTEnd 0 dtInnerRadius tailAngle (Hook + swDiagTail / 4) swDiagTail
				CursiveLoopT spiro-outline (-O) left right stroke top slabLT slabLegs

	define [KHookTopBar xBarLeft] : TopHook.toRight.lBarInner
		x    -- xBarLeft
		yBot -- 0
		yTop -- Ascender

	define CyrlVbGap : (RightSB - SB) * 0.375
	define [CyrlVbLength top] : top * 0.375 + Stroke
	define CyrlVbSw : AdviceStroke 3

	define UpperKConfig : SuffixCfg.weave
		object # body
			straight              KLegs.Straight
			curly                 KLegs.Curly
			symmetricTouching    [KLegs.Symmetric 0]
			symmetricConnected   [KLegs.Symmetric : AdviceStroke 6]
			symmetricConnectedKH [KLegs.Symmetric  [AdviceStroke 6] Descender]
			symmetricConnectedVB [KLegs.Symmetric CyrlVbGap]
		function [body] : object # serifs
			serifless                          { 0 0 0 }
			topLeftSerifed                     { 2 0 0 }
			bottomRightSerifed                 { 0 0 1 }
			topLeftAndBottomRightSerifed       { 2 0 1 }
			topRightSerifed                    { 0 0 2 }
			topLeftAndTopRightSerifed          { 2 0 2 }
			topRightAndBottomRightSerifed      { 0 0 3 }
			triSerifed                         { 2 0 3 }
			serifedKappa                       { 2 1 3 }
			fullSerifedKappa                   { 2 1 7 }
			serifed : match body
				[Just 'symmetricConnectedKH']  { 1 1 2 }
				__                             { 1 1 3 }
			fullSerifed : match body
				[Just 'symmetricConnectedKH']  { 1 1 6 }
				__                             { 1 1 7 }

	define [UpperKLTSerif top sw xBarLeft slabType] : match slabType
		2 : HSerif.lt xBarLeft top SideJut
		1 : HSerif.mt (xBarLeft + [HSwToV : 0.5 * sw]) top Jut
		_ : glyph-proc

	define [UpperKLBSerif top sw xBarLeft slabType] : match slabType
		2 : HSerif.lb xBarLeft 0 SideJut
		1 : HSerif.mb (xBarLeft + [HSwToV : 0.5 * sw]) 0 Jut
		_ : glyph-proc

	define [CyrlKaVBar top xBarLeft] : VBar.m
		xBarLeft + [HSwToV : 0.5 * CyrlVbSw] + 0.7 * CyrlVbGap
		top / 2 - [CyrlVbLength top] / 2
		top / 2 + [CyrlVbLength top] / 2
		Math.min [AdviceStroke 5] (CyrlVbGap * 0.5)

	# Attachment glyph used for Greek Kai Symbol
	create-glyph 'UpperKaiSymbolAttachment' : glyph-proc
		set-width 0
		set-mark-anchor 'trailing' 0 0
		define shapeDepth : 0.8 * Descender - QuarterStroke
		define kSw : mix 1 HVContrast Math.SQRT1_2
		include : PointingTo 0 0 shapeDepth shapeDepth : function [mag] : union
			dispiro
				widths.lhs (Stroke * kSw)
				flat 0   0
				curl mag 0
			if SLAB
				dispiro
					widths.center (Stroke / kSw)
					flat 0 (Stroke * kSw + SideJut)
					curl 0 (0 - SideJut)
				no-shape

	# Main building
	foreach { suffix { LegsImpl {slabLT slabLB slabLegs} } } [pairs-of UpperKConfig] : do
		local straightBar : LegsImpl !== KLegs.Curly
		local xBarLeft : SB + [KBalance slabLT straightBar]

		define [KBaseShape sw top attachment] : glyph-proc
			include : VBar.l xBarLeft 0 top sw
			include : LegsImpl false SB RightSB sw top slabLT slabLegs attachment
			if slabLT : include : UpperKLTSerif top sw xBarLeft slabLT
			if slabLB : include : UpperKLBSerif top sw xBarLeft slabLB

		create-glyph "K.\(suffix)" : glyph-proc
			include : MarkSet.capital
			include : KBaseShape Stroke CAP

		create-glyph "KDescender.\(suffix)" : glyph-proc
			include : MarkSet.capital
			include : KBaseShape Stroke CAP CyrDescender
			include : ExtendBelowBaseAnchors ((-LongVJut) + QuarterStroke)

		create-glyph "KStroke.\(suffix)" : glyph-proc
			include [refer-glyph "K.\(suffix)"] AS_BASE ALSO_METRICS
			include : LetterBarOverlay.l.in
				x     -- xBarLeft
				bot   -- XH
				top   -- (CAP - [if slabLT Stroke 0])
				space -- { 0 [mix SB RightSB 0.75] }

		create-glyph "KVBar.\(suffix)" : glyph-proc
			include : MarkSet.capital
			include : KBaseShape CyrlVbSw CAP
			include : CyrlKaVBar CAP xBarLeft

		create-glyph "grek/KaiSymbol.\(suffix)" : glyph-proc
			include [refer-glyph "K.\(suffix)"] AS_BASE ALSO_METRICS
			eject-contour 'serifRB'
			include : ExtendBelowBaseAnchors Descender
			include [refer-glyph "UpperKaiSymbolAttachment"]

		create-glyph "smcpK.\(suffix)" : glyph-proc
			include : MarkSet.e
			include : KBaseShape Stroke XH

		create-glyph "smcpKDescender.\(suffix)" : glyph-proc
			include : MarkSet.e
			include : KBaseShape Stroke XH CyrDescender
			include : ExtendBelowBaseAnchors ((-LongVJut) + QuarterStroke)

		create-glyph "smcpKVBar.\(suffix)" : glyph-proc
			include : MarkSet.e
			include : KBaseShape CyrlVbSw XH
			include : CyrlKaVBar XH xBarLeft

		create-glyph "KHookTop.\(suffix)" : glyph-proc
			include : MarkSet.capital
			include : VBar.l xBarLeft 0 CAP Stroke
			include : LegsImpl true SB RightSB Stroke CAP slabLT slabLegs
			eject-contour 'serifRT'
			if slabLT : include : UpperKLTSerif CAP Stroke xBarLeft slabLT
			if slabLB : include : UpperKLBSerif CAP Stroke xBarLeft slabLB

		define [BashkirKaShape df top] : glyph-proc
			local left : if SLAB
				[mix df.leftSB df.rightSB 0.35] - [HSwToV : 0.5 * df.mvs]
				mix df.leftSB df.rightSB : if (df.adws > 1) 0.25 0.2
			local leftNB : left - [KBalance SLAB straightBar]
			local xTopBarLeftEnd : mix 0 df.leftSB : if SLAB 0.25 0.375
			local sw : AdviceStroke 3

			include : HBar.t xTopBarLeftEnd (left + 0.1 * Stroke) top
			include : VBar.l left 0 top sw
			include : LegsImpl false leftNB df.rightSB sw top SLAB slabLegs
			if SLAB : begin
				include : VSerif.dl xTopBarLeftEnd top VJut
					Math.min (VJutStroke * df.mvs / Stroke) (0.625 * (left - xTopBarLeftEnd))
				if slabLT : include : UpperKLTSerif top sw left slabLT
			if slabLB : include : UpperKLBSerif top sw left slabLB

		create-glyph "cyrl/KaBashkir.\(suffix)" : glyph-proc
			define df : include : DivFrame para.advanceScaleT
			include : df.markSet.capital
			include : BashkirKaShape df CAP

		create-glyph "cyrl/kaBashkir.\(suffix)" : glyph-proc
			define df : include : DivFrame para.advanceScaleT
			include : df.markSet.e
			include : BashkirKaShape df XH

	define LowerKConfig : SuffixCfg.weave
		object # body
			straight             KLegs.Straight
			curly                KLegs.Curly
			cursive              KLegs.Cursive
			cursiveTailed        KLegs.CursiveTailed
			symmetricTouching   [KLegs.Symmetric 0]
			symmetricConnected  [KLegs.Symmetric : AdviceStroke 6]
		object # serifs
			serifless                     { 0 0 0 }
			topLeftSerifed                { 1 0 0 }
			bottomRightSerifed            { 0 0 1 }
			topLeftAndBottomRightSerifed  { 1 0 1 }
			topRightSerifed               { 0 0 2 }
			topLeftAndTopRightSerifed     { 1 0 2 }
			topRightAndBottomRightSerifed { 0 0 3 }
			triSerifed                    { 1 0 3 }
			serifed                       { 1 1 3 }
			fullSerifed                   { 1 1 7 }

	foreach { suffix { LegsImpl {slabLT slabLB slabLegs} } } [pairs-of LowerKConfig] : do
		local straightBar : LegsImpl !== KLegs.Curly
		local xBarLeft : SB + [KBalance slabLT straightBar]

		define [kBaseShape attachment] : glyph-proc
			include : LeaningAnchor.Above.VBar.l xBarLeft
			include : VBar.l xBarLeft 0 Ascender
			include : LegsImpl false SB RightSB Stroke XH slabLT slabLegs attachment
			if slabLT : include : HSerif.lt xBarLeft Ascender SideJut
			if slabLB : include : tagged 'serifLB'
				HSerif.mb (xBarLeft + [HSwToV HalfStroke]) 0 Jut

		create-glyph "k.\(suffix)" : glyph-proc
			include : MarkSet.b
			include : kBaseShape

		create-glyph "kDescender.\(suffix)" : glyph-proc
			include : MarkSet.b
			include : kBaseShape CyrDescender
			include : ExtendBelowBaseAnchors ((-LongVJut) + QuarterStroke)

		create-glyph "kPalatalHook.\(suffix)" : glyph-proc
			include : MarkSet.b
			include : kBaseShape PalatalHook
			include : ExtendBelowBaseAnchors Descender

		create-glyph "kStroke.\(suffix)" : glyph-proc
			include [refer-glyph "k.\(suffix)"] AS_BASE ALSO_METRICS
			include : LetterBarOverlay.l.in
				x     -- xBarLeft
				bot   -- XH
				top   -- (Ascender - [if slabLT Stroke 0])

		create-glyph "kHookTop.\(suffix)" : glyph-proc
			include : MarkSet.b
			include : LegsImpl false SB RightSB Stroke XH slabLT slabLegs
			include : KHookTopBar xBarLeft
			if slabLB : include : tagged 'serifLB'
				HSerif.mb (xBarLeft + [HSwToV HalfStroke]) 0 Jut
			include : LeaningAnchor.Above.VBar.l xBarLeft

		create-glyph "turnk.\(suffix)" : glyph-proc
			include : VBar.l xBarLeft 0 Ascender
			include : LegsImpl false SB RightSB Stroke XH slabLT slabLegs
			if slabLT : include : tagged 'serifLT' : union
				HSerif.lt (xBarLeft + [HSwToV HalfStroke]) Ascender Jut
				HSerif.rt (xBarLeft + [HSwToV HalfStroke]) Ascender MidJutSide
			if slabLB : include : tagged 'serifLB'
				HSerif.lb xBarLeft 0 SideJut
			include : FlipAround Middle (XH / 2)
			include : MarkSet.p
			include : LeaningAnchor.Below.VBar.r (RightSB - [KBalance slabLT straightBar])

	select-variant 'K' 'K'
	link-reduced-variant 'K/sansSerif' 'K' MathSansSerif
	alias 'grek/Kappa' 0x39A 'K'
	alias-reduced-variant 'grek/Kappa/sansSerif' 'grek/Kappa' 'K/sansSerif' MathSansSerif
	select-variant 'KStroke' 0xA740 (follow -- 'K')
	select-variant 'cyrl/KaStroke' 0x49E (shapeFrom -- 'KStroke') (follow -- 'cyrl/Ka')
	select-variant 'KDescender' 0x2C69
	select-variant 'cyrl/Ka' 0x41A (shapeFrom -- 'K')
	select-variant 'cyrl/KaDescender' 0x49A (shapeFrom -- 'KDescender')
	select-variant 'cyrl/KaVBar' 0x49C (shapeFrom -- 'KVBar') (follow -- 'cyrl/KaVBar')
	select-variant 'cyrl/KaHook' 0x4C3 (shapeFrom -- 'K') (follow -- 'cyrl/KaHook')

	select-variant 'k' 'k'
	link-reduced-variant 'k/sansSerif' 'k' MathSansSerif
	select-variant 'kDescender' 0x2C6A
	select-variant 'kPalatalHook' 0x1D84 (follow -- 'kDescender')
	select-variant 'kStroke' 0xA741 (follow -- 'k')
	select-variant 'cyrl/kaStroke' 0x49F (shapeFrom -- 'kStroke') (follow -- 'cyrl/ka')

	select-variant 'grek/kappa' 0x3BA (shapeFrom -- 'smcpK')
	link-reduced-variant 'grek/kappa/sansSerif' 'grek/kappa' MathSansSerif (shapeFrom -- 'smcpK')

	select-variant 'smcpK' 0x1D0B (follow -- 'K')
	select-variant 'latn/kappa' 0x138 (shapeFrom -- 'smcpK')
	select-variant 'cyrl/ka' 0x43A (shapeFrom -- 'smcpK')
	select-variant 'cyrl/kaDescender' 0x49B (shapeFrom -- 'smcpKDescender')
	select-variant 'cyrl/ka.BGR' (shapeFrom -- 'k') (follow -- 'cyrl/ka')
	select-variant 'cyrl/kaVBar' 0x49D (shapeFrom -- 'smcpKVBar') (follow -- 'cyrl/kaVBar')
	select-variant 'cyrl/kaHook' 0x4C4 (shapeFrom -- 'smcpK') (follow -- 'cyrl/kaHook')

	select-variant 'KHookTop' 0x198
	select-variant 'kHookTop' 0x199

	derive-composites 'cyrl/KaAleut' 0x51E 'cyrl/Ka' 'aleutSlashOver'
	derive-composites 'cyrl/kaAleut' 0x51F 'cyrl/ka' 'aleutSlashOver'
	derive-composites 'KLegStroke' 0xA742 'K' 'legSlashOver'
	derive-composites 'kLegStroke' 0xA743 'k' 'legSlashOver'
	derive-composites 'KStrokeLegStroke' 0xA744 'KStroke' 'legSlashOver'
	derive-composites 'kStrokeLegStroke' 0xA745 'kStroke' 'legSlashOver'

	CreateTurnedLetter 'turnK'     0xA7B0  'K'     HalfAdvance (CAP / 2)
	CreateTurnedLetter 'smcpTurnK' 0x1DF10 'smcpK' HalfAdvance (XH / 2)

	select-variant 'turnk' 0x29E (follow -- 'k')

	select-variant 'cyrl/KaBashkir' 0x4A0
	select-variant 'cyrl/kaBashkir' 0x4A1

	select-variant 'grek/KaiSymbol' 0x3CF (follow -- 'KDescender')

	derive-multi-part-glyphs 'kDot' null {'k' 'dotAbove'} : lambda [srcs gr] : glyph-proc
		local { base mark } srcs
		include : refer-glyph mark
		include : Translate (Width + [HSwToV HalfStroke]) 0
		include [refer-glyph base] AS_BASE
		include : LeaningAnchor.Above.VBar.l Middle
		HintClass.set currentGlyph 'latn' 'dflt'

	glyph-block-import Letter-Blackboard : BBS BBD BBBarLeft
	define [BBKLegShape top left right] : begin
		local kDiag : DiagCorDs (top / 2) (right - left) BBD
		return : union
			HBar.b (right - kDiag * BBD) right 0 BBS
			intersection
				Rect top 0 left (2 * Width)
				ExtLineCenter 2 BBS right top left (top / 2)
			intersection
				spiro-outline
					corner right top
					corner left (top / 2)
					corner left 0
					corner (Width * 2) 0
					corner (Width * 2) top
				union
					ExtLineCenter 2 BBS right 0 (left + kDiag * BBD) (top / 2)
					ExtLineCenter 2 BBS (right - kDiag * BBD) 0 left (top / 2)

	create-glyph 'mathbb/K' 0x1D542 : glyph-proc
		include : MarkSet.capital
		include : BBBarLeft SB 0 CAP
		include : BBKLegShape CAP (SB + BBD + [HSwToV BBS]) RightSB

	create-glyph 'mathbb/k' 0x1D55C : glyph-proc
		include : MarkSet.b
		include : BBBarLeft SB 0 Ascender
		include : BBKLegShape XH (SB + BBD + [HSwToV BBS]) RightSB
