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

import [mix linreg clamp fallback] from "@iosevka/util"
import [Transform] from "@iosevka/geometry/transform"
import [Box] from "@iosevka/geometry/box"

glyph-module

glyph-block Symbol-Mosaic-Split-Graphic : begin
	glyph-block-import CommonShapes
	glyph-block-import Common-Derivatives
	glyph-block-import Common-OShape-Variants : RoundRectShapeT
	glyph-block-import Symbol-Pictograph-Stick-Figure : StickFigureKit
	glyph-block-import Symbol-Pictograph-Keyboard : KeyGen

	define boxDrawingStroke : AdviceStroke 3.5
	define graphicSw : AdviceStroke 3.5

	define top    fontMetrics.os2.sTypoAscender
	define bottom fontMetrics.os2.sTypoDescender
	define left   0
	define MosaicHeight : top - bottom

	glyph-block-export Multicell
	define [Multicell MosaicWidth] : namespace
		define [Mask] : spiro-outline
			corner left top
			corner (left + MosaicWidth) top
			corner (left + MosaicWidth) bottom
			corner left bottom

		export : define [NBox t b l r vspan hspan] : begin
			local r2 : r + MosaicWidth * (hspan - 1)
			local t2 : t + MosaicHeight * (vspan - 1)

			return : new Box t2 b l r2

		export : define [Split t b l r vspan hspan shapeFunc mappings] : glyph-proc
			local box : NBox t b l r vspan hspan
			local shape : shapeFunc box.top box.bottom box.left box.right
			local gizmo currentGlyph.gizmo

			foreach { vidx hidx name code } [items-of mappings] : create-forked-glyph name code : glyph-proc
				set currentGlyph.gizmo gizmo
				include : intersection
					Mask
					composite-proc shape : Translate (-hidx * MosaicWidth) (-vidx * MosaicHeight)

		export : define [Select t b l r vspan hspan shapeFunc vidx hidx] : glyph-proc
			local box : NBox t b l r vspan hspan
			local shape : shapeFunc box.top box.bottom box.left box.right

			include : intersection
				Mask
				composite-proc shape : Translate (-hidx * MosaicWidth) (-vidx * MosaicHeight)

	for-width-kinds WideWidth4
		define right MosaicWidth

		local multicell : Multicell MosaicWidth

		do "Split Circles"
			define [CircleTouchingBox top bot left right] : dispiro
				widths.lhs boxDrawingStroke
				g4 left [mix top bot 0.5]
				arcvh.superness 2
				g4 [mix left right 0.5] bot
				archv.superness 2
				g4 right [mix top bot 0.5]
				arcvh.superness 2
				g4 [mix left right 0.5] top
				archv.superness 2
				close

			create-glyph : glyph-proc
				set-width MosaicWidth
				include : ForceUpright
				include : multicell.Split top bottom left right 2 2 CircleTouchingBox : list
					list 1 0 [MangleName 'quarterCircleLT'] [MangleUnicode 0x1CC35]
					list 1 1 [MangleName 'quarterCircleRT'] [MangleUnicode 0x1CC36]
					list 0 0 [MangleName 'quarterCircleLB'] [MangleUnicode 0x1CC39]
					list 0 1 [MangleName 'quarterCircleRB'] [MangleUnicode 0x1CC3A]

				include : multicell.Split top bottom left right 4 4 CircleTouchingBox : list
					list 3 0 [MangleName 'twelfthCircleLT' ] [MangleUnicode 0x1CC30]
					list 3 1 [MangleName 'twelfthCircleCLT'] [MangleUnicode 0x1CC31]
					list 3 2 [MangleName 'twelfthCircleCRT'] [MangleUnicode 0x1CC32]
					list 3 3 [MangleName 'twelfthCircleRT' ] [MangleUnicode 0x1CC33]
					list 2 0 [MangleName 'twelfthCircleLMT'] [MangleUnicode 0x1CC34]
					list 2 3 [MangleName 'twelfthCircleRMT'] [MangleUnicode 0x1CC37]
					list 1 0 [MangleName 'twelfthCircleLMB'] [MangleUnicode 0x1CC38]
					list 1 3 [MangleName 'twelfthCircleRMB'] [MangleUnicode 0x1CC3B]
					list 0 0 [MangleName 'twelfthCircleLB' ] [MangleUnicode 0x1CC3C]
					list 0 1 [MangleName 'twelfthCircleCLB'] [MangleUnicode 0x1CC3D]
					list 0 2 [MangleName 'twelfthCircleCRB'] [MangleUnicode 0x1CC3E]
					list 0 3 [MangleName 'twelfthCircleRB' ] [MangleUnicode 0x1CC3F]

		do "Television"
			define scaffold : object
			set scaffold.legSize (1 / 6)
			set scaffold.dotSize DotRadius
			set scaffold.dotXOffset : (top - bottom) / 9
			set scaffold.dotYOffset : (top - bottom) / 6
			set scaffold.screenInset : (top - bottom) / 8
			set scaffold.cornerRad : (top - bottom) / 8

			define [Screen top bot left right] : RoundRectShapeT dispiro top bot left right graphicSw scaffold.cornerRad

			define [Television top bot left right] : glyph-proc
				local tvBot : mix bot top scaffold.legSize
				local legWidth : (right - left) * scaffold.legSize * (2 / MosaicWidthScalar)
				local legLeft  : left  + [HSwToV graphicSw]
				local legRight : right - [HSwToV graphicSw]
				local dotX : right - [HSwToV graphicSw] - scaffold.dotXOffset

				include : HBar.t left right top graphicSw
				include : HBar.b left right tvBot graphicSw
				include : VBar.l left tvBot top graphicSw
				include : VBar.r right tvBot top graphicSw
				include : spiro-outline
					corner legLeft tvBot
					corner (legLeft + legWidth / 3) bot
					corner (legLeft + legWidth * 2 / 3) bot
					corner (legLeft + legWidth) tvBot
				include : spiro-outline
					corner legRight tvBot
					corner (legRight - legWidth / 3) bot
					corner (legRight - legWidth * 2 / 3) bot
					corner (legRight - legWidth) tvBot

				include : DotAt dotX (top - graphicSw - scaffold.dotYOffset * 1) scaffold.dotSize
				include : DotAt dotX (top - graphicSw - scaffold.dotYOffset * 2) scaffold.dotSize
				include : DotAt dotX (top - graphicSw - scaffold.dotYOffset * 3) scaffold.dotSize
				include : Screen (top - scaffold.screenInset) (tvBot + scaffold.screenInset) (left + scaffold.screenInset) (dotX - scaffold.dotXOffset)

			create-glyph : glyph-proc
				set-width MosaicWidth
				include : ForceUpright
				include : multicell.Split top bottom left right 2 2 Television : list
					list 1 0 [MangleName 'televisionLT'] [MangleUnicode 0x1CCB2]
					list 1 1 [MangleName 'televisionRT'] [MangleUnicode 0x1CCB3]
					list 0 0 [MangleName 'televisionLB'] [MangleUnicode 0x1CCB4]
					list 0 1 [MangleName 'televisionRB'] [MangleUnicode 0x1CCB5]

		do "Microcomputer"
			define scaffold : object
			set scaffold.blank (1 / 6)
			set scaffold.dotSize DotRadius
			set scaffold.dotXOffset : (top - bottom) / 9
			set scaffold.dotYOffset : (top - bottom) / 6
			set scaffold.keyInset : (top - bottom) / 8 * (MosaicWidthScalar / 2)

			define [Microcomputer top bot left right] : glyph-proc
				local cpuTop : mix top bot scaffold.blank
				local dotX : right - [HSwToV graphicSw] - scaffold.dotXOffset
				local dotY : cpuTop - graphicSw - scaffold.dotYOffset
				local kbdTop : dotY - scaffold.dotYOffset
				local keyLeft : left + [HSwToV graphicSw] + scaffold.keyInset
				local keyRight : right - [HSwToV graphicSw] - scaffold.keyInset

				include : HBar.t left right cpuTop graphicSw
				include : HBar.t left right kbdTop graphicSw
				include : HBar.b left right bot graphicSw
				include : VBar.l left bot cpuTop graphicSw
				include : VBar.r right bot cpuTop graphicSw

				include : HBar.m keyLeft (dotX - scaffold.dotSize / 2 - scaffold.keyInset) dotY graphicSw
				include : DotAt dotX dotY scaffold.dotSize

				# Key configuration
				# **  **  **  **  **  **  ****
				# ***  **  **  **  **  **  ***
				# ****  **  **  **  **  ******
				#       ****************
				include : KeyGen (kbdTop - graphicSw - scaffold.keyInset) (bot + graphicSw + scaffold.keyInset) keyLeft keyRight 28 4 graphicSw : list
					list 3  0  2
					list 3  4  6
					list 3  8 10
					list 3 12 14
					list 3 16 18
					list 3 20 22
					list 3 24 28
					list 2  0  3
					list 2  5  7
					list 2  9 11
					list 2 13 15
					list 2 17 19
					list 2 21 23
					list 2 25 28
					list 1  0  4
					list 1  6  8
					list 1 10 12
					list 1 14 16
					list 1 18 20
					list 1 22 28
					list 0  6 22

			create-glyph : glyph-proc
				set-width MosaicWidth
				include : ForceUpright
				include : multicell.Split top bottom left right 2 2 Microcomputer : list
					list 1 0 [MangleName 'microcomputerLT'] [MangleUnicode 0x1CCB6]
					list 1 1 [MangleName 'microcomputerRT'] [MangleUnicode 0x1CCB7]
					list 0 0 [MangleName 'microcomputerLB'] [MangleUnicode 0x1CCB8]
					list 0 1 [MangleName 'microcomputerRB'] [MangleUnicode 0x1CCB9]

		do "Knight"
			define [StandingKnight top bot left right] : glyph-proc
				local box : new Box top bot left right

				local sw1 : graphicSw * MosaicWidthScalar
				local sw2 : graphicSw * 2 * [Math.sqrt MosaicWidthScalar]
				local kit1 : StickFigureKit box [Transform.Id] sw1
				local kit2 : StickFigureKit box [Translate (sw2 - sw1) 0] sw2
				local kit3 : StickFigureKit box [Translate (sw1 / 2) 0] sw1

				# Flag
				local flagMidX : [box.mixX : 13 / 16] + (sw2 - sw1)
				include : union
					kit1.RoundSeg 1 0 1 1 0 0 (-1)
					intersection [MaskRight flagMidX]
						kit2.RoundSeg (16 / 16) 1 (13 / 16) (13 / 16) 0 0 1
					intersection [MaskLeft  flagMidX]
						kit2.RoundSeg (13 / 16) (13 / 16) (10 / 16) 1 0 0 1

				# Head
				local HelmetX1 : box.mixX (6 / 16)
				local HelmetMask : union
					kit1.Arc 0.75 0.5 (6 / 16) (14 / 16) 0.75 (10 / 16) 0 0 1 1
					MaskLeft HelmetX1
				include : union
					difference
						union
							kit1.RoundSeg ( 4 / 16) (25 / 32) ( 6 / 16) (14 / 16) 0 0 1
							kit1.Arc      ( 6 / 16) (14 / 16) (10 / 16) (14 / 16) ( 8 / 16) (31 / 32) 0 0 1
							kit1.RoundSeg (10 / 16) (14 / 16) (12 / 16) (25 / 32) 0 0 1
							kit1.Arc      (12 / 16) (25 / 32) (13 / 16) (11 / 16) (13 / 16) (47 / 64) 0 0 1
							kit1.ArcVH    (13 / 16) (11 / 16) (11 / 16) ( 8 / 16) 0 0 1
						* HelmetMask
					intersection
						union
							kit1.Arc   ( 2 / 16) (5 / 8) ( 6 / 16) (14 / 16) ( 2 / 16) (6 / 8) 0 0 1 1
							MaskRight HelmetX1
						kit1.Arc 0.75 0.5 (6 / 16) (14 / 16) 0.75 (10 / 16) 0 0 (-1)
					intersection
						* HelmetMask
						union
							kit1.RoundSeg 0.75 0.5 0.25 0.5 0 0 1
							kit1.ArcHV ( 4 / 16) 0.5 ( 2 / 16) (5 / 8) 0 0 1
							kit1.ArcHV ( 6 / 16) 0.5 ( 4 / 16) (5 / 8) 0 0 1
							kit1.ArcHV ( 8 / 16) 0.5 ( 6 / 16) (5 / 8) 0 0 1
							kit1.ArcHV (10 / 16) 0.5 ( 8 / 16) (5 / 8) 0 0 1
							kit1.ArcHV (12 / 16) 0.5 (10 / 16) (5 / 8) 0 0 1
							kit1.Arc   ( 2 / 16) (5 / 8) ( 6 / 16) (14 / 16) ( 2 / 16) (6 / 8) 0 0 1
							kit1.Arc   ( 4 / 16) (5 / 8) ( 8 / 16) (14 / 16) ( 4 / 16) (6 / 8) 0 0 1
							kit1.Arc   ( 6 / 16) (5 / 8) (10 / 16) (14 / 16) ( 6 / 16) (6 / 8) 0 0 1
							kit1.Arc   ( 8 / 16) (5 / 8) (12 / 16) (14 / 16) ( 8 / 16) (6 / 8) 0 0 1
							kit1.Arc   (10 / 16) (5 / 8) (14 / 16) (14 / 16) (10 / 16) (6 / 8) 0 0 1

				# Body
				include : union
					difference
						union
							kit1.ArcVH (12 / 16) ( 8 / 16) ( 7 / 16) ( 4 / 16) 0 0 1
							kit1.ArcHV ( 7 / 16) ( 4 / 16) ( 3 / 16) ( 6 / 16) 0 0 1
							kit1.Arc   ( 3 / 16) ( 6 / 16) ( 4 / 16) ( 8 / 16) ( 3 / 16) ( 7 / 16) 0 0 1
						kit1.ArcHV ( 7 / 16) ( 6 / 16) ( 4 / 16) ( 8 / 16) 0 0 1 1
					intersection [MaskBelow : box.mixY 0.5]
						kit1.Arc (12 / 16) ( 8 / 16) ( 7 / 16) ( 6 / 16) ( 9 / 16) ( 6 / 16) 0 0 1
					kit1.ArcHV ( 7 / 16) ( 6 / 16) ( 4 / 16) ( 8 / 16) 0 0 1

				# Limbs
				include : difference
					union
						# Left Arm
						kit1.RoundSeg 1 0.5 (5 / 8) 0.5 0 0 (-1)
						kit1.RoundSeg 1 0.5 (5 / 8) 0.5 0 0 (-3)
						kit1.RoundSeg 1 0.5 1 [Math.min (17 / 32) : 8 / 16 + 2 * sw1 / (top - bot)] 0 1 (-3)
						# Right Arm
						kit3.RoundSeg (0 / 16) (7 / 16) (4 / 16) ( 7 / 16) 1 0 1
						kit3.RoundSeg (0 / 16) (7 / 16) (4 / 16) ( 7 / 16) 1 0 3
						kit3.RoundSeg (1 / 32) (7 / 16) (1 / 32) [Math.min (15 / 32) : 7 / 16 + 2 * sw1 / (top - bot)] 0 1 1
						# Leg
						kit1.RoundSeg (8 / 16) 0 (8 / 16) (5 / 16) 0 0 1
						kit1.RoundSeg (7 / 16) 0 (7 / 16) (5 / 16) 0 0 (-1)
					union
						kit1.ArcVH (12 / 16) ( 8 / 16) ( 7 / 16) ( 4 / 16) 0 0 1 1
						kit1.ArcHV ( 7 / 16) ( 4 / 16) ( 3 / 16) ( 6 / 16) 0 0 1 1
						kit1.Arc   ( 3 / 16) ( 6 / 16) ( 4 / 16) ( 8 / 16) ( 3 / 16) (7 / 16) 0 0 1 1
						kit1.Box   ( 4 / 16) ( 6 / 16) ( 8 / 16) ( 8 / 16)

				# Feet
				include : difference
					spiro-outline
						corner left bot
						g4     [box.mixX : 1 / 4] (bot + sw2)
						g4     [box.mixX : 2 / 4] (bot + 0.99 * sw2)
						g4     [box.mixX : 3 / 4] (bot + sw2)
						corner [box.mixX : 7 / 8]  bot
					intersection [MaskRight : box.mixX : 7 / 16] [MaskLeft : box.mixX : 1 / 2]

			create-glyph : glyph-proc
				set-width MosaicWidth
				include : ForceUpright
				include : multicell.Split top bottom left right 2 2 StandingKnight : list
					list 1 0 [MangleName 'standingknightLT'] [MangleUnicode 0x1CCD2]
					list 1 1 [MangleName 'standingknightRT'] [MangleUnicode 0x1CCD3]
					list 0 0 [MangleName 'standingknightLB'] [MangleUnicode 0x1CCD4]
					list 0 1 [MangleName 'standingknightRB'] [MangleUnicode 0x1CCD5]
