###### Automatic builds

# Build accented glyphs

define customDecompositions {
	# Latvians use comma instead of cedillas in several letters.
	# Record them as custom decomposition.
	."\u0156" "R\u0326"
	."\u0157" "r\u0326"
	."\u0136" "K\u0326"
	."\u0137" "k\u0326"
	."\u0145" "N\u0326"
	."\u0146" "n\u0326"
	."\u013B" "L\u0326"
	."\u013C" "l\u0326"
	."\u0122" "G\u0326"
	."\u0123" "g\u0312"
	
	# autobuild Latin glyphs
	."\u0197" "I\u0335"
	."\u019A" "l\u0335"
	."\u0248" "J\u0335"
	."\u0249" "j\u0335"
	."\u0268" "i\u0335"
	."\u024C" "R\u0335"
	."\u024D" "r\u0335"
	."\u01B5" "Z\u0335"
	."\u01B6" "z\u0335"
	."\u1D7B" "\u026A\u0335"
	."\u1D7C" "\u0269\u0335"
 	
	."\u1D7F" "\u028A\u0336"
	."\u0289" "u\u0336"
	."\u0244" "U\u0336"
	."\u01E5" "g\u0336"
	."\u01BB" "2\u0336"
	."\u024E" "Y\u0336"
	."\u04B0" "\u04AE\u0335"
	."\u04B1" "\u04AF\u0335"
	."\u024F" "y\u0336"
	."\uAB30" "\uAB64\u0336"
	."\u1D7D" "p\u0336"
 	
	."\u0142" "l\uE090"
	."\u013E" "l\u0315"
	."\u0165" "t\u0315"
 	
	."\u023A" "A\u0338"
	."\u023B" "C\u0338"
	."\u023C" "c\u0337"
	."\u023E" "T\u0338"
	."\u0246" "E\u0338"
	."\u0247" "e\u0337"

	."\u0290" "z\u0322"
	."\u0256" "d\u0322"
	."\u0273" "n\u0322"
	."\u01AE" "T\u0322"
	."\u1D8F" "a\u0322"
	."\u1D90" "\u0251\u0322"
	."\u1D91" "\u0257\u0322"
	."\u1D99" "u\u0322"
 	
	."\u1E9A" "a\u0357"
	."\u1E9C" "\u017F\uE090"
	."\u1E9D" "\u017F\u0335"
 	
 	# Cyrillic composite characters
	."\u0498" "\u0417\u0327"
	."\u0499" "\u0437\u0327"
	."\u04AA" "\u0421\u0327"
	."\u04AB" "\u0441\u0327"

	# Spacing modifers
#	."`"      " \u0300"
	."\u02CB" " \u0300"
#	."\u00B4" " \u0301"
	."\u02CA" " \u0301"
#	."^"      " \u0302"
	."\u02C6" " \u0302"
#	."~"      " \u0303"
	."\u02DC" " \u0303"
	."\u00AF" " \u0304"
	."\u02C9" " \u0304"
	."\u02D8" " \u0306"
	."\u02D9" " \u0307"
	."\u00A8" " \u0308"
#	."\u00B0" " \u030A"
	."\u02DA" " \u030A"
	."\u02C7" " \u030C"
	."\u00B8" " \u0327"
	."\u02CD" " \u0331"
	."\u02CE" " \u0316"
	."\u02CF" " \u0317"
	."\u02D2" " \u0339"
	."\u02D3" " \u031C"
	."\u02D4" " \u031D"
	."\u02D5" " \u031E"
	."\u02D6" " \u031F"
	."\u02D7" " \u0320"
	."\u02DB" " \u0328"
	."\u02DD" " \u030B"
	."\u02DF" " \u033D"
	."\u02EC" " \u032C"
	."\u02ED" " \u033F"
	."\u02F3" " \u0325"
	."\u02F7" " \u0330"

	."\u1FED" " \u0308\u0300"
	."\u1FEE" " \u0308\u0301"
	."\u1FEF" " \u0300"
	."\u1FFD" " \u0301"
	."\u1FFE" " \u0314"
	."\u1FBD" " \u0313"
	."\u1FBE" " \u0345"
	."\u1FBF" " \u0313"
	."\u1FC0" " \u0342"
	."\u1FC1" " \u0308\u0342"
	."\u0384" " \u0301"
	."\u0385" " \u0308\u0301"
	."\u037A" " \u0345"
	
	# Suppress incorrect slashed arrows... so far
	."\u219A" ""
	."\u219B" ""
	."\u21AE" ""
}

let : begin
	suggestGC
	define [isAboveMark mark] : mark && mark.anchors && mark.anchors.above && mark.anchors.above.type === MARK
	define iotaBelowToLF : function [p] : if (p === glyphs.iotaBelow) glyphs.iotaLF p
	define ogonekBelowToTR : function [p] : if (p === glyphs.ogonekBelow) glyphs.ogonekTR p
	define [subParts parts] : begin
		local hasMarkAbove false
		foreach p [items-of parts] : if [isAboveMark p] : set hasMarkAbove true
		
		# replace dotted-i and dotted-j with dotless equalivents
		if ((parts.0 === glyphs.i || parts.0 === glyphs.cyrUkrainiani) && hasMarkAbove) : parts.0 = glyphs.dotlessi
		if (parts.0 === glyphs.j && hasMarkAbove) : parts.0 = glyphs.dotlessj
		
		# replace below marks with trailing marks
		if parts.0.anchors.lf : set parts : parts.map iotaBelowToLF
		if parts.0.anchors.trailing : set parts : parts.map ogonekBelowToTR
		
		# composite greek overmarks
		for [local j 0] (j < parts.length) [inc j] : piecewise
			(parts.(j) === glyphs.commaAbove) : begin
				piecewise
					(parts.(j + 1) === glyphs.graveAbove) : begin
						set parts.(j) null; set parts.(j + 1) glyphs.psilivaria
					(parts.(j + 1) === glyphs.acuteAbove) : begin
						set parts.(j) null; set parts.(j + 1) glyphs.psilioxia
					(parts.(j + 1) === glyphs.perispomeniAbove) : begin
						set parts.(j) null; set parts.(j + 1) glyphs.psiliperispomeni
			(parts.(j) === glyphs.revCommaAbove) : begin
				piecewise
					(parts.(j + 1) === glyphs.graveAbove) : begin
						set parts.(j) null; set parts.(j + 1) glyphs.dasiavaria
					(parts.(j + 1) === glyphs.acuteAbove) : begin
						set parts.(j) null; set parts.(j + 1) glyphs.dasiaoxia
					(parts.(j + 1) === glyphs.perispomeniAbove) : begin
						set parts.(j) null; set parts.(j + 1) glyphs.dasiaperispomeni
		return parts

	define [pad s n] : begin
		while (s.length < n) : s = '0' + s
		return s
	local nComposed 0
	local foundDecompositions {.}
	define [decideName namingParts parts code] : begin
		local baseName namingParts.0.name
		local glyphName baseName
		foreach [part : namingParts.slice 1] : if part : glyphName = glyphName + [fallback part.shortName part.name]
		if foundDecompositions.(glyphName) : begin
			local j 2
			while foundDecompositions.(glyphName + j) [inc j]
			set glyphName (glyphName + j)
		if (glyphName.length > 27) : set glyphName ('uni' + [pad [[code.toString 16].toUpperCase] 4])
		return glyphName
	local [buildForCode code] : if [not unicodeGlyphs.(code)] : begin
		local str : String.fromCharCode code
		local nfd : fallback customDecompositions.(str) : unorm.nfd str
		if (nfd.length > 1) : begin
			local parts {}
			local allFound true
			foreach j [range 0 nfd.length] : begin
				local part unicodeGlyphs.([nfd.charCodeAt j])
				if [not part] : then : set allFound false
				: else : set parts.(j) unicodeGlyphs.([nfd.charCodeAt j])
			if allFound : begin
				local namingParts : parts.slice 0
				set parts : subParts parts
				local glyphName : decideName namingParts parts code
				set foundDecompositions.(glyphName) {glyphName code parts}

	if recursiveCodes : recursiveCodes.forEach buildForCode
	: else : foreach code [range 0x0000 0xFFFF] : buildForCode code
	progress "Composition Decision"
	suggestGC
	
	local {glyphName code parts} {}
	define construction : glyph-construction
		if code : assign-unicode code
		include parts.0 AS_BASE
		set-width parts.0.advanceWidth
		
		local names {parts.0.name}
		foreach part [items-of : parts.slice 1] : if part : begin
			include part
			names.push part.name
			if (part.name === 'rtailBR') : eject-contour 'serifRB'
		inc nComposed
	
	define [cfv glyphName _pa] : if (!recursive && _pa.0.featureSelector) : begin
		local h {.}
		foreach [feature : items-of : Object.keys _pa.0.featureSelector] : begin
			local variant _pa.0.featureSelector.(feature)
			local variantRoot glyphs.(variant)
			if variantRoot : begin
				set parts {variantRoot :: [_pa.slice 1]}
				set code null
				create-glyph (glyphName + '.' + feature) construction

				set h.(feature) (glyphName + '.' + feature)
		if glyphs.(glyphName) : set glyphs.(glyphName).featureSelector h
	
	foreach [_id : items-of : Object.keys foundDecompositions] : begin
		set {glyphName code parts} foundDecompositions.(_id)
		create-glyph glyphName construction
		cfv glyphName parts

	progress "Unicode Precomposites (\(nComposed) glyphs)"
	suggestGC


define [suggestName name] : begin
	if glyphs.(name) : begin
		local j 2
		while glyphs.(name + j) : inc j
		set name (name + j)
	return name
# Build miniature clyphs : circled, superscripts, subscripts...
define [createCircledGlyphs records] : if [not recursive] : begin
	local dscale 0.55
	local pendingGlyphs : records.map : [record] => record.1
	local miniatureFont : Miniature 
		glyphs -- pendingGlyphs
		crowd  -- [fallback para.smallCrowd 3.75]
		scale  -- 0.65
		unfair -- true
	
	foreach {unicode glyphid w} [items-of records] : create-glyph [suggestName : 'circle' + glyphid] : glyph-construction
		local width : fallback w WIDTH
		set-width width
		local sw [adviceBlackness 5]
		if unicode : assign-unicode unicode
		include : create-glyph [suggestName : 'circleinner' + glyphid] : glyph-construction
			local g miniatureFont.(glyphid)
			include g
			local shift 0
			if (g.anchors.above && g.anchors.below) : set shift : CAP / 2 -  [mix g.anchors.above.y g.anchors.below.y 0.5]
			apply-transform : Upright
			apply-transform : Translate (-WIDTH / 2) (-CAP / 2 + shift)
			apply-transform : Scale dscale
			apply-transform : Translate (width / 2) (CAP / 2 * dscale)
			apply-transform : Italify
			refair this
		
		include : OShape 
			* (CAP * dscale + [Math.max (CAP * 0.175) (sw * 3)])
			* (-[Math.max (CAP * 0.175) (sw * 3)])
			* [Math.max (SB + O * 3) (width / 2 - CAP / 2 * dscale - sw * 2.5)]
			* [Math.min (width - SB - O * 3) (width / 2 + CAP / 2 * dscale + sw * 2.5)]
			* sw
			* (SMALLSMOOTHA * width / WIDTH)
			* (SMALLSMOOTHB * width / WIDTH)
		apply-transform : Upright
		apply-transform : Translate 0 (parenMid - CAP * dscale / 2)
		apply-transform : Italify

define [createBracedGlyphs records] : if [not recursive] : begin
	local dscale 0.55
	local pscale 0.6
	local pendingGlyphs : records.map : [record] => record.1
	local miniatureFont : Miniature 
		glyphs  -- pendingGlyphs
		crowd   -- [fallback para.smallCrowd 3.75]
		scale   -- 0.65
		sbscale -- 1 
		unfair  -- true
	
	foreach {unicode glyphid w} [items-of records] : sketch
		local width : fallback w WIDTH
		set-width width
		local sw [adviceBlackness 5]
		local l : [Math.max (SB + O * 3) (width / 2 - CAP / 2 * dscale - sw * 2.5)] + OX
		local r : width - l
		
		include : create-glyph [suggestName : 'circleinner' + glyphid] : glyph-construction
			include miniatureFont.(glyphid)
			apply-transform : Upright
			apply-transform : Translate (-WIDTH / 2) 0
			apply-transform : Scale dscale
			apply-transform : Translate (width / 2) 0
			apply-transform : Italify
			refair this
		
		include : dispiro
			widths.lhs sw
			g4 [mix l r 0.15] (parenTop * pscale)
			g4.down.mid l     (parenMid * pscale)
			g4 [mix l r 0.15] (parenBot * pscale)
		
		include : dispiro
			widths.rhs sw
			g4 [mix r l 0.15] (parenTop * pscale)
			g4.down.mid r     (parenMid * pscale)
			g4 [mix r l 0.15] (parenBot * pscale)
			
		include : Upright
		include : Translate 0 (parenMid - parenMid * pscale)
		include : Italify
		
		save [suggestName : 'braced' + glyphid] unicode

define [createSuperscripts records] : if [not recursive] : begin
	local pendingGlyphs : records.map : [record] => record.1
	local miniatureFont : Miniature
		glyphs -- pendingGlyphs
		crowd  -- [fallback para.smallCrowd 3.5]
		scale  -- 0.7
		unfair -- true
	foreach {unicode glyphid} [items-of records] : create-glyph [suggestName : 'sup' + glyphid] : glyph-construction
		if unicode : assign-unicode unicode
		include miniatureFont.(glyphid) AS_BASE
		apply-transform [Upright] true
		apply-transform [Translate (-MIDDLE) (-CAP)] true
		apply-transform [Scale 0.7] true
		apply-transform [Translate MIDDLE (CAP + ACCENT / 2)] true
		apply-transform [Italify] true
		refair this

define [createSubscripts records] : if [not recursive] : begin
	local pendingGlyphs : records.map : [record] => record.1
	local miniatureFont : Miniature
		glyphs -- pendingGlyphs
		crowd  -- [fallback para.smallCrowd 3.5]
		scale  -- 0.7
		unfair -- true
	foreach {unicode glyphid} [items-of records] : create-glyph [suggestName : 'sub' + glyphid] : glyph-construction
		if unicode : assign-unicode unicode
		include miniatureFont.(glyphid) AS_BASE
		apply-transform [Upright] true
		apply-transform [Translate (-MIDDLE) 0] true
		apply-transform [Scale 0.7] true
		apply-transform [Translate MIDDLE (DESCENDER / 2)] true
		apply-transform [Italify] true
		refair this

define [createSMCPs records] : if [not recursive] : begin
	local pendingGlyphs : records.map : [record] => record.1
	local forkedParams : Object.create para
	set forkedParams.cap0 para.cap
	set forkedParams.cap XH
	set forkedParams.xheight (XH * XH / CAP)
	local sf : Fork pendingGlyphs forkedParams
	foreach {unicode glyphid tfm} [items-of records] : create-glyph [suggestName : 'smcp' + glyphid] : glyph-construction
		if unicode : assign-unicode unicode
		include sf.(glyphid) AS_BASE
		if tfm : include tfm

define [createMedievalCombs records] : if [not recursive] : begin
	local pendingGlyphs : records.map : [record] => record.1
	local miniatureFont : Miniature
		glyphs -- pendingGlyphs
		crowd  -- [fallback para.smallCrowd2 3.5]
		scale  -- 0.7
		unfair -- true
	foreach {unicode glyphid} [items-of records] : create-glyph [suggestName : 'comb' + glyphid] : glyph-construction
		set-width 0
		if unicode : assign-unicode unicode
		include miniatureFont.(glyphid)
		apply-transform : Upright
		apply-transform : Translate (-MIDDLE) 0
		apply-transform : Scale 0.4
		apply-transform : Translate markMiddle aboveMarkBot
		apply-transform : Italify 
		refair this
		set-anchor 'above' MARK markMiddle XH markMiddle aboveMarkTop

define [createFractions records] : if [not recursive] : begin
	local pendingGlyphs : [records.map : [record] => record.1].concat : records.map : [record] => record.2
	local miniatureFont : Miniature
		glyphs -- pendingGlyphs
		crowd  -- 4
		scale  -- 0.6
		unfair -- true
	foreach {unicode numid denid height} [items-of records] : create-glyph [suggestName : numid + 'over' + denid] : glyph-construction
		if unicode : assign-unicode unicode
		local fine : adviceBlackness 3
		local dist : XH * 0.4
		include : create-glyph : glyph-construction
			include : create-glyph [suggestName : 'num' + numid] : glyph-construction
				include miniatureFont.(numid)
				apply-transform : Upright
				apply-transform : Translate (- miniatureFont.(numid).advanceWidth / 2) 0
				apply-transform : Scale (CAP / [fallback height CAP] * 0.55)
				apply-transform : Translate MIDDLE 0
				apply-transform : Italify
				refair this
			apply-transform : Upright
			apply-transform : Translate 0 (CAP * 0.55 + dist)
			apply-transform : Italify
			include : create-glyph [suggestName : 'den' + denid] : glyph-construction
				include miniatureFont.(denid)
				apply-transform : Upright
				apply-transform : Translate (- miniatureFont.(denid).advanceWidth / 2) 0
				apply-transform : Scale (CAP / [fallback height CAP] * 0.55)
				apply-transform : Translate MIDDLE 0
				apply-transform : Italify
				refair this
			apply-transform : Upright
			apply-transform : Translate (-MIDDLE) (-CAP * 0.55 - dist / 2)
			apply-transform : Translate MIDDLE parenMid
			apply-transform : Italify
		include : HBar SB RIGHTSB parenMid (fine * 0.75)


symbol-block 'Circled and Braced' : if [not recursive] : begin
	local compositions : list
		list 0xA9   'C'
		list 0xAE   'R'
		list 0x2117 'P'
		list 0x24EA 'zero' FULLWIDTH
		list null   'space' FULLWIDTH
	foreach [j : range 1 till 9] : compositions.push {(0x2460 + j - 1) unicodeGlyphs.(['0'.charCodeAt 0] + j).name FULLWIDTH}
	foreach [j : range 0 26] : compositions.push {(0x24B6 + j) unicodeGlyphs.(['A'.charCodeAt 0] + j).name FULLWIDTH}
	foreach [j : range 0 26] : compositions.push {(0x24D0 + j) unicodeGlyphs.(['a'.charCodeAt 0] + j).name FULLWIDTH}
	createCircledGlyphs compositions

	local compositions : list
		list null   'space' FULLWIDTH
	foreach [j : range 1 till 9] : compositions.push {(0x2474 + j - 1) unicodeGlyphs.(['0'.charCodeAt 0] + j).name FULLWIDTH}
	foreach [j : range 0 26] : compositions.push {(0x249C + j) unicodeGlyphs.(['a'.charCodeAt 0] + j).name FULLWIDTH}
	createBracedGlyphs compositions

createSMCPs : list
	list 0x1D00 'A'
	list 0x1D01 'AE'
	list 0x1D03 'Bbar'
	list 0x1D04 'C'
	list 0x1D05 'D'
	list 0x1D06 'Dcroat'
	list 0x1D07 'E'
	list 0x1D08 'cyrZe'
	list 0x1D0A 'J'
	list 0x1D0B 'K'
	list 0x1D0C 'Lslash'
	list 0x1D0D 'M'
	list 0x1D0E 'cyrI'
	list 0x1D0F 'O'
	list 0x1D10 'turnC'
	list 0x1D15 'OU'
	list 0x1D18 'P'
	list 0x1D19 'cyrYa'
	list 0x1D1A 'R' [FlipAround MIDDLE (XH / 2)]
	list 0x1D1B 'T'
	list 0x1D20 'V'
	list 0x1D21 'W'
	list 0x1D22 'Z'
	list 0x1D23 'Ezh'
	list 0x1D26 'Gamma'
	list 0x1D27 'Lambda'
	list 0x1D28 'Pi'
	list 0x1D29 'Rho'
	list 0x1D2B 'cyrEl'
progress 'Small Caps'

createSuperscripts : list
	list 0x2070 'zero'
	list 0x00B9 'one'
	list 0x00B2 'two'
	list 0x00B3 'three'
	list 0x2074 'four'
	list 0x2075 'five'
	list 0x2076 'six'
	list 0x2077 'seven'
	list 0x2078 'eight'
	list 0x2079 'nine'
	list 0x02B0 'h'
	list 0x02B1 'hhooktop'
	list 0x02B2 'j'
	list 0x02B3 'r'
	list 0x02B4 'turnr'
	list 0x02B5 'turnrrtail'
	list 0x02B6 'invsmcpR'
	list 0x02B7 'w'
	list 0x02B8 'y'
	list 0x02C0 'fineglottalstop'
	list 0x02C1 'finerevglottalstop'
	list 0x02E0 'latingamma'
	list 0x02E1 'l'
	list 0x02E2 's'
	list 0x02E3 'x'
	list 0x02E4 'revglottalstop'
	list 0x2071 'i'
	list 0x207F 'n'
	list 0x1D43 'a'
	list 0x1D44 'turna'
	list 0x1D45 'scripta'
	list 0x1D46 'turnae'
	list 0x1D47 'b'
	list 0x1D48 'd'
	list 0x1D49 'e'
	list 0x1D4A 'turne'
	list 0x1D4B 'epsilon'
	list 0x1D4C 'cyrze'
	list 0x1D4D 'g'
	list 0x1D4E 'turni'
	list 0x1D4F 'k'
	list 0x1D50 'm'
	list 0x1D51 'eng'
	list 0x1D52 'o'
	list 0x1D53 'turnc'
	list 0x1D54 'oupperhalf'
	list 0x1D55 'olowerhalf'
	list 0x1D56 'p'
	list 0x1D57 't'
	list 0x1D58 'u'
	list 0x1D5A 'turnm'
	list 0x1D5B 'v'
	list 0x1D5D 'beta'
	list 0x1D5E 'gamma'
	list 0x1D5F 'delta'
	list 0x1D60 'phi'
	list 0x1D61 'chi'
	list 0x1D78 'smcpH'
	list 0x1D9B 'turnscripta'
	list 0x1D9C 'c'
	list 0x1D9D 'ccurlytail'
	list 0x1D9E 'eth'
	list 0x1D9F 'revlatinepsilon'
	list 0x1DA0 'f'
	list 0x1DA1 'turnf'
	list 0x1DA2 'scriptg'
	list 0x1DA3 'turnh'
	list 0x1DA4 'ibarOver'
	list 0x1DA5 'latiniota'
	list 0x1DA6 'smcpI'
	list 0x1DA7 'smcpIbarOver'
	list 0x1DA8 'jcurlytail'
	list 0x1DAB 'smcpL'
	list 0x1DA9 'lrtail'
	list 0x1DAC 'mltail'
	list 0x1DAD 'turnmleg'
	list 0x1DAE 'nltail'
	list 0x1DAF 'nrtailBR'
	list 0x1DB0 'smcpN'
	list 0x1DB1 'obar'
	list 0x1DB2 'varphi'
	list 0x1DB3 'srtail'
	list 0x1DB4 'esh'
	list 0x1DB5 'tltail'
	list 0x1DB6 'ulongBarOver'
	list 0x1DB7 'latinupsilon1'
	list 0x1DB8 'smcpU'
	list 0x1DB9 'latinupsilon2'
	list 0x1DBA 'turnv'
	list 0x1DBC 'zrtailBR'
	list 0x1DBD 'zcurlytail'
	list 0x1DBE 'ezh'
	list 0x1DBF 'theta'
	list 0x1DBB 'z'
	list 0x1D2C 'A'
	list 0x1D2D 'AE'
	list 0x1D2E 'B'
	list 0x1D2F 'Bbar'
	list 0x1D30 'D'
	list 0x1D31 'E'
	list 0x1D32 'turnE'
	list 0x1D33 'G'
	list 0x1D34 'H'
	list 0x1D35 'I'
	list 0x1D36 'J'
	list 0x1D37 'K'
	list 0x1D38 'L'
	list 0x1D39 'M'
	list 0x1D3A 'N'
	list 0x1D3B 'cyrI'
	list 0x1D3C 'O'
	list 0x1D3D 'OU'
	list 0x1D3E 'P'
	list 0x1D3F 'R'
	list null   'S' # there is no superscript S in unicode, but is is used for the SM symbol
	list 0x1D40 'T'
	list 0x1D41 'U'
	list 0x1D42 'W'
	list 0x2C7D 'V'
	list 0x207A 'plus'
	list 0x207B 'minus'
	list 0x207C 'equal'
	list 0x207D 'parenLeft'
	list 0x207E 'parenRight'
if [not recursive] : let [df : Miniature {'a' 'o'} 3.5 0.7] : begin
	sketch # ordfeminine
		include df.a
		include : HBarBottom SB RIGHTSB DESCENDER
		apply-transform : Upright
		apply-transform : Translate (-MIDDLE) (-XH)
		apply-transform : Scale 0.7
		apply-transform : Translate MIDDLE CAP
		apply-transform : Italify
		save 'ordfeminine' 0xAA

	sketch # ordmasculine
		include df.o
		include : HBarBottom SB RIGHTSB DESCENDER
		apply-transform : Upright
		apply-transform : Translate (-MIDDLE) (-XH)
		apply-transform : Scale 0.7
		apply-transform : Translate MIDDLE CAP
		apply-transform : Italify
		save 'ordmasculine' 0xBA
progress 'Superscripts'

createSubscripts : list
	list 0x2080 'zero'
	list 0x2081 'one'
	list 0x2082 'two'
	list 0x2083 'three'
	list 0x2084 'four'
	list 0x2085 'five'
	list 0x2086 'six'
	list 0x2087 'seven'
	list 0x2088 'eight'
	list 0x2089 'nine'
	list 0x2090 'a'
	list 0x2091 'e'
	list 0x2092 'o'
	list 0x2093 'x'
	list 0x2094 'turne'
	list 0x2095 'h'
	list 0x2096 'k'
	list 0x2097 'l'
	list 0x2098 'm'
	list 0x2099 'n'
	list 0x209A 'p'
	list 0x209B 's'
	list 0x209C 't'
	list 0x1D62 'i'
	list 0x1D63 'r'
	list 0x1D64 'u'
	list 0x1D65 'v'
	list 0x1D66 'beta'
	list 0x1D67 'gamma'
	list 0x1D68 'rho'
	list 0x1D69 'phi'
	list 0x1D6A 'chi'
	list 0x2C7C 'j'
	list 0x208A 'plus'
	list 0x208B 'minus'
	list 0x208C 'equal'
	list 0x208D 'parenLeft'
	list 0x208E 'parenRight'
progress 'Subscripts'

createFractions : list
	list 0x00BC 'one' 'four'
	list 0x00BD 'one' 'two'
	list 0x00BE 'three' 'four'
	list 0x2150 'one' 'seven'
	list 0x2151 'one' 'nine'
	list 0x2152 'one' 'ten'
	list 0x2153 'one' 'three'
	list 0x2154 'two' 'three'
	list 0x2155 'one' 'five'
	list 0x2156 'two' 'five'
	list 0x2157 'three' 'five'
	list 0x2158 'four' 'five'
	list 0x2159 'one' 'six'
	list 0x215A 'five' 'six'
	list 0x215B 'one' 'eight'
	list 0x215C 'three' 'eight'
	list 0x215D 'five' 'eight'
	list 0x215E 'seven' 'eight'
	list 0x2189 'zero' 'three'
	# care-of
	list 0x2105 'C' 'O'
	list 0x2106 'C' 'U'
	# Powerline LN symbol
	list 0xE0A1 'L' 'N'
	# fraction bar
	list null 'space' 'space'
progress 'Fractions'

createMedievalCombs : list
	list 0x363 'a'
	list 0x364 'e'
	list 0x365 'i'
	list 0x366 'o'
	list 0x367 'u'
	list 0x368 'c'
	list 0x369 'd'
	list 0x36A 'h'
	list 0x36B 'm'
	list 0x36C 'r'
	list 0x36D 't'
	list 0x36E 'v'
	list 0x36F 'x'
progress 'Medival Combining Characters'

# Ligatures
symbol-block 'Unicode Ligatures'
	define shrink : clamp 0.75 0.9 : linreg 72 0.75 108 0.9 STROKE
	define [createLigatures records] : if [not recursive] : begin
		local pendingGlyphs : [records.map : [record] => record.1].concat : records.map : [record] => record.2
		local df : Thinner pendingGlyphs shrink 1
		foreach [{unicode c1 c2 mark} : items-of records] : begin
			local glyphName "\(c1)_\(c2)"
			if glyphs.(glyphName) : begin
				local j 2
				while glyphs.(glyphName + j) : inc j
				set glyphName (glyphName + j)
			
			sketch
				include df.(c2)
				include : Translate (WIDTH * shrink - SB * shrink * 1.75) 0
				include df.(c1)
				include : Upright
				include : Translate (-WIDTH * shrink + (SB * shrink * 7/8)) 0
				include : Scale ((WIDTH - SB * 1.25) / (WIDTH - SB * 2) * WIDTH / (WIDTH * shrink * 2 - SB * shrink * 1.75)) 1
				include : Translate (WIDTH / 2) 0
				include : Italify
				
				if mark : include mark
				save glyphName unicode

	createLigatures : list
		list 0x1C4 'D' 'Zcaron'
		list 0x1C5 'D' 'zcaron'
		list 0x1C6 'd' 'zcaron'
		list 0x1C7 'L' 'J'
		list 0x1C8 'L' 'j'
		list 0x1C9 'l' 'j'
		list 0x1CA 'N' 'J'
		list 0x1CB 'N' 'j'
		list 0x1CC 'n' 'j'
		list 0x2A3 'd' 'z'
		list 0x1F1 'D' 'Z'
		list 0x1F2 'D' 'z'
		list 0x1F3 'd' 'z'
		list 0x2A4 'd' 'ezh'
		list 0x2A5 'd' 'zcurlytail'
		list 0x2A6 't' 's'
		list 0x2A7 't' 'esh'
		list 0x2A8 't' 'ccurlytail'
		list 0x2A9 'f' 'eng'
		list 0x2AA 'l' 's'
		list 0x2AB 'l' 'z'
		list 0x478 'O' 'y' ifMarks
		list 0x479 'o' 'y' pMarks
		list 0x20A7 'P' 's'
		list 0x20A8 'R' 's'

# Composite superscripts and subscripts
let : begin
	define [doubleSuperscript a b] : glyph-construction
		include a
		apply-transform : Translate (-WIDTH * 0.6) 0
		include b
		apply-transform : Upright
		apply-transform : Translate (-WIDTH * 0.2) (-CAP)
		apply-transform : Scale 0.8
		apply-transform : Translate MIDDLE CAP
		apply-transform : Italify
	
	sketch # trademark
		include : doubleSuperscript glyphs.supT glyphs.supM
		save 'trademark' 0x2122
	
	sketch # servicemark
		include : doubleSuperscript glyphs.supS glyphs.supM
		save 'servicemark' 0x2120
progress 'Double Superscripts'


# CJK double width letters
symbol-block 'CJK Double Width Characters'
	define [createDoubleWidth records] : if [not recursive] : begin
		local scale 1.25
		local pendingGlyphs : records.map : [record] => record.1
		local widenFont : Widen pendingGlyphs scale (scale * 1.1)
		foreach {unicode glyphid} [items-of records] : create-glyph [suggestName : 'dw' + glyphid] : glyph-construction
			set-width UPM
			if unicode : assign-unicode unicode
			include widenFont.(glyphid) AS_BASE
			apply-transform [Translate (UPM / 2 - (WIDTH * scale) / 2) 0] true
	
	if [not recursive] : createDoubleWidth : let [a {}] : begin
		foreach [j : range 1 0x5f] : if [not unicodeGlyphs.(0xff00 + j)] : a.push {(0xff00 + j) unicodeGlyphs.(0x20 + j).name}
		a.push {0xFFE0 'cent'}
		a.push {0xFFE1 'sterling'}
		a.push {0xFFE5 'yen'}
		* a
	
### Generate Features and remove double-width glyphs when necessary
if [not recursive] : begin
	if [not para.cjk] : begin
		set font.glyf : font.glyf.filter [lambda [g] : g.advanceWidth <= WIDTH]
		set glyphList font.glyf

	set font.features.cv {.}
	foreach [name : items-of : Object.keys glyphs] : begin
		if glyphs.(name).featureSelector : begin
			local fs glyphs.(name).featureSelector
			foreach [feature : items-of : Object.keys fs] : begin
				if [not font.features.cv.(feature)] : set font.features.cv.(feature) {.}
				set font.features.cv.(feature).(name) fs.(feature)

	set font.features.mark {.}
	set font.features.mkmk {.marks {} .bases {}}
	set font.features.markGlyphs {.}
	set font.features.gdef {.simple {} .ligature {} .mark {}}
	define [buildAnchorDescription glyph inserter propx propy prefix th] : begin
		local buf ''
		foreach key [items-of : Object.keys glyph.anchors] : if (!th || th.(key)) : buf = buf + ' <anchor ' + [Math.round glyph.anchors.(key).(propx)] + ' ' + [Math.round glyph.anchors.(key).(propy)] + '> ' + inserter + ' @' + prefix + key
		return buf
	
	# mark
	define [createMarkLookup tableName anchorClasses] : let [lookup : set font.features.mark.(tableName) {.marks {} .bases {}}] : begin
		local th {.}
		foreach [ac : items-of anchorClasses] : set th.(ac) true
		foreach glyph [items-of glyphList] : if glyph.anchors : begin
			local anchorKeys : Object.keys glyph.anchors
			local hasAnchor false
			foreach [key : items-of anchorKeys] : if th.(key) : set hasAnchor true
			if hasAnchor : begin
				local isMarkGlyph false
				foreach key [items-of anchorKeys] : if (glyph.anchors.(key).type == 'mark') : set isMarkGlyph true
				if isMarkGlyph
					then : lookup.marks.push : 'markClass ' + glyph.name + [buildAnchorDescription glyph '' 'x' 'y' 'mark' th]
					else : lookup.bases.push : 'pos base ' + glyph.name + [buildAnchorDescription glyph 'mark' 'x' 'y' 'mark' th]
	
	createMarkLookup 'letter1' {'above' 'below'}
	createMarkLookup 'letter2' {'trailing' 'lf' 'topright' 'bottomright'}
	createMarkLookup 'overlay' {'overlay' 'slash'}
	# mkmk and GDEF
	foreach glyph [items-of glyphList] : if (glyph.anchors && [begin [local anchorKeys : Object.keys glyph.anchors] anchorKeys.length])
		then
			local isMarkGlyph false
			foreach key [items-of anchorKeys] : if (glyph.anchors.(key).type == 'mark') : set isMarkGlyph true
			
			if isMarkGlyph
				then
					font.features.mkmk.marks.push : 'markClass ' + glyph.name + ' ' + [buildAnchorDescription glyph '' 'x' 'y' 'mkmk']
					font.features.mkmk.bases.push : 'pos mark ' + glyph.name + ' ' + [buildAnchorDescription glyph 'mark' 'mbx' 'mby' 'mkmk']
					foreach key [items-of anchorKeys] : begin
						if [not font.features.markGlyphs.(key)] : set font.features.markGlyphs.(key) {}
						font.features.markGlyphs.(key).push glyph.name
					font.features.gdef.mark.push glyph.name
				else : if [[regex '_'].test glyph.name] [font.features.gdef.ligature.push glyph.name] [font.features.gdef.simple.push glyph.name]
		else : if [[regex '_'].test glyph.name] [font.features.gdef.ligature.push glyph.name] [font.features.gdef.simple.push glyph.name]
	
	progress 'Features'