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

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

glyph-module

glyph-block Symbol-Pictograph-Schematic : for-width-kinds WideWidth4 : begin
	glyph-block-import CommonShapes
	glyph-block-import Common-Derivatives
	glyph-block-import Shared-Symbol-Shapes : TriangleShape
	glyph-block-import Symbol-Geometric-Shared : GeometricDim

	define top     fontMetrics.os2.sTypoAscender
	define bottom  fontMetrics.os2.sTypoDescender
	define left    0
	define right   MosaicWidth

	define midx : mix left right 0.5
	define midy : mix bottom top 0.5
	define MosaicHeight : top - bottom

	define Geom : GeometricDim MosaicUnitWidth MosaicWidth

	define boxDrawingStroke : AdviceStroke 3.5
	define fineStroke : AdviceStroke 3.5 : Math.sqrt (MosaicWidthScalar / 2)

	define gateSize : MosaicHeight / 4 * MosaicWidthScalar
	define gateBot : midy - gateSize
	define gateTop : midy + gateSize
	define ringSize : Math.min (Geom.Size * 0.5) (MosaicWidth / 6)
	define [InvertRingAt x y fMask] : [if fMask spiro-outline dispiro]
		if fMask {} : list
			widths.rhs fineStroke
		g4 x (y - ringSize)
		archv 32 2.0
		g4 (x - ringSize) y
		arcvh 32 2.0
		g4 x (y + ringSize)
		archv 32 2.0
		g4 (x + ringSize) y
		arcvh 32 2.0
		close

	do "Monostable and Bell"
		create-glyph [MangleName 'monostable'] [MangleUnicode 0x238D] : glyph-proc
			set-width MosaicWidth
			include : HBar.b Geom.Left (Geom.MidX - Geom.Size * 0.5) Geom.Bot boxDrawingStroke
			include : VBar.m (Geom.MidX - Geom.Size * 0.5) Geom.Bot Geom.Top boxDrawingStroke
			include : HBar.t (Geom.MidX - Geom.Size * 0.5) (Geom.MidX + Geom.Size * 0.5) Geom.Top boxDrawingStroke
			include : VBar.m (Geom.MidX + Geom.Size * 0.5) Geom.Bot Geom.Top boxDrawingStroke
			include : HBar.b (Geom.MidX + Geom.Size * 0.5) Geom.Right Geom.Bot boxDrawingStroke

		create-glyph [MangleName 'bellSymbol'] [MangleUnicode 0x237E] : glyph-proc
			set-width MosaicWidth
			include : intersection
				MaskBelow Geom.MidY
				refer-glyph : MangleName 'monostable'
			include : with-transform
				ApparentTranslate 0 (Geom.Size / 2)
				refer-glyph : MangleName 'segment'

	do "Fuse"
		create-glyph [MangleName 'fuse'] [MangleUnicode 0x23DB] : glyph-proc
			include [refer-glyph : MangleName : NameUni 0x2500] AS_BASE ALSO_METRICS
			include : refer-glyph : MangleName 'whiteHoriRectangle'

	do "Earth Ground"
		create-glyph [MangleName 'earthGround'] [MangleUnicode 0x23DA] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : VBar.m midx midy top boxDrawingStroke
			include : HBar.m Geom.Left Geom.Right midy boxDrawingStroke
			include : HBar.m (Geom.MidX - Geom.Size * 0.6) (Geom.MidX + Geom.Size * 0.6) [mix bottom top 0.4] boxDrawingStroke
			include : HBar.m (Geom.MidX - Geom.Size * 0.3) (Geom.MidX + Geom.Size * 0.3) [mix bottom top 0.3] boxDrawingStroke

	do "Explosion at Horizon"
		define horizon : Geom.MidY - Geom.Size * 0.8
		create-glyph [MangleName 'explosionHorizon'] [MangleUnicode 0x1CE02] : glyph-proc
			set-width MosaicWidth
			include : HBar.m Geom.Left Geom.Right horizon boxDrawingStroke
			include : dispiro
				widths.center fineStroke
				corner (Geom.MidX - Geom.Size * 0.8) (horizon + Geom.Size * 0.7)
				corner (Geom.MidX - Geom.Size * 0.4) (horizon + Geom.Size * 0.3)
			include : dispiro
				widths.center fineStroke
				corner (Geom.MidX + Geom.Size * 0.8) (horizon + Geom.Size * 0.7)
				corner (Geom.MidX + Geom.Size * 0.4) (horizon + Geom.Size * 0.3)
			include : dispiro
				widths.center fineStroke
				corner (Geom.MidX - Geom.Size * 0.4) (horizon + Geom.Size * 1.4)
				corner (Geom.MidX - Geom.Size * 0.2) (horizon + Geom.Size * 0.4)
			include : dispiro
				widths.center fineStroke
				corner (Geom.MidX + Geom.Size * 0.4) (horizon + Geom.Size * 1.4)
				corner (Geom.MidX + Geom.Size * 0.2) (horizon + Geom.Size * 0.4)

	do "Funnel"
		create-glyph [MangleName 'funnel'] [MangleUnicode 0x1CE08] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : TriangleShape Geom.Left Geom.Top Geom.Right Geom.Top Geom.MidX Geom.Bot boxDrawingStroke
			include : VBar.m midx bottom (Geom.Bot + boxDrawingStroke * 2) boxDrawingStroke

	do "Antenna"
		define rodLeft  : Geom.Left  + [HSwToV : boxDrawingStroke / 2]
		define rodRight : Geom.Right - [HSwToV : boxDrawingStroke / 2]
		define rodTop Geom.Top
		create-glyph [MangleName 'antenna'] [MangleUnicode 0x1CC08] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : VBar.m midx bottom rodTop boxDrawingStroke
			include : intersection
				MaskBelow rodTop
				union
					dispiro
						widths.center boxDrawingStroke
						corner [mix midx rodLeft 2] [mix midy rodTop 2]
						corner midx midy
					dispiro
						widths.center boxDrawingStroke
						corner [mix midx rodRight 2] [mix midy rodTop 2]
						corner midx midy

	do "Resistor"
		glyph-block-import Shared-Symbol-Shapes : HZigzag VZigzag
		define amplitude : Geom.Size * 0.8
		define vWaves 2
		define hWaves MosaicWidthScalar

		create-glyph [MangleName 'resistorHori'] [MangleUnicode 0x1CC09] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			local segs : 2 * hWaves
			local mask : (right - left) / (segs * 2)
			include : difference
				HZigzag.fromCenter midy left right amplitude segs 0 boxDrawingStroke 1
				MaskLeftLine  (left + mask) bottom (left + mask) (midy - boxDrawingStroke / 2)
				MaskRightLine (right - mask) (midy + boxDrawingStroke / 2) (right - mask) top

		create-glyph [MangleName 'resistorVert'] [MangleUnicode 0x1CC0A] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			local segs : 2 * vWaves
			local mask : (top - bottom) / (segs * 2)
			include : difference
				VZigzag.fromCenter midx bottom top amplitude segs 0 boxDrawingStroke 1
				MaskBelowLine left (bottom + mask) (midx - [HSwToV : boxDrawingStroke / 2]) (bottom + mask)
				MaskAboveLine (midx + [HSwToV : boxDrawingStroke / 2]) (top - mask) right (top - mask)

	do "Coil"
		glyph-block-import Symbol-Mosaic-Split-Graphic : Multicell
		local multicell : Multicell MosaicWidth

		define amplitude : Geom.Size * 0.8

		define [CoilImpl top bot left right] : begin
			local mid1 : mix left right (1 / 3)
			local mid2 : mix left right (2 / 3)
			local midy : mix bot top 0.5

			local yTerm : midy + boxDrawingStroke / 2
			local yTop : midy + amplitude
			local yBot : midy - amplitude
			local yInter : mix yBot yTop 0.95
			local ySide : mix yBot yTop 0.45
			local kX 0.1
			local kX2 0.15
			local kX3 : StrokeWidthBlend 0.24 0.21

			return : dispiro
				widths.rhs boxDrawingStroke
				straight.right.start left yTerm
				g4 [mix left mid1 kX3] [mix yTerm yTop 0.4]
				g4.right.mid [mix left mid1 (0.5 + kX2)] yTop
				g4 mid1 yInter
				g4.down.mid [mix mid1 mid2 (0.5 - kX)] ySide
				arch.rhs yBot (sw -- boxDrawingStroke)
				g4.up.mid [mix left mid1 (0.5 + kX)] ySide
				g4 mid1 yInter
				flat [mix mid1 mid2 (0.5 - kX2)] yTop
				curl [mix mid1 mid2 (0.5 + kX2)] yTop
				g4 mid2 yInter
				g4.down.mid [mix mid2 right (0.5 - kX)] ySide
				arch.rhs yBot (sw -- boxDrawingStroke)
				g4.up.mid [mix mid1 mid2 (0.5 + kX)] ySide
				g4 mid2 yInter
				g4.right.mid [mix mid2 right (0.5 - kX2)] yTop
				g4 [mix right mid2 kX3] [mix yTerm yTop 0.4]
				straight.right.end right yTerm

		create-glyph : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : multicell.Split top bottom left right 1 3 CoilImpl : list
				list 0 0 [MangleName 'inductorLeftThird']   [MangleUnicode 0x1CC0B]
				list 0 1 [MangleName 'inductorMiddleThird'] [MangleUnicode 0x1CC0C]
				list 0 2 [MangleName 'inductorRightThird']  [MangleUnicode 0x1CC0D]

	do "Diode"
		define diodeGap : MosaicWidth / 9
		define diodeLeft : left + diodeGap
		define diodeRight : right - diodeGap

		create-glyph [MangleName 'diodeLeft'] [MangleUnicode 0x1CC0E] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : HBar.m left diodeLeft midy boxDrawingStroke
			include : HBar.m diodeRight right midy boxDrawingStroke
			include : VBar.l diodeLeft gateBot gateTop boxDrawingStroke
			include : TriangleShape diodeLeft midy diodeRight gateTop diodeRight gateBot boxDrawingStroke

		create-glyph [MangleName 'diodeRight'] [MangleUnicode 0x1CC0F] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : HBar.m left diodeLeft midy boxDrawingStroke
			include : HBar.m diodeRight right midy boxDrawingStroke
			include : VBar.r diodeRight gateBot gateTop boxDrawingStroke
			include : TriangleShape diodeLeft gateBot diodeLeft gateTop diodeRight midy boxDrawingStroke

	do "Transistor"
		local slope : MosaicHeight / MosaicWidth
		local tipDx : Math.max (Geom.Size / 5) (boxDrawingStroke / slope)
		local tipDy : tipDx * (-slope)
		local baseDx : -tipDy / [Math.sqrt 3] * 2
		local baseDy : baseDx / (-slope)
		define arrowPos : (1 - [HSwToV boxDrawingStroke] / MosaicMiddle) * 0.4

		define [VerticalPart] : intersection
			Rect top bottom left (midx + [HSwToV : 0.5 * boxDrawingStroke])
			union
				ExtLineCenter 1 boxDrawingStroke midx bottom left midy
				ExtLineCenter 1 boxDrawingStroke left midy midx top

		create-glyph [MangleName 'transistorPNP'] [MangleUnicode 0x1CC10] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : VBar.l left gateBot gateTop boxDrawingStroke
			include : VerticalPart

			local arrowCx : mix midx left arrowPos
			local arrowCy : mix bottom midy arrowPos
			include : spiro-outline
				corner (arrowCx + tipDx) (arrowCy + tipDy)
				corner (arrowCx - tipDx - baseDx) (arrowCy - tipDy + baseDy)
				corner (arrowCx - tipDx + baseDx) (arrowCy - tipDy - baseDy)

		create-glyph [MangleName 'transistorNPN'] [MangleUnicode 0x1CC11] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : VBar.l left gateBot gateTop boxDrawingStroke
			include : VerticalPart

			local arrowCx : mix midx left arrowPos
			local arrowCy : mix top midy arrowPos
			include : spiro-outline
				corner (arrowCx - tipDx) (arrowCy + tipDy)
				corner (arrowCx + tipDx - baseDx) (arrowCy - tipDy - baseDy)
				corner (arrowCx + tipDx + baseDx) (arrowCy - tipDy + baseDy)

	do "Receptacle"
		create-glyph [MangleName 'receptacle'] [MangleUnicode 0x1CC12] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : refer-glyph : MangleName : NameUni 0x1FBDB
			include : refer-glyph : MangleName : NameUni 0x2576

	do "Capacitor"
		define capacitorSize Geom.Size
		define capacitorGap : Geom.Size / 4

		create-glyph [MangleName 'capacitorHori'] [MangleUnicode 0x1CC13] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : HBar.m left (midx - capacitorGap) midy boxDrawingStroke
			include : VBar.r (midx - capacitorGap) (midy - capacitorSize) (midy + capacitorSize) boxDrawingStroke
			include : VBar.l (midx + capacitorGap) (midy - capacitorSize) (midy + capacitorSize) boxDrawingStroke
			include : HBar.m (midx + capacitorGap) right midy boxDrawingStroke

		create-glyph [MangleName 'capacitorVert'] [MangleUnicode 0x1CC14] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : VBar.m midx bottom (midy - capacitorGap) boxDrawingStroke
			include : HBar.t (midx - capacitorSize) (midx + capacitorSize) (midy - capacitorGap) boxDrawingStroke
			include : HBar.b (midx - capacitorSize) (midx + capacitorSize) (midy + capacitorGap) boxDrawingStroke
			include : VBar.m midx (midy + capacitorGap) top boxDrawingStroke

	do "Rings"
		create-glyph [MangleName 'twoRings'] [MangleUnicode 0x1CC88] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : InvertRingAt (left + ringSize) midy
			include : InvertRingAt (right - ringSize) midy

		define [InvertedInputImpl spread] : glyph-proc
			local limit : MosaicHeight / 2 - ringSize
			local spread2 : Math.min (spread - boxDrawingStroke / 2) limit

			include : InvertRingAt (right - ringSize) (midy + spread2)
			include : InvertRingAt (right - ringSize) (midy - spread2)

			if (spread >= MosaicHeight / 2) : begin
				include : difference
					HBar.t left (right - ringSize) top boxDrawingStroke
					InvertRingAt (right - ringSize) (midy + spread2) 1
				include : difference
					HBar.b left (right - ringSize) bottom boxDrawingStroke
					InvertRingAt (right - ringSize) (midy - spread2) 1
			: else : begin
				include : HBar.t left midx top boxDrawingStroke
				include : HBar.b left midx bottom boxDrawingStroke
				include : VBar.m midx (midy + spread - boxDrawingStroke) top    boxDrawingStroke
				include : VBar.m midx bottom (midy - spread + boxDrawingStroke) boxDrawingStroke
				include : difference
					HBar.t midx (right - ringSize) (midy + spread) boxDrawingStroke
					InvertRingAt (right - ringSize) (midy + spread2) 1
				include : difference
					HBar.b midx (right - ringSize) (midy - spread) boxDrawingStroke
					InvertRingAt (right - ringSize) (midy - spread2) 1

		create-glyph [MangleName 'invertedInputs'] [MangleUnicode 0x1CC17] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : InvertedInputImpl (gateSize - [if (MosaicWidthScalar < 2) (ringSize - boxDrawingStroke / 2) 0])

		create-glyph [MangleName 'invertedOutput'] [MangleUnicode 0x1CC18] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : InvertRingAt (left + ringSize) midy
			include : HBar.m (left + ringSize * 2 - fineStroke / 2) right midy boxDrawingStroke

	do "Buffer"
		create-glyph [MangleName 'bufferGate'] [MangleUnicode 0x1CC19] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : HBar.m left midx midy boxDrawingStroke
			include : TriangleShape midx gateBot midx gateTop right midy boxDrawingStroke

		create-glyph [MangleName 'invertedBufferGate'] [MangleUnicode 0x1CC1A] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : HBar.m left (midx - ringSize * 2 + fineStroke / 2) midy boxDrawingStroke
			include : InvertRingAt (midx - ringSize) midy
			include : TriangleShape midx gateBot midx gateTop right midy boxDrawingStroke

	do "Logic Gates"
		define andCurlX : Math.max midx (right - gateSize)
		define leftOX : left - OX
		define orCurlX1 : mix leftOX right 0.15
		define orCurlX2 : mix leftOX right 0.4

		create-glyph [MangleName 'andGate'] [MangleUnicode 0x1CC16] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : VBar.l left gateBot gateTop boxDrawingStroke

			include : dispiro
				widths.lhs boxDrawingStroke
				flat left gateBot
				curl (right - andCurlX) gateBot
				archv
				g4 right midy
				arcvh
				flat (right - andCurlX) gateTop
				corner left gateTop

		create-glyph [MangleName 'orGate'] [MangleUnicode 0x1CC15] : glyph-proc
			set-width MosaicWidth
			include : ForceUpright
			include : intersection [Rect gateTop gateBot leftOX right]
				dispiro
					widths.lhs boxDrawingStroke
					g4 leftOX gateTop
					quadControls 1 0.3
					g4 orCurlX1 midy
					quadControls 0 0.7
					g4 leftOX gateBot
			include : difference
				union
					intersection [MaskBelow midy] : dispiro
						widths.lhs boxDrawingStroke
						flat leftOX gateBot
						curl orCurlX2 gateBot
						quadControls 0.7 0
						g4 right midy
					intersection [MaskAbove midy] : dispiro
						widths.rhs boxDrawingStroke
						flat leftOX gateTop
						curl orCurlX2 gateTop
						quadControls 0.7 0
						g4 right midy
				spiro-outline
					g4 leftOX gateTop
					quadControls 1 0.3
					g4 orCurlX1 midy
					quadControls 0 0.7
					g4 leftOX gateBot
					close
