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

import [mix linreg clamp fallback] from '../support/utils'
import [designParameters] from '../meta/aesthetics'

export : define [apply] : begin
	glyph-module-entry commonShapes overmarks letterBasic
	# spaces
	# we set the width of emquad to 1000mem (1em) and the width of emspace to WIDTH (0.5em)
	### 'Spaces'
	alias 'enquad' 0x2000 'space'
	alias 'ensp' 0x2002 'space'
	alias 'threePerEmsp' 0x2004 'space'
	alias 'fourPerEmsp' 0x2005 'space'
	alias 'sixPerEmsp' 0x2006 'space'
	alias 'fgsp' 0x2007 'space'

	sketch # zwsp
		set-width 0
		set currentGlyph.cmpPriority (-9999)
		save 'zwsp' 0x200B

	sketch # nbsp
		include glyphs.space
		include markset.e
		set currentGlyph.cmpPriority (-100)
		save 'nbsp' 0xA0

	sketch # em-space
		set-width FULLWIDTH
		save 'emquad' 0x2001
		save 'emsp' 0x2003

	### 'Brackets'
	sketch # parenLeft
		include : dispiro
			widths.lhs
			g4 [mix SB RIGHTSB designParameters.parenInside] [mix parenMid parenTop (1 + designParameters.parenOvershoot)]
			quadcontrols 1 (1 - designParameters.parenCurliness)
			g4 [mix SB RIGHTSB designParameters.parenOutside] parenMid
			quadcontrols 0 designParameters.parenCurliness
			g4 [mix SB RIGHTSB designParameters.parenInside] [mix parenMid parenBot (1 + designParameters.parenOvershoot)]
		save 'parenLeft' '('

	sketch # parenRight
		include glyphs.parenLeft
		include : FlipAround MIDDLE parenMid
		save 'parenRight' ')'

	sketch # bracketLeft
		local l : mix SB RIGHTSB designParameters.bracketOutside
		local r : mix SB RIGHTSB designParameters.bracketInside

		include : HBarBottom l r parenBot
		include : HBarTop    l r parenTop
		include : VBarLeft   l parenBot parenTop
		save 'bracketLeft' '['

	sketch # bracketRight
		include glyphs.bracketLeft
		include : FlipAround MIDDLE parenMid
		save 'bracketRight' ']'

	sketch # braceLeft.straight
		local parenCenter [mix SB RIGHTSB [mix designParameters.braceInside designParameters.braceOutside 0.5]]
		local radius    : [mix SB RIGHTSB designParameters.braceInside] - parenCenter
		local top : mix parenMid parenTop (1 + designParameters.braceOvershoot)
		local bot : mix parenMid parenBot (1 + designParameters.braceOvershoot)

		include : dispiro
			straight.left.start [mix SB RIGHTSB designParameters.braceInside] (top - HALFSTROKE) [widths.heading HALFSTROKE HALFSTROKE LEFTWARD]
			archv
			flat parenCenter (top - radius) [heading DOWNWARD]
			curl parenCenter (parenMid + radius) [heading DOWNWARD]
			arcvh
			straight.left.end [mix SB RIGHTSB designParameters.braceOutside] parenMid [heading LEFTWARD]

		include : dispiro
			straight.left.start [mix SB RIGHTSB designParameters.braceInside] (bot + HALFSTROKE) [widths.heading HALFSTROKE HALFSTROKE LEFTWARD]
			archv
			flat parenCenter (bot + radius) [heading UPWARD]
			curl parenCenter (parenMid - radius) [heading UPWARD]
			arcvh
			straight.left.end [mix SB RIGHTSB designParameters.braceOutside] parenMid [heading LEFTWARD]
		save 'braceLeft.straight'

	sketch # braceLeft.curly
		local xIns : mix SB RIGHTSB [mix designParameters.braceOutside designParameters.braceInside 1]
		local xOus : mix SB RIGHTSB [mix designParameters.braceInside designParameters.braceOutside 1]
		local m1   : mix SB RIGHTSB [mix designParameters.braceInside designParameters.braceOutside designParameters.braceCurlyM1]
		local m2   : mix SB RIGHTSB [mix designParameters.braceInside designParameters.braceOutside designParameters.braceCurlyM2]
		local braceRadiusLowLimit : (parenTop - parenMid - STROKE) * (1 / 3) + HALFSTROKE
		local radius1 : Math.min (xIns - m1) braceRadiusLowLimit
		local radius2 : [Math.min (m2 - xOus) braceRadiusLowLimit] - HALFSTROKE
		local ess : mix STROKE ESS 0.25
		local top : mix parenMid parenTop (1 + designParameters.braceOvershoot)
		local bot : mix parenMid parenBot (1 + designParameters.braceOvershoot)
		include : dispiro
			straight.left.start xIns (top - HALFSTROKE) [widths.heading HALFSTROKE HALFSTROKE LEFTWARD]
			archv
			g4.down.mid m1 (top - radius1) [heading DOWNWARD]
			alsothru 0.5 0.5 [widths (ess / 2) (ess / 2)]
			g4.down.mid m2 (parenMid + radius2) [widths.heading HALFSTROKE HALFSTROKE DOWNWARD]
			arcvh
			straight.left.end xOus parenMid [heading LEFTWARD]

		include : dispiro
			straight.left.start xIns (bot + HALFSTROKE) [widths.heading HALFSTROKE HALFSTROKE LEFTWARD]
			archv
			g4.up.mid m1 (bot + radius1) [heading UPWARD]
			alsothru 0.5 0.5 [widths (ess / 2) (ess / 2)]
			g4.up.mid m2 (parenMid - radius2) [widths.heading HALFSTROKE HALFSTROKE UPWARD]
			arcvh
			straight.left.end xOus parenMid [heading LEFTWARD]
		save 'braceLeft.curly'

	composite 'braceRight.straight' glyphs.'braceLeft.straight' [FlipAround MIDDLE parenMid]
	composite 'braceRight.curly' glyphs.'braceLeft.curly' [FlipAround MIDDLE parenMid]
	
	select-variant 'braceLeft' '{' 'curly' {
		.cv36 'braceLeft.straight'
		.cv37 'braceLeft.curly'
	}
	select-variant 'braceRight' '}' 'curly' {
		.cv36 'braceRight.straight'
		.cv37 'braceRight.curly'
	}

	sketch # angleLeft
		local fatten : Math.hypot 1 (([mix SB RIGHTSB : designParameters.parenInside - designParameters.parenOutside] - O) / (parenTop - parenMid))
		include : dispiro
			widths.lhs OPERATORSTROKE
			flat [mix SB RIGHTSB designParameters.parenInside] parenTop
			curl ([mix SB RIGHTSB designParameters.parenOutside] + O) parenMid [widths.heading (OPERATORSTROKE * fatten) 0 DOWNWARD]
		include : dispiro
			widths.rhs OPERATORSTROKE
			flat [mix SB RIGHTSB designParameters.parenInside] parenBot
			curl ([mix SB RIGHTSB designParameters.parenOutside] + O) parenMid [widths.heading 0 (OPERATORSTROKE * fatten) UPWARD]
		save 'angleLeft' 0x2329
	alias 'mangleLeft' 0x27E8 'angleLeft'

	turned 'angleRight' 0x232A 'angleLeft' MIDDLE parenMid
	alias 'mangleRight' 0x27E9 'angleRight'

	dual 'dblangleLeft' 0x27EA 'angleLeft' (WIDTH * 0.35)
	dual 'dblangleRight' 0x27EB 'angleRight' (WIDTH * 0.35)

	sketch # ceilingLeft
		include : HBarTop    [mix SB RIGHTSB designParameters.bracketOutside] [mix SB RIGHTSB designParameters.bracketInside] parenTop
		include : VBarLeft   [mix SB RIGHTSB designParameters.bracketOutside] parenBot parenTop
		save 'ceilingLeft' 0x2308

	sketch # floorLeft
		include : HBarBottom [mix SB RIGHTSB designParameters.bracketOutside] [mix SB RIGHTSB designParameters.bracketInside] parenBot
		include : VBarLeft   [mix SB RIGHTSB designParameters.bracketOutside] parenBot parenTop
		save 'floorLeft' 0x230A
	turned 'floorRight' 0x230B 'ceilingLeft' MIDDLE parenMid
	turned 'ceilingRight' 0x2309 'floorLeft' MIDDLE parenMid

	### 'Small Punctuations'
	sketch # period
		set-width WIDTH
		include : Ring (PERIODSIZE - O) O (MIDDLE - PERIODRADIUS + O) (MIDDLE + PERIODRADIUS - O) true
		save 'period' '.'

	sketch # xhdot
		set-width WIDTH
		include : Ring (XH - O) (XH - PERIODSIZE + O) (MIDDLE - PERIODRADIUS + O) (MIDDLE + PERIODRADIUS - O) true
		save 'xhdot'

	sketch # comma
		set-width WIDTH
		include glyphs.period
		local sw : Math.min STROKE (PERIODSIZE * 0.5)
		include : dispiro
			widths.rhs sw
			g4 (MIDDLE + PERIODRADIUS - O) [mix O (PERIODSIZE - O) 0.5]
			g4 (MIDDLE + PERIODRADIUS - O + 0.1 * TANSLANT) ([mix O (PERIODSIZE - O) 0.5] - 0.1)
			quadcontrols (0.9 * TANSLANT * DESCENDER / (1.7 * PERIODRADIUS - O)) 0.5 12
			g4 [mix MIDDLE (MIDDLE - PERIODRADIUS) 0.3] DESCENDER
		save 'comma' ','

	sketch # invertComma
		set-width WIDTH
		include glyphs.period

		local sw : Math.min STROKE (PERIODSIZE * 0.5)
		include : dispiro
			widths.lhs sw
			g4 (MIDDLE - PERIODRADIUS + O) [mix O (PERIODSIZE - O) 0.5]
			g4 (MIDDLE - PERIODRADIUS + O + 0.1 * TANSLANT) ([mix O (PERIODSIZE - O) 0.5] - 0.1)
			quadcontrols (-0.3 * TANSLANT * DESCENDER / ((1.3 + TANSLANT * 2) * PERIODRADIUS - O)) 0.5 12
			g4 [mix MIDDLE (MIDDLE + PERIODRADIUS) (0.3 + TANSLANT * 2)] DESCENDER
		save 'invertComma'

	sketch # colon
		set-width WIDTH
		include glyphs.period
		include glyphs.xhdot
		save 'colon' ':'
		save 'colon.dmid'

		branch
			apply-transform : Upright
			apply-transform : Translate 0 (parenMid - XH / 2)
			apply-transform : Italify
			save 'colon.mid'
		branch
			local delta : Math.max 0 : WIDTH / 2 - (XH - PERIODSIZE) / 2
			apply-transform : Translate delta 0
			save 'colon.dright'
			apply-transform : Translate (-2 * delta) 0
			save 'colon.dleft'

	sketch # semicolon
		include glyphs.comma
		include glyphs.xhdot
		save 'semicolon' ';'
		save 'greekquestion' 0x37E

	### 'Emotion Punctuations'
	local questionBottom : Math.max (CAP * 0.3) (DOTSIZE * 1.5)

	define [QuestionShape top questionBottom left right] : glyph-construction
		include : dispiro
			widths.rhs
			g4 left (top - HOOK)
			hookstart (top - O)
			g4 right (top - SMOOTHB * 0.9)
			alsothru 0.5 0.45 [widths.center ESSQUESTION]
			straight.down.end ([mix left right 0.5] - HALFSTROKE * HVCONTRAST) questionBottom [widths STROKE 0]

	sketch # question
		set-width WIDTH
		include : QuestionShape CAP questionBottom SB RIGHTSB
		include : Ring (DOTSIZE - O) O (MIDDLE - DOTRADIUS + O) (MIDDLE + DOTRADIUS - O) true
		save 'question' '?'

	sketch # interrobang
		set-width WIDTH
		local angle : 12 / 180 * Math.PI
		include : QuestionShape CAP questionBottom [mix MIDDLE SB 0.75] RIGHTSB
		include : Translate (-MIDDLE) (-DOTRADIUS)
		include : Rotate (-2 * angle)
		include : Translate MIDDLE DOTRADIUS
		include : VBar MIDDLE questionBottom CAP
		include : Translate (-MIDDLE) (-DOTRADIUS)
		include : Rotate (1.2 * angle)
		include : Translate MIDDLE DOTRADIUS
		include : Ring (DOTSIZE - O) O (MIDDLE - DOTRADIUS + O) (MIDDLE + DOTRADIUS - O) true
		save 'interrobang' 0x203D

	sketch # dwquestion
		set-width UPM
		include : QuestionShape CAP questionBottom (UPM * 0.25) (UPM * 0.75)
		include : Ring (DOTSIZE - O) O (UPM / 2 - DOTRADIUS + O) (UPM / 2 + DOTRADIUS - O) true
		save 'dwquestion' 0xFF1F

	sketch # questionDown
		set-width WIDTH
		include glyphs.question
		include : FlipAround MIDDLE (XH / 2)
		save 'questionDown' 0xBF

	sketch # exclam
		set-width WIDTH
		include markset.capital
		include : VBar MIDDLE [clamp 0 (CAP * 0.4) (questionBottom * 1.18)] CAP
		include : Ring (DOTSIZE - O) O (MIDDLE - DOTRADIUS + O) (MIDDLE + DOTRADIUS - O) true
		save 'exclam' '!'

	sketch # exclamDown
		set-width WIDTH
		include glyphs.exclam
		include : FlipAround MIDDLE (XH / 2)
		save 'exclamDown' 0xA1

	sketch # doubleexclam
		local d : 0.25 * WIDTH
		include glyphs.exclam
		apply-transform : Translate (-d * 2) 0
		include glyphs.exclam
		apply-transform : Translate d 0
		save 'doubleexclam' 0x203C

	sketch # bar
		set-width WIDTH
		set currentGlyph.anchors.above {.type BASE .x MIDDLE .y parenTop}
		set currentGlyph.anchors.below {.type BASE .x MIDDLE .y parenBot}
		include : VBar MIDDLE parenBot parenTop
		save 'bar' '|'

	sketch # brokenbar
		local breakDist : Math.max STROKE (CAP / 8)
		include : VBar MIDDLE (parenMid + breakDist / 2) parenTop
		include : VBar MIDDLE parenBot (parenMid - breakDist / 2)
		save 'brokenbar' 0xA6

	# Click symbols
	alias 'dentalclick' 0x1C0 'bar'
	dual 'alveolarlateralclick' 0x1C1 'bar' (WIDTH * 0.35)
	alias 'alveolarclick' 0x1C3 'exclam'

	sketch # palatoalveolarclick
		include glyphs.bar AS_BASE
		include : HBarBottom SB RIGHTSB (parenMid + XH * 0.1) OPERATORSTROKE
		include : HBarTop SB RIGHTSB (parenMid - XH * 0.1) OPERATORSTROKE
		save 'palatoalveolarclick' 0x1C2

	### 'Typographic Symbols'
	sketch # ampersand
		set-width WIDTH

		local fine : adviceBlackness 3
		local p 0.875
		local l 0.05
		local pr [linreg 500 0.82 700 0.85 WIDTH]
		local rr 0.95
		local q 0.45
		local r 1.1

		include : dispiro
			widths.rhs fine
			flat (RIGHTSB - O) CAPMIDDLE [heading DOWNWARD]
			curl (RIGHTSB - O) SMOOTHA
			arcvh
			g4   (MIDDLE + CORRECTION_OMIDX * fine) O
			archv
			g4   (SB + O) SMOOTHB
			alsothru 0.5 0.5 [widths.center fine]
			g4   [mix SB RIGHTSB p] (CAP - SMOOTHB * pr) [widths.lhs fine]
			arcvh
			g4   ([mix SB RIGHTSB [mix p l 0.5]] - CORRECTION_OMIDX * fine) (CAP - O)
			archv
			g4   [mix SB RIGHTSB l] (CAP - SMOOTHA * pr)
			alsothru 0.5 0.5 [widths.center fine]
			g4.down.end [mix SB RIGHTSB r] 0 [widths.heading 0 fine DOWNWARD]
		save 'ampersand' '&'

	sketch # at.long
		set-width WIDTH

		local top parenTop
		local bot parenBot
		local otop : mix bot top 0.75
		local obot : mix top bot 0.8

		local sw : adviceBlackness 3.5
		local m1 : [mix (SB + sw) (RIGHTSB - sw) 0.47] - sw / 2
		local m2 : [mix m1 RIGHTSB 0.52] + TANSLANT * sw

		local sma : SMOOTHA * ((RIGHTSB - m1) / (RIGHTSB - SB) * 1.1)
		local smb : SMOOTHB * ((RIGHTSB - m1) / (RIGHTSB - SB) * 1.1)

		include : dispiro
			widths.lhs sw
			flat RIGHTSB (otop - O) [heading LEFTWARD]
			curl m2 (otop - O)
			archv
			flat m1 (otop - sma)
			curl m1 (obot + smb)
			arcvh
			g4   m2 (obot + O)
			archv
			flat RIGHTSB (obot + sma)
			curl RIGHTSB (top - SMOOTHB)
			arcvh
			g4   (MIDDLE - CORRECTION_OMIDS) (top - O) [widths STROKE 0]
			archv
			flat SB (top - SMOOTHA) [widths sw 0]
			curl SB (bot + SMOOTHB)
			arcvh
			flat (MIDDLE + CORRECTION_OMIDS) (bot + O) [widths STROKE 0 ]
			curl (RIGHTSB - HALFSTROKE + TANSLANT * sw) (bot + O)
		save 'at.long'

	sketch # at.tight
		set-width WIDTH

		local top parenTop
		local bot parenBot
		local otop : mix bot top 0.75
		local obot : mix top bot 0.8

		local sw : adviceBlackness 4
		local swh : adviceBlackness 3.75
		local left : SB - sw * HVCONTRAST / 3
		local right : RIGHTSB + sw * HVCONTRAST / 3

		local m1 : [mix (left + sw / 2) (right - sw / 2) (1 / 3)] - sw * HVCONTRAST / 2
		local m2 : [mix (left + sw / 2) (right - sw / 2) (2 / 3)] + sw * HVCONTRAST / 2

		local sma : SMOOTHA * ((m2 - m1) / (RIGHTSB - SB) * 1.1)
		local smb : SMOOTHB * ((m2 - m1) / (RIGHTSB - SB) * 1.1)

		include : dispiro
			widths.lhs sw
			flat m2 (obot - O) [heading UPWARD]
			curl m2 (otop - smb)
			arcvh
			g4   (MIDDLE - CORRECTION_OMIDX * sw) (otop - O)
			archv
			flat m1 (otop - sma)
			curl m1 (obot + smb)
			arcvh
			flat MIDDLE obot
			curl (right - (m2 - m1) / 2) obot
			archv
			flat right (obot + sma)
			curl right (top - SMOOTHB)
			arcvh
			g4   (MIDDLE - CORRECTION_OMIDS) (top - O) [widths swh 0]
			archv
			flat left (top - SMOOTHA) [widths sw 0]
			curl left (bot + SMOOTHB)
			arcvh
			flat (MIDDLE + CORRECTION_OMIDS) (bot + O) [widths swh 0 ]
			curl (right - HALFSTROKE + TANSLANT * sw) (bot + O)
		save 'at.fourfold'

	sketch # at.short
		set-width WIDTH

		local top operTop
		local obot operBot
		local otop [mix obot top 0.675]

		local sw : adviceBlackness 3.5
		local m1 : [mix (SB + sw) (RIGHTSB - sw) 0.53] + sw / 2
		local m2 : [mix SB m1 0.5] + TANSLANT * sw

		local sma : SMOOTHA * ((m1 - SB) / (RIGHTSB - SB) * 1.1)
		local smb : SMOOTHB * ((m1 - SB) / (RIGHTSB - SB) * 1.1)
		local atTurnBot (obot - sma / 4)

		local shrink 0.6

		include : dispiro
			straight.up.start (m1 - (sw * (1 - shrink) * HVCONTRAST)) (otop - smb) [widths.heading (sw * shrink) 0 UPWARD]
			arcvh
			g4 (m2 - sw * TANSLANT) (otop - O) [widths.heading sw 0 LEFTWARD]
			archv
			flat SB (otop - sma)
			curl SB (obot + smb)
			arcvh
			g4 (m2 - sw * TANSLANT) (obot + O) [heading RIGHTWARD]
			archv
			straight.up.end (m1 - (sw * (1 - shrink) * HVCONTRAST)) (obot + sma) [widths.heading (sw * shrink) 0 UPWARD]
		
		include : dispiro
			widths.lhs sw
			corner m1 (atTurnBot + sma) [heading UPWARD]
			corner m1 (otop - smb) [heading UPWARD]
			corner m1 otop [widths.heading (sw * shrink) 0 UPWARD]
		
		include : dispiro
			widths.lhs (sw * shrink)
			straight.down.start (m1 - sw * shrink * HVCONTRAST) (atTurnBot + sma) [heading DOWNWARD]
			arcvh
			g4 ([mix (m1 - sw * HVCONTRAST) RIGHTSB 0.5] + CORRECTION_OMIDX * sw) (atTurnBot + O) [widths.lhs sw]
			archv
			flat RIGHTSB (atTurnBot + sma)
			curl RIGHTSB (top - SMOOTHB)
			hookend (top - O)
			g4 SB (top - HOOK)

		save 'at.short'
	
	select-variant 'at' '@' 'short' {
		.cv31 'at.long'
		.cv32 'at.fourfold'
		.cv33 'at.short'
	}

	sketch # paragraph
		set-width WIDTH
		local sw : adviceBlackness 3.6
		include : dispiro
			widths.center sw
			straight.left.start (MIDDLE - sw / 4) (CAP - sw / 2) [heading LEFTWARD]
			archv
			g4.down.mid (SB + sw / 2) [mix (CAP * 0.5) (CAP - sw / 2) 0.5] [heading DOWNWARD]
			arcvh
			straight.right.end (MIDDLE - sw / 4) (CAP * 0.5) [heading RIGHTWARD]

		branch
			include : VBar (MIDDLE + sw / 4) 0 CAP sw
			include : VBar (RIGHTSB - sw / 2) 0 CAP sw
			save 'paragraph.high'
		branch
			include : VBar (MIDDLE + sw / 4) DESCENDER CAP sw
			include : VBar (RIGHTSB - sw / 2) DESCENDER CAP sw
			save 'paragraph.low'

	select-variant 'paragraph' 0xB6 'high' {
		.cv22 'paragraph.high'
		.cv23 'paragraph.low'
	}

	sketch # section
		local top parenTop
		local bot parenBot
		local sma SMOOTHA
		local s : dispiro
			widths.lhs
			g4 RIGHTSB (top - HOOK)
			hookstart top
			g4 SB (top - sma)
			alsothru 0.5 0.5 [widths HALFSTROKE HALFSTROKE]
			g4 RIGHTSB [mix bot top 0.501] [widths 0 STROKE]
			g4 RIGHTSB [mix bot top 0.5] [widths 0 STROKE]
			g4 [mix SB RIGHTSB 0.6] [mix bot top : [linreg 18 0.325 108 0.3 STROKE] * (1 - TANSLANT * 0.1)]
		include s
		include : FlipAround MIDDLE parenMid
		include s
		save 'section' 0xA7

	local asteriskCenterY : parenTop - LONGJUT * 1.5

	foreach [{size name} : items-of {{1.2 'asterisk.high'} {0.85 'smallasterisk.high'}}] : sketch
		local radius : LONGJUT * size
		local fine : STROKE * 0.4
		local final : 0.5 * [Math.min STROKE (radius * Math.PI * 2 / 10)]

		foreach j [range 0 5] : begin
			local s : Math.sin (j / 5 * Math.PI * 2)
			local c : Math.cos (j / 5 * Math.PI * 2)
			include : dispiro
				flat MIDDLE asteriskCenterY [widths fine fine]
				curl (MIDDLE + radius * s) (asteriskCenterY + radius * c) [widths final final]
		save name

	composite 'asterisk.low' glyphs.'asterisk.high' [Upright] [Translate 0 (parenMid - asteriskCenterY)] [Italify]
	composite 'smallasterisk.low' glyphs.'smallasterisk.high' [Upright] [Translate 0 (parenMid - asteriskCenterY)] [Italify]
	select-variant 'asterisk' '*' 'high' {
		.cv18 'asterisk.high'
		.cv19 'asterisk.low'
	}

	sketch # numbersign
		local fine : adviceBlackness 3.5
		include : HBar SB RIGHTSB [mix parenTop parenBot (1 / 3)]
		include : HBar SB RIGHTSB [mix parenTop parenBot (2 / 3)]
		include : VBar [mix SB RIGHTSB 0.3] (parenBot + fine) (parenTop - fine) fine
		include : VBar [mix SB RIGHTSB 0.7] (parenBot + fine) (parenTop - fine) fine
		save 'numbersign' '#'

	# Slashes
	define slashDefautLeft   : SB + HALFSTROKE
	define slashDefaultRight : RIGHTSB - HALFSTROKE
	define [SlashShape l r] : glyph-construction
		local cor : (1 / 2) * HVCONTRAST / [Math.sqrt (1 - [Math.pow ((r - l - STROKE) / (parenTop - parenBot)) 2])]
		start-from (l - STROKE * cor) parenBot
		line-to    (l + STROKE * cor) parenBot
		line-to    (r + STROKE * cor) parenTop
		line-to    (r - STROKE * cor) parenTop
		reverse-last

	sketch # slash
		include : SlashShape slashDefautLeft slashDefaultRight
		save 'slash' '/'
		save 'solidus' 0x2044
	sketch # slash.left
		include : SlashShape slashDefautLeft WIDTH
		save 'slash.left'
	sketch # slash.right
		include : SlashShape 0 slashDefaultRight
		save 'slash.right'

	define [BackslashShape l r] : glyph-construction
		local cor : (1 / 2) * HVCONTRAST / [Math.sqrt (1 - [Math.pow ((r - l - STROKE) / (parenTop - parenBot)) 2])]
		start-from (l - STROKE * cor) parenTop
		line-to    (l + STROKE * cor) parenTop
		line-to    (r + STROKE * cor) parenBot
		line-to    (r - STROKE * cor) parenBot
	local backslashWidth : (slashDefaultRight - slashDefautLeft) * (1 + TANSLANT * 2)
	sketch # backslash
		include : BackslashShape (MIDDLE - backslashWidth / 2) (MIDDLE + backslashWidth / 2)
		save 'backslash' "\\"
	sketch # backslash.left
		include : BackslashShape (MIDDLE - backslashWidth / 2) WIDTH
		save 'backslash.left'
	sketch # backslash.right
		include : BackslashShape 0 (MIDDLE + backslashWidth / 2)
		save 'backslash.right'


	### 'Dashes'
	sketch # underscore.high
		set-width WIDTH
		include : HBarBottom SB RIGHTSB 0
		save 'underscore.high'

	composite 'underscore.low' glyphs.'underscore.high' [Upright] [Translate 0 (DESCENDER * 0.9)] [Italify]
	select-variant 'underscore' '_' 'high' {
		.cv20 'underscore.high'
		.cv21 'underscore.low'
	}

	sketch # overline
		include : HBarTop SB RIGHTSB CAP
		save 'overline' 0x203E

	sketch # hyphen
		set-width WIDTH
		include : HBar SB RIGHTSB parenMid
		save 'hyphen' '-'

	sketch # softhyphen
		include glyphs.hyphen AS_BASE
		save 'softhyphen' 0xAD
	alias 'gpHyphen' 0x2010 'hyphen'
	alias 'nbHyphen' 0x2011 'hyphen'
	alias 'figureDash' 0x2012 'hyphen'
	alias 'enDash' 0x2013 'hyphen'

	sketch # emDash
		set-width FULLWIDTH
		include : HBar 0 FULLWIDTH parenMid
		save 'emDash' 0x2014

	sketch # doubleEmDash
		set-width (FULLWIDTH * 2)
		include : HBar 0 (FULLWIDTH * 2) parenMid
		save 'doubleEmDash'

	alias 'horizontalBar' 0x2015 'emDash'


	### 'Interpuncts'
	sketch # interpunct
		set-width FULLWIDTH
		include : Ring (parenMid + PERIODRADIUS - O) (parenMid - PERIODRADIUS + O) (FWMIDDLE - PERIODRADIUS + O) (FWMIDDLE + PERIODRADIUS - O) true
		save 'period.center'
		save 'interpunct' 0xB7
		save 'greekbullet' 0x387
		save 'bullet' 0x2022
		save 'hyphenpoint' 0x2027

	sketch # whitebullet
		set-width FULLWIDTH
		local s : [adviceBlackness 5] * 0.75
		include : Ring (parenMid + PERIODRADIUS - O) (parenMid - PERIODRADIUS + O) (FWMIDDLE - PERIODRADIUS + O) (FWMIDDLE + PERIODRADIUS - O) true
		include : Ring (parenMid + PERIODRADIUS - O - s) (parenMid - PERIODRADIUS + O + s) (FWMIDDLE - PERIODRADIUS + O + s) (FWMIDDLE + PERIODRADIUS - O - s) true
		reverse-last
		save 'whitebullet' 0x25E6


	### 'Quotes and Primes'
	local quoteTop (CAP * 1.05)
	local quoteBottom (XH * 0.85)

	sketch # singleQuote
		set-width WIDTH

		include : dispiro
			widths.center (STROKE * 1.1)
			g4.down.start MIDDLE quoteTop [heading DOWNWARD]
			g4 MIDDLE quoteBottom [widths.heading (HALFSTROKE * 0.95) (HALFSTROKE * 0.95) DOWNWARD]
		save 'singleQuote' 0x27

	sketch # doubleQuote
		set-width WIDTH

		local dist : 0.2 * WIDTH
		include glyphs.singleQuote
		apply-transform : Translate (-dist * 2) 0
		include glyphs.singleQuote
		apply-transform : Translate dist 0
		save 'doubleQuote' 0x22

	local yCurlyQuotes [mix quoteBottom quoteTop 0.5]
	local commaLow (DESCENDER * 0.9)
	local ratio : Math.min 1 : (quoteTop - quoteBottom) / (PERIODSIZE - commaLow)

	sketch # lowSingleQuote
		include glyphs.comma
		include : FlipAround MIDDLE 0 ratio ratio
		save 'lowSingleQuote'

	sketch # openSingleQuote
		include glyphs.lowSingleQuote
		include : FlipAround MIDDLE [mix [mix PERIODSIZE commaLow 0.5] yCurlyQuotes 0.5]
		save 'openSingleQuote'

	sketch # closeSingleQuote
		include glyphs.openSingleQuote
		include : FlipAround MIDDLE yCurlyQuotes
		save 'closeSingleQuote'

	sketch # revertSingleQuote
		include glyphs.invertComma
		include : FlipAround MIDDLE 0 ratio ratio
		include : FlipAround MIDDLE [mix [mix PERIODSIZE commaLow 0.5] yCurlyQuotes 0.5]
		include : FlipAround MIDDLE yCurlyQuotes
		save 'revertSingleQuote'

	sketch # lowDoubleQuote
		local dist : WIDTH * 0.225
		include glyphs.lowSingleQuote
		apply-transform : Translate (-dist * 2) 0
		include glyphs.lowSingleQuote
		apply-transform : Translate dist 0
		save 'lowDoubleQuote'

	sketch # openDoubleQuote
		include glyphs.lowDoubleQuote
		include : FlipAround MIDDLE [mix [mix PERIODSIZE commaLow 0.5] yCurlyQuotes 0.5]
		save 'openDoubleQuote'

	sketch # closeDoubleQuote
		include glyphs.openDoubleQuote
		include : FlipAround MIDDLE yCurlyQuotes
		save 'closeDoubleQuote'

	sketch # revertDoubleQuote
		local dist : WIDTH * 0.225
		include glyphs.revertSingleQuote
		apply-transform : Translate (-dist * 2) 0
		include glyphs.revertSingleQuote
		apply-transform : Translate dist 0
		save 'revertDoubleQuote'

	fwr nothing 0x201A 'lowSingleQuote'
	fwr nothing 0x2018 'openSingleQuote'
	fwl nothing 0x2019 'closeSingleQuote'
	fwr nothing 0x201B 'revertSingleQuote'
	fwr nothing 0x201E 'lowDoubleQuote'
	fwr nothing 0x201C 'openDoubleQuote'
	fwl nothing 0x201D 'closeDoubleQuote'
	fwr nothing 0x201F 'revertDoubleQuote'

	sketch # prime
		local wide : WIDTH * 0.1
		include : dispiro
			widths.center (STROKE * 1.2)
			flat (MIDDLE + wide) quoteTop [heading DOWNWARD]
			curl (MIDDLE - wide) quoteBottom [widths.heading HALFSTROKE HALFSTROKE DOWNWARD]
		save 'prime' 0x2032

	sketch # doubleprime
		local d : 0.25 * (RIGHTSB - SB)
		include glyphs.prime
		apply-transform : Translate (-d * 2) 0
		include glyphs.prime
		apply-transform : Translate d 0
		save 'doubleprime' 0x2033

	sketch # tripleprime
		local wide : WIDTH * 0.1
		local d : WIDTH * 0.3
		local fine : 0.5 * [adviceBlackness 3.5]
		include : dispiro
			widths.center (fine * 2 * 1.2)
			flat (MIDDLE + wide) quoteTop [heading DOWNWARD]
			curl (MIDDLE - wide) quoteBottom [widths.heading fine fine DOWNWARD]
		include : dispiro
			widths.center (fine * 2 * 1.2)
			flat (MIDDLE - d + wide) quoteTop [heading DOWNWARD]
			curl (MIDDLE - d - wide) quoteBottom [widths.heading fine fine DOWNWARD]
		include : dispiro
			widths.center (fine * 2 * 1.2)
			flat (MIDDLE + d + wide) quoteTop [heading DOWNWARD]
			curl (MIDDLE + d - wide) quoteBottom [widths.heading fine fine DOWNWARD]
		save 'tripleprime' 0x2034

	sketch # revprime
		local wide : -WIDTH * 0.1
		include : dispiro
			widths.center (STROKE * 1.2)
			flat (MIDDLE + wide) quoteTop [heading DOWNWARD]
			curl (MIDDLE - wide) quoteBottom [widths.heading HALFSTROKE HALFSTROKE DOWNWARD]
		save 'revprime' 0x2035

	sketch # revdoubleprime
		local d : 0.25 * (RIGHTSB - SB)
		include glyphs.revprime
		apply-transform : Translate (-d * 2) 0
		include glyphs.revprime
		apply-transform : Translate d 0
		save 'revdoubleprime' 0x2036

	sketch # revtripleprime
		local wide : -WIDTH * 0.1
		local d : WIDTH * 0.3
		local fine : 0.5 * [adviceBlackness 3.5]
		include : dispiro
			widths.center (fine * 2 * 1.2)
			flat (MIDDLE + wide) quoteTop [heading DOWNWARD]
			curl (MIDDLE - wide) quoteBottom [widths.heading fine fine DOWNWARD]
		include : dispiro
			widths.center (fine * 2 * 1.2)
			flat (MIDDLE - d + wide) quoteTop [heading DOWNWARD]
			curl (MIDDLE - d - wide) quoteBottom [widths.heading fine fine DOWNWARD]
		include : dispiro
			widths.center (fine * 2 * 1.2)
			flat (MIDDLE + d + wide) quoteTop [heading DOWNWARD]
			curl (MIDDLE + d - wide) quoteBottom [widths.heading fine fine DOWNWARD]
		save 'revtripleprime' 0x2037

	sketch # singleGuillemetLeft
		local top : mix parenMid parenTop 0.5
		local bot : mix parenMid parenBot 0.5
		local extension 0.55
		local cor 1

		local sw : adviceBlackness 3.5

		include : dispiro
			widths.center sw
			g4 [mix MIDDLE RIGHTSB extension] top
			quadcontrols 0.4 0.75
			g4 [mix MIDDLE SB extension] [mix top bot 0.5] [widths.center.heading (cor * sw) LEFTWARD]

		include : dispiro
			widths.center (sw * cor)
			g4 [mix MIDDLE SB extension] [mix top bot 0.5] [heading RIGHTWARD]
			quadcontrols (1 - 0.4) (1 - 0.75)
			g4 [mix MIDDLE RIGHTSB extension] bot [widths.center sw]

		apply-transform : Translate (-(RIGHTSB - SB) * 0.05) 0
		save 'singleGuillemetLeft' 0x2039

	sketch # guillemetLeft
		include glyphs.singleGuillemetLeft
		apply-transform : Translate ((RIGHTSB - SB) * 0.5) 0
		include glyphs.singleGuillemetLeft
		apply-transform : Translate (-(RIGHTSB - SB) * 0.25) 0
		save 'guillemetLeft' 0xAB

	sketch # singleGuillemetRight
		include glyphs.singleGuillemetLeft
		include : FlipAround MIDDLE parenMid
		save 'singleGuillemetRight' 0x203A

	sketch # guillemetRight
		include glyphs.guillemetLeft
		include : FlipAround MIDDLE parenMid
		save 'guillemetRight' 0xBB


	### 'Daggers'
	sketch # dagger
		include : HBar SB RIGHTSB [mix parenTop parenBot 0.33]
		include : VBar MIDDLE parenBot parenTop

		save 'dagger' 0x2020

	sketch # doubledagger
		include glyphs.dagger
		include : HBar SB RIGHTSB [mix parenTop parenBot 0.67]
		save 'doubledagger' 0x2021

	### 'Ellipsis'
	sketch # onedotLeader
		set-width FULLWIDTH
		local radius : linreg WIDTH (0.5 * [adviceBlackness 3.25] * PERIODSIZE / DOTSIZE) UPM PERIODRADIUS FULLWIDTH
		include : Ring (radius * 2 - O) O (FULLWIDTH / 2 - radius + O) (FULLWIDTH / 2 + radius - O) true
		save 'onedotLeader' 0x2024

	sketch # twodotsLEader
		set-width FULLWIDTH
		local radius : linreg WIDTH (0.5 * [adviceBlackness 3.25] * PERIODSIZE / DOTSIZE) UPM PERIODRADIUS FULLWIDTH
		local left : mix 0 FULLWIDTH (1 / 4)
		local right : mix 0 FULLWIDTH (3 / 4)
		include : Ring (radius * 2 - O) O (left - radius + O) (left + radius - O) true
		include : Ring (radius * 2 - O) O (right - radius + O) (right + radius - O) true
		save 'twodotsLEader' 0x2025

	sketch # ellipsis
		set-width FULLWIDTH
		local radius : linreg WIDTH (0.5 * [adviceBlackness 3.25] * PERIODSIZE / DOTSIZE) UPM PERIODRADIUS FULLWIDTH
		local left : mix 0 FULLWIDTH (1 / 6)
		local right : mix 0 FULLWIDTH (5 / 6)
		include : Ring (radius * 2 - O) O (left - radius + O) (left + radius - O) true
		include : Ring (radius * 2 - O) O (FULLWIDTH / 2 - radius + O) (FULLWIDTH / 2 + radius - O) true
		include : Ring (radius * 2 - O) O (right - radius + O) (right + radius - O) true
		save 'ellipsis' 0x2026

	### 'Percentages'
	sketch # percent
		set-width WIDTH
		local dotwidth ([adviceBlackness 4] * 1.5)
		local cor : HVCONTRAST / [Math.sqrt (1 - [Math.pow ((RIGHTSB - SB - STROKE) / (CAP - 0)) 2])]

		start-from SB 0
		line-to (SB + STROKE * cor) 0
		line-to RIGHTSB CAP
		line-to (RIGHTSB - STROKE * cor) CAP

		include : VBarLeft SB [mix CAP 0 0.3] CAP dotwidth
		include : VBarRight RIGHTSB 0 [mix 0 CAP 0.3] dotwidth
		save 'percent' '%'

	sketch # permille
		local dotwidth ([adviceBlackness 4] * 1.5)

		include : dispiro
			widths.center
			flat SB (CAP * 0.2)
			curl [mix SB RIGHTSB 0.85] (CAP * 0.9)

		include : VBarLeft [mix SB RIGHTSB 0.075] [mix CAP 0 0.3] CAP dotwidth
		include : VBarRight RIGHTSB 0 [mix 0 CAP 0.3] dotwidth
		include : VBarRight (RIGHTSB - [Math.max (WIDTH * 0.25) (dotwidth * 1.5)]) 0 [mix 0 CAP 0.3] dotwidth
		save 'permille' 0x2030

	sketch # basepoint
		local dotwidth ([adviceBlackness 4] * 1.5)
		local dotfine [adviceBlackness 3.5]

		include : dispiro
			widths.center
			flat SB (CAP * 0.2)
			curl [mix SB RIGHTSB 0.85] (CAP * 0.9)

		include : VBarLeft SB [mix CAP 0 0.3] CAP dotwidth
		include : VBarRight RIGHTSB 0 [mix 0 CAP 0.3] dotfine
		include : VBar [mix [mix SB RIGHTSB 0.1] RIGHTSB 0.5] 0 [mix 0 CAP 0.3] dotfine
		include : VBarLeft [mix SB RIGHTSB 0.1] 0 [mix 0 CAP 0.3] dotfine
		save 'basepoint' 0x2031

	### "ASCII Marks"
	local MarkZoom : glyph-construction
		apply-transform : Upright
		apply-transform : Translate (-MIDDLE) (-XH - ACCENT)
		apply-transform : Scale ((RIGHTSB - SB) / (markExtend * 3))
		apply-transform : Translate (MIDDLE) (XH + ACCENT)
		apply-transform : Italify

	composite 'asciitilde.low' glyphs.'asciitilde.high' [Upright] [Translate 0 (parenMid - XH - ACCENT)] [Italify] markset.plus
	select-variant 'asciitilde' '~' 'low'  {
		.cv16 'asciitilde.high'
		.cv17 'asciitilde.low'
	}
	composite 'asciicaret.low' glyphs.'asciicaret.high' [Upright] [Translate 0 (parenMid - XH - ACCENT)] [Italify] markset.plus
	select-variant 'asciicaret' '^' 'high'  {
		.cv29 'asciicaret.high'
		.cv30 'asciicaret.low'
	}

	composite 'degree' glyphs.space glyphs.ringAbove MarkZoom [into-unicode 0xB0]

	alias 'mdfPrime' 0x2B9 'prime'
	alias 'mdfDoublePrime' 0x2BA 'doubleprime'
	alias 'mdfTurncomma' 0x2BB 'openSingleQuote'
	alias 'mdfApostrophe' 0x2BC 'closeSingleQuote'
	alias 'mdfRevComma' 0x2BD 'revertSingleQuote'
	alias 'mdfStress' 0x2C8 'singleQuote'
	turned 'mdfSecondaryStress' 0x2CC 'singleQuote' MIDDLE (XH / 2)


	### 'Double-width punctuations' : if (para.spacing > 0) : begin
	dwc nothing 0xFF01 'exclam'
	dwc nothing 0xFF1A 'colon'
	dwc nothing 0xFF1B 'semicolon'
	dwl nothing 0xFF0C 'comma'
	dwl nothing 0xFF0E 'period'
	dwr nothing 0xFF08 'parenLeft' (-WIDTH * 0.15)
	dwl nothing 0xFF09 'parenRight' (WIDTH * 0.15)

	local r : Math.max PERIODRADIUS (WIDTH * 0.225)
	local ry : r * 0.25
	sketch
		include : CircleDotAt MIDDLE ry (r + PERIODRADIUS * 0.5)
		include : CircleDotAt MIDDLE ry (r - PERIODRADIUS * 0.4)
		reverse-last
		branch
			set-width FULLWIDTH1
			save "dwlcjkperiod" 0x3002
		branch
			save 'cjkperiod' 0xFF61
	sketch
		local k 0.9
		include : dispiro
			widths.center
			g4 (MIDDLE - r * 1.1) (ry + r * (k - 0.2))
			quadcontrols 0.5 0.45
			g4 (MIDDLE + r) (ry + r * (-k - 0.35))
		branch
			set-width FULLWIDTH1
			save "dwlcjkcomma" 0x3001
		branch
			save 'cjkcomma' 0xFF64

	local cjkqd 0.75
	local cjkqd2 0.97
	local ideotop : para.ideoMid + (parenTop - parenMid)
	local ideobot : para.ideoMid - (parenTop - parenMid)
	sketch # cjkSingleQuoteLeft
		include : HBarTop    [mix SB RIGHTSB designParameters.bracketOutside] [mix SB RIGHTSB designParameters.bracketInside] [mix ideobot ideotop cjkqd2]
		include : VBarLeft   [mix SB RIGHTSB designParameters.bracketOutside] [mix ideotop ideobot cjkqd] [mix ideobot ideotop cjkqd2]
		save 'cjkSingleQuoteLeft' 0xFF62
	sketch # cjkSingleQuoteRight
		include glyphs.cjkSingleQuoteLeft
		include : FlipAround MIDDLE parenMid
		save 'cjkSingleQuoteRight' 0xFF63

	sketch # cjkDoubleQuoteLeft
		local sw : adviceBlackness 6
		local dw : [Math.max (WIDTH * 0.175) [adviceBlackness 3.25]] + sw * 2
		local outside : mix SB RIGHTSB designParameters.bracketOutside
		local inside : mix SB RIGHTSB designParameters.bracketInside
		local top : mix ideobot ideotop cjkqd2
		local bottom : mix ideotop ideobot cjkqd

		include : VBarLeft outside bottom top sw
		include : HBarTop outside inside top sw
		include : VBarRight inside top (top - dw) sw
		include : HBarBottom outside (outside + dw) bottom sw
		include : VBarRight (outside + dw) bottom (top - dw + sw) sw
		include : HBarBottom (outside + dw) inside (top - dw) sw
		save 'cjkDoubleQuoteLeft'
	sketch # cjkSingleQuoteRight
		include glyphs.cjkDoubleQuoteLeft
		include : FlipAround MIDDLE parenMid
		save 'cjkDoubleQuoteRight'

	dwr nothing 0x300C 'cjkSingleQuoteLeft'
	dwl nothing 0x300D 'cjkSingleQuoteRight'
	dwr nothing 0x300E 'cjkDoubleQuoteLeft'
	dwl nothing 0x300F 'cjkDoubleQuoteRight'