317 lines
15 KiB
Text
317 lines
15 KiB
Text
import '../support/point' as Point
|
|
import '../support/transform' as Transform
|
|
import [mix linreg clamp fallback] from '../support/utils'
|
|
import '../support/anchor' as Anchor
|
|
|
|
# Parameter generation
|
|
export : define [calculateMetrics para] : begin
|
|
define UPM 1000
|
|
define HalfUPM : UPM / 2
|
|
|
|
# Key metrics
|
|
define Width : Math.round para.width
|
|
define SB para.sb
|
|
define CAP para.cap
|
|
define XH para.xheight
|
|
define Descender : fallback para.descender (XH - CAP)
|
|
define Contrast : fallback para.contrast 1
|
|
# Key metrics for symbols
|
|
define symbolMid : fallback para.symbolMid (XH * 0.65)
|
|
define parenTop : symbolMid + para.parenSize / 2
|
|
define parenBot : symbolMid - para.parenSize / 2
|
|
|
|
define operTop : symbolMid + para.operSize * (Width - SB * 2)
|
|
define operBot : symbolMid - para.operSize * (Width - SB * 2)
|
|
define tackTop : symbolMid + para.tackSize * (Width - SB * 2)
|
|
define tackBot : symbolMid - para.tackSize * (Width - SB * 2)
|
|
define plusTop : symbolMid + para.plusSize * (Width - SB * 2)
|
|
define plusBot : symbolMid - para.plusSize * (Width - SB * 2)
|
|
define pictTop : symbolMid + para.pictSize * (Width - SB * 2)
|
|
define pictBot : symbolMid - para.pictSize * (Width - SB * 2)
|
|
define bgopTop : symbolMid + para.bgopSize * (Width - SB * 2)
|
|
define bgopBot : symbolMid - para.bgopSize * (Width - SB * 2)
|
|
|
|
|
|
# Transform constructors
|
|
define [Italify angle shift] : begin
|
|
local slope [Math.tan ([fallback angle para.slantAngle] / 180 * Math.PI)]
|
|
return : new Transform 1 slope 0 1 [fallback shift : -slope * symbolMid] 0
|
|
define [Upright angle shift] [Italify angle shift :.inverse]
|
|
define [Scale sx sy] : new Transform sx 0 0 [fallback sy sx] 0 0
|
|
define [Translate x y] : new Transform 1 0 0 1 x y
|
|
define [Rotate angle] : new Transform [Math.cos angle] (-[Math.sin angle]) [Math.sin angle] [Math.cos angle] 0 0
|
|
|
|
define globalTransform : Italify para.slantAngle
|
|
define TanSlope globalTransform.yx
|
|
define SINSLANT : Math.sin (para.slantAngle / 180 * Math.PI)
|
|
define COSSLANT : Math.cos (para.slantAngle / 180 * Math.PI)
|
|
define HVContrast : Contrast * COSSLANT + SINSLANT * TanSlope
|
|
|
|
# Orient parameters
|
|
define Upward : new Point (-HVContrast) 0
|
|
define Downward : new Point HVContrast 0
|
|
define Rightward : new Point TanSlope 1
|
|
define Leftward : new Point (- TanSlope) (-1)
|
|
|
|
define [UpwardT] : new Point (-HVContrast) 0
|
|
define [DownwardT] : new Point HVContrast 0
|
|
define [RightwardT] : new Point this.gizmo.yx 1
|
|
define [LeftwardT] : new Point (- this.gizmo.yx) (-1)
|
|
|
|
# Style parameters
|
|
define O para.overshoot
|
|
define OX para.overshootx
|
|
define OXHook para.oxhook
|
|
define Hook para.hook
|
|
define AHook para.ahook
|
|
define SHook para.shook
|
|
define RHook para.rhook
|
|
define JHook para.jhook
|
|
define FHook para.fhook
|
|
define HookX para.hookx
|
|
define Smooth para.smooth
|
|
define SmallSmooth para.smallsmooth
|
|
define Stroke para.stroke
|
|
define DotSize : fallback para.dotsize Stroke
|
|
define PeriodSize : fallback para.periodsize DotSize
|
|
define HBarPos : designParameters.hBarPos - 0.09 * Stroke / CAP
|
|
define OverlayPos designParameters.overlayPos
|
|
define Jut para.jut
|
|
define LongJut para.longjut
|
|
define MidJutSide : Math.max Jut : mix (0.5 * Stroke * HVContrast) LongJut 0.5
|
|
define MidJutCenter : Math.max Jut : mix (0.5 * Stroke * HVContrast) LongJut 0.6
|
|
define VJut para.vjut
|
|
define Accent para.accent
|
|
define AccentX para.accentx
|
|
|
|
define CThin : fallback para.cthin 0.75
|
|
define CThinB : fallback para.cthinb 0.5
|
|
|
|
define SLAB para.slab
|
|
|
|
define TailAdjX : Width * 0.2
|
|
define TailAdjY : XH * 0.25
|
|
define LBalance : LongJut * 0.04
|
|
define IBalance : fallback para.ibalance (LongJut * 0.04)
|
|
define LBalance2 : LongJut * 0.14
|
|
define IBalance2 : fallback para.ibalance (LongJut * 0.14)
|
|
define JBalance : fallback para.jbalance 0
|
|
define JBalance2 : fallback para.jbalance2 (Stroke * 0.25 + LBalance)
|
|
define TBalance : fallback para.tbalance JBalance
|
|
define TBalance2 : fallback para.tbalance2 TBalance
|
|
define RBalance : fallback para.rbalance (JBalance * 0.3)
|
|
define RBalance2 : fallback para.rbalance2 0
|
|
define FBalance : fallback para.fbalance 0
|
|
define OneBalance : fallback para.onebalance 0
|
|
|
|
# derived metrics
|
|
define MONOSPACE : para.diversityM == 1 && para.diversityF == 1 && para.diversityI == 1 && para.diversityII == 1
|
|
define WideWidth0 : if MONOSPACE (Width * 2) UPM
|
|
define WideWidth1 : if (para.spacing >= 1) WideWidth0 Width
|
|
define WideWidth2 : if (para.spacing >= 2) WideWidth0 Width
|
|
|
|
define Ess : Stroke * [fallback para.essx Contrast]
|
|
define EssQuestion : Stroke * [fallback para.essxq Contrast]
|
|
define HalfStroke : Stroke / 2
|
|
define RightSB : Width - SB
|
|
define Middle : Width / 2
|
|
define CapMiddle : CAP / 2
|
|
define DotRadius : DotSize / 2
|
|
define PeriodRadius : PeriodSize / 2
|
|
define SideJut : Jut - HalfStroke * HVContrast
|
|
|
|
define [StrokeWidthBlend min max sw] : linreg 18 min 126 max [fallback sw Stroke]
|
|
|
|
define SmoothAdjust : StrokeWidthBlend 80 144
|
|
define [SmoothAOf smooth width] : smooth - TanSlope * SmoothAdjust / Width * width
|
|
define [SmoothBOf smooth width] : smooth + TanSlope * SmoothAdjust / Width * width
|
|
define SmoothA : Smooth - TanSlope * SmoothAdjust
|
|
define SmoothB : Smooth + TanSlope * SmoothAdjust
|
|
define SmallSmoothA : SmallSmooth - TanSlope * SmoothAdjust
|
|
define SmallSmoothB : SmallSmooth + TanSlope * SmoothAdjust
|
|
|
|
|
|
define CorrectionOMidX : TanSlope * 0.9 * [StrokeWidthBlend 1.3 0.9]
|
|
define CorrectionOMidS : Stroke * CorrectionOMidX
|
|
|
|
# Blackness parameters
|
|
# We will estimate blackness using lower-case 'e'
|
|
local DarknessMockWidth : if (Width < HalfUPM) (HalfUPM * [Math.pow (Width / HalfUPM) 0.5]) Width
|
|
local DarknessMockWidth2 : HalfUPM * [Math.pow (Width / HalfUPM) 0.5]
|
|
define [WHITENESS div] : begin
|
|
local w : DarknessMockWidth * [fallback div 1] - SB * 2
|
|
return : ((XH - Stroke * 3) * w * (1 / 3)) / (XH * w)
|
|
define [adviceBlackness crowdedness div mul] : begin
|
|
local gap : DarknessMockWidth * [fallback div 1] - SB * 2
|
|
local shrink : (1 - [WHITENESS 1]) / (crowdedness * HVContrast)
|
|
return : Math.min Stroke ([fallback mul 1] * gap * shrink)
|
|
define [adviceBlackness2 cowX cowY refH div] : Math.min
|
|
adviceBlackness cowX (refH / DarknessMockWidth2)
|
|
adviceBlackness cowY div
|
|
define [MVertStrokeD div] : adviceBlackness designParameters.lllcrowdedness div
|
|
define MVertStroke : MVertStrokeD 1
|
|
define OverlayStroke : adviceBlackness 3.75
|
|
define OperatorStroke : adviceBlackness 3.125
|
|
define GeometryStroke : adviceBlackness 4.5
|
|
define ShoulderFine : Math.min (Stroke * para.shoulderfineMin) [adviceBlackness 16]
|
|
|
|
define Superness : fallback para.superness 2
|
|
define [superXY x superness] : Math.pow (1 - [Math.pow x [fallback superness Superness]]) (1 / [fallback superness Superness])
|
|
|
|
define [adviceSSmooth y sign _stroke] : begin
|
|
# Handle with extreme care.
|
|
local stroke : fallback _stroke Stroke
|
|
local strokeFactor : stroke * [clamp 1 2 : linreg 126 1 137 1.025 stroke] * [clamp 0 1 : Math.pow (Width / HalfUPM) 0.5]
|
|
local widthFactor : RightSB - SB
|
|
local ss : y * 0.21 + 0.375 * strokeFactor + 0.035 * widthFactor
|
|
return : ss + sign * TanSlope * (SmoothAdjust + 0.75 * stroke)
|
|
|
|
define [adviceGlottalStopSmooth y sign] : begin
|
|
return : ((y - Stroke) * 0.24 + Stroke * 0.625) + sign * TanSlope * SmoothAdjust
|
|
|
|
define [shoulderMidSlope _fine _stroke _dir] : begin
|
|
local stroke : fallback _stroke Stroke
|
|
local fine : fallback _fine ShoulderFine
|
|
local dir : fallback _dir 1
|
|
return : 0.5 * HVContrast * (stroke - fine) / stroke + dir * TanSlope
|
|
|
|
return [object
|
|
UPM HalfUPM Width SB CAP XH Descender Contrast symbolMid parenTop parenBot operTop operBot
|
|
tackTop tackBot plusTop plusBot pictTop pictBot bgopTop bgopBot Italify Upright Scale
|
|
Translate Rotate globalTransform TanSlope HVContrast Upward Downward Rightward Leftward
|
|
UpwardT DownwardT LeftwardT RightwardT O OX OXHook Hook AHook SHook RHook JHook FHook HookX
|
|
Smooth SmallSmooth Stroke DotSize PeriodSize HBarPos OverlayPos
|
|
LongJut Jut VJut Accent AccentX CThin CThinB SLAB TailAdjX TailAdjY LBalance
|
|
IBalance LBalance2 IBalance2 JBalance JBalance2 TBalance TBalance2 RBalance RBalance2
|
|
FBalance OneBalance WideWidth0 WideWidth1 WideWidth2 Ess EssQuestion
|
|
HalfStroke RightSB Middle CapMiddle DotRadius PeriodRadius SideJut SmoothA
|
|
SmoothB SmallSmoothA SmallSmoothB CorrectionOMidX CorrectionOMidS compositeBaseAnchors
|
|
adviceBlackness adviceBlackness2 MVertStroke MVertStrokeD OverlayStroke OperatorStroke
|
|
GeometryStroke ShoulderFine Superness superXY adviceSSmooth adviceGlottalStopSmooth
|
|
shoulderMidSlope StrokeWidthBlend SmoothAOf SmoothBOf SmoothAdjust MidJutSide MidJutCenter]
|
|
|
|
export : define [setFontMetrics para metrics fm] : begin
|
|
define [object CAP Descender XH Width] metrics
|
|
# Metric metadata
|
|
# Note: we use 1000upm in design, and (1000 * upmsacle)upm in production, to avoid rounding error.
|
|
define asc : para.leading * CAP / (CAP - Descender)
|
|
define desc : para.leading * Descender / (CAP - Descender)
|
|
define descenderPad : fallback para.descenderPad 0
|
|
|
|
set fm.OS_2.xAvgCharWidth Width
|
|
set fm.head.unitsPerEm 1000
|
|
set fm.hhea.ascender asc
|
|
set fm.OS_2.usWinAscent (asc + [fallback para.winMetricAscenderPad 0])
|
|
set fm.OS_2.sTypoAscender asc
|
|
|
|
set fm.hhea.descender (Descender - descenderPad)
|
|
set fm.OS_2.usWinDescent ([Math.abs desc] + descenderPad + [fallback para.winMetricDescenderPad 0])
|
|
set fm.OS_2.sTypoDescender (desc - descenderPad)
|
|
|
|
set fm.hhea.lineGap (para.leading - asc + Descender)
|
|
set fm.OS_2.sTypoLineGap (para.leading - asc + desc)
|
|
|
|
set fm.OS_2.sxHeight XH
|
|
set fm.OS_2.sCapHeight CAP
|
|
set fm.post.italicAngle (0 - para.slantAngle)
|
|
|
|
|
|
export : define [compositeBaseAnchors] : begin
|
|
local h {.}
|
|
foreach a [items-of arguments] : foreach k [items-of [Object.keys a.baseAnchors]] : begin
|
|
set h.(k) : new Anchor a.baseAnchors.(k).x a.baseAnchors.(k).y a.baseAnchors.(k).type a.baseAnchors.(k).mbx a.baseAnchors.(k).mby
|
|
return {.baseAnchors h .isMarkSet true}
|
|
|
|
export : define [MarksetDiv p me] : begin
|
|
define width : p * me.Width
|
|
define middle : p * me.Middle
|
|
define rightSB : me.Width * p - me.SB
|
|
define [ta anchor] : return : new Anchor
|
|
* (anchor.x * me.globalTransform.xx + anchor.y * me.TanSlope + me.globalTransform.x)
|
|
* (anchor.x * me.globalTransform.xy + anchor.y * me.globalTransform.yy + me.globalTransform.y)
|
|
|
|
define markAboveLower {.baseAnchors {.above [ta : new Anchor middle me.XH ]}}
|
|
define markAboveOper {.baseAnchors {.above [ta : new Anchor middle me.operTop ]}}
|
|
define markAboveTack {.baseAnchors {.above [ta : new Anchor middle me.tackTop ]}}
|
|
define markAbovePlus {.baseAnchors {.above [ta : new Anchor middle me.plusTop ]}}
|
|
define markAboveCap {.baseAnchors {.above [ta : new Anchor middle me.CAP ]}}
|
|
define markBelowLower {.baseAnchors {.below [ta : new Anchor middle me.Descender ]}}
|
|
define markBelowTack {.baseAnchors {.below [ta : new Anchor middle me.tackBot ]}}
|
|
define markBelowOper {.baseAnchors {.below [ta : new Anchor middle me.operBot ]}}
|
|
define markBelowPlus {.baseAnchors {.below [ta : new Anchor middle me.plusBot ]}}
|
|
define markBelowZero {.baseAnchors {.below [ta : new Anchor middle 0 ]}}
|
|
define markToprightLower {.baseAnchors {.topright [ta : new Anchor rightSB me.XH ]}}
|
|
define markToprightCap {.baseAnchors {.topright [ta : new Anchor rightSB me.CAP ]}}
|
|
define markBottomrightLower {.baseAnchors {.bottomright [ta : new Anchor rightSB me.Descender ]}}
|
|
define markBottomrightZero {.baseAnchors {.bottomright [ta : new Anchor rightSB 0 ]}}
|
|
define markTieAbove {.baseAnchors {.tieAbove [ta : new Anchor width (me.XH + me.Accent * 1.38)]}}
|
|
define markTieBelow {.baseAnchors {.tieBelow [ta : new Anchor width me.Descender ]}}
|
|
|
|
define [buildStandardMarkSet] : begin
|
|
local a : compositeBaseAnchors.apply null arguments
|
|
set a.baseAnchors.overlay : new Anchor
|
|
* [mix a.baseAnchors.below.x a.baseAnchors.above.x me.OverlayPos]
|
|
* [mix a.baseAnchors.below.y a.baseAnchors.above.y me.OverlayPos]
|
|
set a.baseAnchors.slash : new Anchor
|
|
* [mix a.baseAnchors.below.x a.baseAnchors.above.x 0.5]
|
|
* [mix a.baseAnchors.below.y a.baseAnchors.above.y 0.5]
|
|
return a
|
|
|
|
return : object
|
|
capital : buildStandardMarkSet markAboveCap markBelowZero markToprightCap markBottomrightZero markTieAbove markTieBelow
|
|
b : buildStandardMarkSet markAboveCap markBelowZero markToprightCap markBottomrightZero markTieAbove markTieBelow
|
|
e : buildStandardMarkSet markAboveLower markBelowZero markToprightLower markBottomrightZero markTieAbove markTieBelow
|
|
oper : buildStandardMarkSet markAboveOper markBelowOper markToprightLower markBottomrightZero markTieAbove markTieBelow
|
|
tack : buildStandardMarkSet markAboveTack markBelowTack markToprightLower markBottomrightZero markTieAbove markTieBelow
|
|
plus : buildStandardMarkSet markAbovePlus markBelowPlus markToprightLower markBottomrightZero markTieAbove markTieBelow
|
|
p : buildStandardMarkSet markAboveLower markBelowLower markToprightLower markBottomrightLower markTieAbove markTieBelow
|
|
if : buildStandardMarkSet markAboveCap markBelowLower markToprightCap markBottomrightLower markTieAbove markTieBelow
|
|
|
|
export : define designParameters : object
|
|
# V shape
|
|
straightVShapeSbShrink 0.8
|
|
straightSmallYShapeSbShrink 0.8
|
|
#
|
|
equal_wideness 0.075
|
|
logic_narrow_shrink 0.75
|
|
GeometricLargeX : lambda [mw uw] : (mw + uw / 2) / mw
|
|
geometric_small_x (4 / 7)
|
|
arrow_size 0.45
|
|
# ()
|
|
parenOutside 0.2
|
|
parenInside 0.9
|
|
parenCurliness 0.7
|
|
parenOvershoot 0.0375
|
|
# []
|
|
bracketOutside 0.1
|
|
bracketInside 0.95
|
|
# {}
|
|
braceOutside 0.05
|
|
braceInside 0.95
|
|
braceCurlyM1 0.6
|
|
braceCurlyM2 0.45
|
|
braceOvershoot 0.02
|
|
# Crosdedness
|
|
lllcrowdedness (3 + 1 / 3)
|
|
# Bar position
|
|
hBarPos 0.525
|
|
eBarPos 0.5
|
|
fiveBarPos 0.64
|
|
overlayPos 0.52
|
|
fBarPos 0.91
|
|
gBarPos 0.42
|
|
upperEBarPos : lambda [slab] : if slab 0.52 0.53
|
|
|
|
export : define [GenDivFrame metrics] : lambda [_div _hPack _sbMul] : begin
|
|
local div : fallback _div 1
|
|
local hPack : Math.max 2 [fallback _hPack 0]
|
|
local sbMul : fallback _sbMul : Math.min 1 : (metrics.Width * div - hPack * [metrics.adviceBlackness hPack div]) / (2 * hPack * metrics.SB)
|
|
return : object
|
|
div div
|
|
width : metrics.Width * div
|
|
middle : metrics.Middle * div
|
|
sb : metrics.SB * sbMul
|
|
leftSB : metrics.SB * sbMul
|
|
rightSB : metrics.Width * div - metrics.SB * sbMul
|
|
mvs : metrics.MVertStrokeD div
|
|
markSet: MarksetDiv div metrics
|