813 lines
No EOL
26 KiB
Text
813 lines
No EOL
26 KiB
Text
###### Automatic builds
|
|
|
|
# Build accented glyphs
|
|
define [isAboveMark mark] : mark && mark.anchors && mark.anchors.above && mark.anchors.above.type === MARK
|
|
set font.features {.}
|
|
set font.features.cv {.}
|
|
|
|
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"
|
|
|
|
."\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"
|
|
|
|
# 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"
|
|
|
|
# Suppress incorrect slashed arrows... so far
|
|
."\u219A" ""
|
|
."\u219B" ""
|
|
."\u21AE" ""
|
|
}
|
|
|
|
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
|
|
|
|
|
|
#set font.features.ccmp {}
|
|
define [shorter x y] : if (x.length < y.length) x y
|
|
|
|
local {cfv} : let : begin
|
|
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}
|
|
inc nComposed
|
|
#if (global && global.gc) : global.gc
|
|
if recursiveCodes : recursiveCodes.forEach buildForCode
|
|
: else : foreach code [range 0x0000 0xFFFF] : buildForCode code
|
|
#if (global && global.gc) : global.gc
|
|
progress "Composition Decision"
|
|
|
|
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'
|
|
|
|
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)"
|
|
|
|
list cfv
|
|
|
|
|
|
symbol-block "Manual Precomposites and CV variants"
|
|
cfv 'i' {glyphs.dotlessi glyphs.dotAbove}
|
|
cfv 'cyrUkrainiani' {glyphs.i}
|
|
|
|
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)
|
|
|
|
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' glyphs.space glyphs.tildeAbove MarkZoom [into-unicode '~']
|
|
composite 'asciigrave' glyphs.space glyphs.graveAbove MarkZoom [into-unicode '`']
|
|
composite 'asciicaret' glyphs.space glyphs.circumflexAbove MarkZoom [into-unicode '^']
|
|
composite 'latin1acute' glyphs.space glyphs.acuteAbove MarkZoom [into-unicode 0xB4]
|
|
composite 'degree' glyphs.space glyphs.ringAbove MarkZoom [into-unicode 0xB0]
|
|
|
|
if [not recursive] : begin
|
|
composite 'asciitilde.centered' glyphs.asciitilde [Upright] [Translate 0 (parenMid - XH - ACCENT)] [Italify]
|
|
set glyphs.asciitilde.featureSelector {
|
|
.cv16 'asciitilde'
|
|
.cv17 'asciitilde.centered'
|
|
}
|
|
composite 'asterisk.centered' glyphs.asterisk [Upright] [Translate 0 (parenMid - glyphs.asterisk.centery)] [Italify]
|
|
set glyphs.asterisk.featureSelector {
|
|
.cv18 'asterisk'
|
|
.cv19 'asterisk.centered'
|
|
}
|
|
|
|
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 pendingGlyphs [fallback para.smallCrowd 3.75] 0.65 nothing 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 [createSuperscripts records] : if [not recursive] : begin
|
|
local pendingGlyphs : records.map : [record] -> record.1
|
|
local miniatureFont : Miniature pendingGlyphs [fallback para.smallCrowd 3.5] 0.7 nothing 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 pendingGlyphs [fallback para.smallCrowd 3.5] 0.7 nothing 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 params : Object.create para
|
|
set params.cap0 para.cap
|
|
set params.cap XH
|
|
set params.xheight (XH * XH / CAP)
|
|
local sf : Fork pendingGlyphs params
|
|
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 pendingGlyphs [fallback para.smallCrowd2 3.5] 0.7 nothing 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 pendingGlyphs 4 0.6 nothing 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)
|
|
|
|
|
|
let : 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
|
|
progress 'Circled'
|
|
|
|
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 0x1D1C 'U'
|
|
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
|
|
create-glyph 'ordfeminine' : glyph-construction
|
|
assign-unicode 0xAA
|
|
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
|
|
|
|
create-glyph 'ordmasculine' : glyph-construction
|
|
assign-unicode 0xBA
|
|
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
|
|
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} : 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)
|
|
create-glyph glyphName : glyph-construction
|
|
assign-unicode unicode
|
|
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
|
|
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'
|
|
|
|
# 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
|
|
|
|
create-glyph 'trademark' : glyph-construction
|
|
assign-unicode 0x2122
|
|
include : doubleSuperscript glyphs.supT glyphs.supM
|
|
|
|
create-glyph 'servicemark' : glyph-construction
|
|
assign-unicode 0x2120
|
|
include : doubleSuperscript glyphs.supS glyphs.supM
|
|
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
|
|
|
|
### 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.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' |