629 lines
26 KiB
Plaintext
629 lines
26 KiB
Plaintext
$$include '../meta/macros.ptl'
|
|
|
|
import '../support/transform' as : Transform && [object [transformPoint tp] [untransform utp] inverse]
|
|
import '../support/fairify' as fairify
|
|
|
|
import [mix linreg clamp fallback] from '../support/utils'
|
|
import [designParameters] from '../meta/aesthetics'
|
|
|
|
export : define [apply] : begin
|
|
glyph-module-entry
|
|
###### COMMON GLYPH CONSTRUCTIONS
|
|
define [select-variant name unicode default featureSelector] : begin
|
|
if (pickHash && [not pickHash.(name)]) : return nothing
|
|
local variant : variantSelector.(name) || default
|
|
local chosenGlyph glyphs.((name + '.' + variant))
|
|
create-glyph name : glyph-construction
|
|
include chosenGlyph AS_BASE ALSO_METRICS
|
|
if unicode : assign-unicode unicode
|
|
if featureSelector : set currentGlyph.featureSelector featureSelector
|
|
set this.cmpPriority chosenGlyph.cmpPriority
|
|
|
|
define [italic-variant name unicode] : create-glyph name : glyph-construction
|
|
if para.isItalic
|
|
then : include glyphs.(name + '.italic') AS_BASE
|
|
else : include glyphs.(name + '.upright') AS_BASE
|
|
if unicode : assign-unicode unicode
|
|
|
|
define [alias newid unicode oldid] : begin
|
|
create-glyph newid : glyph-construction
|
|
if unicode : assign-unicode unicode
|
|
include glyphs.(oldid) AS_BASE
|
|
set-width glyphs.(oldid).advanceWidth
|
|
set this.featureSelector glyphs.(oldid).featureSelector
|
|
set this.cmpPriority glyphs.(oldid).cmpPriority
|
|
|
|
define [composite newid] : let [parts : {}.slice.call arguments 1] : begin
|
|
create-glyph [fallback newid ('glyph' + [newtemp])] : glyph-construction
|
|
local first true
|
|
foreach [part : items-of parts] : begin
|
|
include part first
|
|
if first : set-width part.advanceWidth
|
|
set first false
|
|
|
|
define [into-unicode code] : glyph-construction
|
|
if code : assign-unicode code
|
|
|
|
# Transformation variants
|
|
define [turned newid unicode id x y mark] : create-glyph [fallback newid : 'turn' + id] : glyph-construction
|
|
if unicode : assign-unicode unicode
|
|
include glyphs.(id) [if mark false AS_BASE]
|
|
set-width glyphs.(id).advanceWidth
|
|
if mark : include mark
|
|
include : FlipAround x y
|
|
# Dual derivatives
|
|
define [dual newid unicode id spacing] : create-glyph [fallback newid : 'double' + id] : glyph-construction
|
|
if unicode : assign-unicode unicode
|
|
include glyphs.(id) AS_BASE
|
|
apply-transform : Translate (-spacing) 0
|
|
include glyphs.(id)
|
|
apply-transform : Translate (spacing / 2) 0
|
|
|
|
define [vdual newid unicode id spacing] : create-glyph [fallback newid : 'double' + id] : glyph-construction
|
|
if unicode : assign-unicode unicode
|
|
depends-on glyphs.(id)
|
|
include : create-glyph : glyph-construction
|
|
include glyphs.(id)
|
|
apply-transform : Upright
|
|
apply-transform : Translate 0 (-spacing)
|
|
include : create-glyph : glyph-construction
|
|
include glyphs.(id)
|
|
apply-transform : Upright
|
|
apply-transform : Translate 0 (spacing / 2)
|
|
apply-transform : Italify
|
|
# Full-width derivatives
|
|
define [fwl newid unicode id] : create-glyph [fallback newid : 'fwl' + id] : glyph-construction
|
|
if unicode : assign-unicode unicode
|
|
include glyphs.(id)
|
|
set-width FULLWIDTH
|
|
|
|
define [fwr newid unicode id] : create-glyph [fallback newid : 'fwr' + id] : glyph-construction
|
|
if unicode : assign-unicode unicode
|
|
include glyphs.(id)
|
|
set-width FULLWIDTH
|
|
apply-transform : Translate (FULLWIDTH - WIDTH) 0
|
|
|
|
define [dwl newid unicode id] : create-glyph [fallback newid : 'dwl' + id] : glyph-construction
|
|
if unicode : assign-unicode unicode
|
|
include glyphs.(id)
|
|
set-width UPM
|
|
|
|
define [dwr newid unicode id] : create-glyph [fallback newid : 'dwr' + id] : glyph-construction
|
|
if unicode : assign-unicode unicode
|
|
include glyphs.(id)
|
|
set-width UPM
|
|
apply-transform : Translate (UPM - WIDTH) 0
|
|
|
|
define [dwc newid unicode id] : create-glyph [fallback newid : 'dwc' + id] : glyph-construction
|
|
if unicode : assign-unicode unicode
|
|
include glyphs.(id)
|
|
set-width UPM
|
|
apply-transform : Translate ((UPM - WIDTH) / 2) 0
|
|
|
|
|
|
|
|
###### COMMON SHAPES
|
|
define [Ring u d l r transformShiftOnly] : create-glyph : glyph-construction
|
|
local my ((u + d) / 2)
|
|
local mx ((l + r) / 2)
|
|
currentGlyph.gizmo = [if transformShiftOnly [Translate 0 0] globalTransform]
|
|
include : spiro-outline
|
|
begin [lambda : set this.gizmo currentGlyph.gizmo]
|
|
g4 mx d
|
|
archv
|
|
g4 l my
|
|
arcvh
|
|
g4 mx u
|
|
archv
|
|
g4 r my
|
|
arcvh
|
|
close [lambda : begin [set this.angles 4] [set this.fairGizmo currentGlyph.gizmo]]
|
|
if transformShiftOnly : begin
|
|
local {.x mx1 .y my1} [tp globalTransform {.x mx .y my}]
|
|
apply-transform : Translate (mx1 - mx) (my1 - my)
|
|
define [RingAt x y r] : Ring (y + r) (y - r) (x - r) (x + r)
|
|
define [DotAt x y r] : Ring (y + r) (y - r) (x - r) (x + r) true
|
|
|
|
define [CircleRing u d l r transformShiftOnly] : create-glyph : glyph-construction
|
|
local my ((u + d) / 2)
|
|
local mx ((l + r) / 2)
|
|
currentGlyph.gizmo = [if transformShiftOnly [Translate 0 0] globalTransform]
|
|
include : spiro-outline
|
|
begin [lambda : set this.gizmo currentGlyph.gizmo]
|
|
g4 mx d
|
|
g4 l my
|
|
g4 mx u
|
|
g4 r my
|
|
close [lambda : begin [set this.angles 4] [set this.fairGizmo currentGlyph.gizmo]]
|
|
if transformShiftOnly : begin
|
|
local {.x mx1 .y my1} [tp globalTransform {.x mx .y my}]
|
|
apply-transform : Translate (mx1 - mx) (my1 - my)
|
|
define [CircleRingAt x y r] : CircleRing (y + r) (y - r) (x - r) (x + r)
|
|
define [CircleDotAt x y r] : CircleRing (y + r) (y - r) (x - r) (x + r) true
|
|
|
|
define [OShape u d l r _width _sma _smb ai] : glyph-construction
|
|
local middle : (l + r) / 2
|
|
local width : fallback _width STROKE
|
|
local sma : fallback _sma SMALLSMOOTHA
|
|
local smb : fallback _smb SMALLSMOOTHB
|
|
local mc : CORRECTION_OMIDX * width
|
|
if (u - d > sma + smb) : then : begin
|
|
include : dispiro
|
|
widths width 0
|
|
g4 (middle - mc) (u - O)
|
|
archv
|
|
[if ai flat.ai flat] (l + OX) (u - sma)
|
|
[if ai curl.ai curl] (l + OX) (d + smb)
|
|
arcvh
|
|
g4 (middle + mc) (d + O)
|
|
archv
|
|
[if ai flat.ai flat] (r - OX) (d + sma)
|
|
[if ai curl.ai curl] (r - OX) (u - smb)
|
|
arcvh
|
|
close
|
|
: else : begin
|
|
local ymiddlea : mix d u (smb / (sma + smb))
|
|
local ymiddleb : mix d u (sma / (sma + smb))
|
|
include : dispiro
|
|
widths width 0
|
|
g4 (middle - mc) (u - O)
|
|
archv
|
|
g4 (l + OX) ymiddlea
|
|
arcvh
|
|
g4 (middle + mc) (d + O)
|
|
archv
|
|
g4 (r - OX) ymiddleb
|
|
arcvh
|
|
close
|
|
define [OBarLeftShape _top _left] : glyph-construction
|
|
local top : fallback _top XH
|
|
local left : fallback _left SB
|
|
local fine SHOULDERFINE
|
|
local st : shoulderMidSlope fine nothing 1
|
|
local sb : shoulderMidSlope fine nothing (-1)
|
|
local mt : [mix left RIGHTSB 0.5] + (st - CORRECTION_OMIDX) * STROKE
|
|
local mb : [mix left RIGHTSB 0.5] + (sb + CORRECTION_OMIDX) * STROKE
|
|
include : dispiro
|
|
widths.lhs
|
|
g4 (mt) (top - O) [heading {.y (-1) .x (-st)}]
|
|
archv
|
|
flat (left + (STROKE - fine) * HVCONTRAST) (top - SMALLSMOOTHA) [widths fine 0]
|
|
curl (left + (STROKE - fine) * HVCONTRAST) (0 + SMALLSMOOTHB) [widths fine 0]
|
|
arcvh
|
|
g4 (mb) O [widths.heading STROKE 0 {.y (1) .x (-sb)}]
|
|
archv
|
|
[if ((SMALLSMOOTHA + SMALLSMOOTHB) / top > 0.75) flat.ai flat] (RIGHTSB - OX) (0 + SMALLSMOOTHA)
|
|
[if ((SMALLSMOOTHA + SMALLSMOOTHB) / top > 0.75) curl.ai curl] (RIGHTSB - OX) (top - SMALLSMOOTHB)
|
|
arcvh
|
|
close
|
|
|
|
define [OBarRightShape top right] : glyph-construction
|
|
include : create-glyph [OBarLeftShape top (WIDTH - [fallback right RIGHTSB])]
|
|
include : FlipAround MIDDLE ([fallback top XH] / 2)
|
|
|
|
define SERIF_SHIFT_X 0.6
|
|
define [LeftwardTopSerif x y length _sw] : glyph-construction
|
|
local sw : fallback _sw STROKE
|
|
include : dispiro
|
|
flat (x + HALFSTROKE * HVCONTRAST) y [widths.heading sw 0 LEFTWARD]
|
|
curl (x - length - TANSLANT * (sw * SERIF_SHIFT_X)) y
|
|
|
|
define [LeftwardBottomSerif x y length _sw] : glyph-construction
|
|
local sw : fallback _sw STROKE
|
|
include : dispiro
|
|
flat (x + HALFSTROKE * HVCONTRAST) y [widths.heading 0 sw LEFTWARD]
|
|
curl (x - length + TANSLANT * (sw * SERIF_SHIFT_X)) y
|
|
|
|
define [RightwardTopSerif x y length _sw] : glyph-construction
|
|
local sw : fallback _sw STROKE
|
|
include : dispiro
|
|
flat (x - HALFSTROKE * HVCONTRAST) y [widths.heading 0 sw RIGHTWARD]
|
|
curl (x + length - TANSLANT * (sw * SERIF_SHIFT_X)) y
|
|
|
|
define [RightwardBottomSerif x y length _sw] : glyph-construction
|
|
local sw : fallback _sw STROKE
|
|
include : dispiro
|
|
flat (x - HALFSTROKE * HVCONTRAST) y [widths.heading sw 0 RIGHTWARD]
|
|
curl (x + length + TANSLANT * (sw * SERIF_SHIFT_X)) y
|
|
|
|
define [CenterTopSerif x y length _sw] : glyph-construction
|
|
local sw : fallback _sw STROKE
|
|
include : dispiro
|
|
flat (x + length - TANSLANT * (sw * SERIF_SHIFT_X)) y [widths sw 0]
|
|
curl (x - length - TANSLANT * (sw * SERIF_SHIFT_X)) y
|
|
|
|
define [CenterBottomSerif x y length _sw] : glyph-construction
|
|
local sw : fallback _sw STROKE
|
|
include : dispiro
|
|
flat (x + length + TANSLANT * (sw * SERIF_SHIFT_X)) y [widths 0 sw]
|
|
curl (x - length + TANSLANT * (sw * SERIF_SHIFT_X)) y
|
|
|
|
define [DownwardRightSerif x y length sw] : glyph-construction
|
|
include : dispiro
|
|
widths.rhs sw
|
|
flat x y [heading DOWNWARD]
|
|
curl x (y - length) [heading DOWNWARD]
|
|
define [UpwardRightSerif x y length sw] : glyph-construction
|
|
include : dispiro
|
|
widths.lhs sw
|
|
flat x y [heading UPWARD]
|
|
curl x (y + length) [heading UPWARD]
|
|
define [DownwardLeftSerif x y length sw] : glyph-construction
|
|
include : dispiro
|
|
widths.lhs sw
|
|
flat x y [heading DOWNWARD]
|
|
curl x (y - length) [heading DOWNWARD]
|
|
define [UpwardLeftSerif x y length sw] : glyph-construction
|
|
include : dispiro
|
|
widths.rhs sw
|
|
flat x y [heading UPWARD]
|
|
curl x (y + length) [heading UPWARD]
|
|
|
|
define sideSerifK 0.5
|
|
define [AIVSerifs top _left _right] : glyph-construction
|
|
local left : fallback _left SB
|
|
local right : fallback _right RIGHTSB
|
|
if SLAB : begin
|
|
include : CenterTopSerif (left + STROKE * sideSerifK * HVCONTRAST) top JUT
|
|
tag-contour 'serifLT'
|
|
include : CenterTopSerif (right - STROKE * sideSerifK * HVCONTRAST) top JUT
|
|
tag-contour 'serifRT'
|
|
define [AIHSerifs top _left _right] : glyph-construction
|
|
local left : fallback _left SB
|
|
local right : fallback _right RIGHTSB
|
|
if SLAB : begin
|
|
include : AIVSerifs top _left _right
|
|
include : CenterBottomSerif (left + STROKE * sideSerifK * HVCONTRAST) 0 JUT
|
|
include : CenterBottomSerif (right - STROKE * sideSerifK * HVCONTRAST) 0 JUT
|
|
define [AINSerifs top _left _right sw xn] : glyph-construction
|
|
local left : fallback _left SB
|
|
local right : fallback _right RIGHTSB
|
|
local jut : JUT * [fallback xn 1]
|
|
if SLAB : begin
|
|
include : LeftwardTopSerif (left + sw * (sideSerifK - 0.5) * HVCONTRAST) top (jut - sw / 2 * HVCONTRAST)
|
|
include : CenterTopSerif (right - sw * sideSerifK * HVCONTRAST) top jut
|
|
include : CenterBottomSerif (left + sw * sideSerifK * HVCONTRAST) 0 jut
|
|
tag-contour 'serifLB'
|
|
#include : CenterdBottomSerif (right - STROKE * (sideSerifK - 0.5) * HVCONTRAST) 0 (JUT / 2)
|
|
define [AICyrISerifs top _left _right] : glyph-construction
|
|
local left : fallback _left SB
|
|
local right : fallback _right RIGHTSB
|
|
if SLAB : begin
|
|
include : LeftwardBottomSerif left 0 SIDEJUT
|
|
include : RightwardTopSerif right top SIDEJUT
|
|
include : CenterTopSerif (left + STROKE * sideSerifK * HVCONTRAST) top JUT
|
|
include : CenterBottomSerif (right - STROKE * sideSerifK * HVCONTRAST) 0 JUT
|
|
tag-contour 'serifRB'
|
|
define [AIMSerifs top _left _right] : glyph-construction
|
|
local left : fallback _left SB
|
|
local right : fallback _right RIGHTSB
|
|
if SLAB : begin
|
|
include : LeftwardTopSerif (left + STROKE * (sideSerifK - 0.5) * HVCONTRAST) top SIDEJUT
|
|
include : RightwardTopSerif (right - STROKE * (sideSerifK - 0.5) * HVCONTRAST) top SIDEJUT
|
|
include : CenterBottomSerif (left + STROKE * sideSerifK * HVCONTRAST) 0 JUT
|
|
include : CenterBottomSerif (right - STROKE * sideSerifK * HVCONTRAST) 0 JUT
|
|
|
|
|
|
define [halfXStrand _leftx lefty rightx righty turn straight tension _fine] : glyph-construction
|
|
local leftx : _leftx + (HALFSTROKE * HVCONTRAST * [if (rightx > _leftx) 1 (-1)])
|
|
local fine : (_fine || STROKE) * 0.5
|
|
|
|
local turnyleft : mix lefty righty turn
|
|
local cyleft : mix turnyleft righty tension
|
|
|
|
local straightxleft : mix leftx rightx straight
|
|
local straightyleft : mix cyleft righty straight
|
|
|
|
include : dispiro
|
|
widths.center
|
|
flat leftx lefty [heading [if (lefty < righty) UPWARD DOWNWARD]]
|
|
curl leftx turnyleft [heading [if (lefty < righty) UPWARD DOWNWARD]]
|
|
quadcontrols 0 ((cyleft - turnyleft) / (straightyleft - turnyleft)) 24
|
|
flat straightxleft straightyleft
|
|
curl rightx righty
|
|
end [function : set this.cleanmore true]
|
|
|
|
|
|
define [xStrand _leftx lefty _rightx righty turn straight tension] : glyph-construction
|
|
local middlex : mix _leftx _rightx 0.5
|
|
local middley : mix lefty righty 0.5
|
|
|
|
include : halfXStrand _leftx lefty middlex middley turn straight tension
|
|
include : halfXStrand _rightx righty middlex middley turn straight tension
|
|
|
|
define [nShoulderKnots] : params [left right [fine SHOULDERFINE] [top XH] [bottom 0] [sma SMALLSMOOTHA] [smb SMALLSMOOTHB] [stroke STROKE]] : begin
|
|
local slope : shoulderMidSlope fine stroke
|
|
local middle : [mix (left - stroke * HVCONTRAST) right 0.5] + (slope - CORRECTION_OMIDX) * stroke
|
|
return : list
|
|
flat left (top - sma - 2) [widths fine 0]
|
|
curl left (top - sma)
|
|
arcvh
|
|
g4 middle (top - O) [widths.heading 0 stroke {.y (1) .x (slope)}]
|
|
archv
|
|
flat right (top - smb)
|
|
curl right bottom [heading DOWNWARD]
|
|
|
|
define [nShoulder] : begin
|
|
local a arguments
|
|
glyph-construction
|
|
include : dispiro : nShoulderKnots.apply null a
|
|
|
|
|
|
define [mShoulderSpiro] : params [left right top bottom width fine] : glyph-construction
|
|
local fix : TANSLANT * STROKE * HVCONTRAST * width / STROKE
|
|
local sm : SMALLSMOOTH * 0.75
|
|
include : spiro-outline
|
|
corner (right - width * HVCONTRAST) bottom
|
|
curl (right - width * HVCONTRAST) (top - sm + fix)
|
|
arcvh 8 'no-tiny'
|
|
g2 [mix left (right - width * HVCONTRAST) 0.5] (top - O - width)
|
|
archv 8 'no-tiny'
|
|
flat left (top - sm - fix)
|
|
corner left (top - sm - fix - 1)
|
|
corner (left - fine) (top - sm - 1)
|
|
curl (left - fine) (top - sm)
|
|
arcvh 8 'no-tiny'
|
|
g2 [mix (left - fine * HVCONTRAST) right 0.5] (top - O)
|
|
archv 8 'no-tiny'
|
|
flat right (top - sm)
|
|
corner right bottom
|
|
close
|
|
|
|
define [HBar xleft xright y _fine] : glyph-construction
|
|
include : dispiro
|
|
widths.center [fallback _fine STROKE]
|
|
flat xleft y [heading RIGHTWARD]
|
|
curl xright y [heading RIGHTWARD]
|
|
|
|
define [HBarTop xl xr y _fine] : HBar xl xr (y - [fallback _fine STROKE] * 0.5) _fine
|
|
define [HBarBottom xl xr y _fine] : HBar xl xr (y + [fallback _fine STROKE] * 0.5) _fine
|
|
define [HOverlayBar xleft xright y s] : dispiro
|
|
widths.center [fallback s OVERLAYSTROKE]
|
|
flat xleft y
|
|
curl xright y
|
|
define [VBar x ydown yup _fine] : glyph-construction
|
|
local fine : fallback _fine STROKE
|
|
include : dispiro
|
|
widths.center fine
|
|
flat x ydown [heading [if (ydown < yup) UPWARD DOWNWARD]]
|
|
curl x yup [heading [if (ydown < yup) UPWARD DOWNWARD]]
|
|
|
|
define [VBarLeft x yd yu _fine] : VBar (x + [fallback _fine STROKE] * 0.5 * HVCONTRAST) yd yu _fine
|
|
define [VBarRight x yd yu _fine] : VBar (x - [fallback _fine STROKE] * 0.5 * HVCONTRAST) yd yu _fine
|
|
|
|
define [VerticalHook x y extend depth fine strg] : glyph-construction
|
|
include : dispiro
|
|
widths.center [fallback fine STROKE]
|
|
flat x (y + [fallback strg 0]) [heading [if (depth > 0) DOWNWARD UPWARD]]
|
|
curl x (y - [if (depth > 0) 0.01 (-0.01)]) [heading [if (depth > 0) DOWNWARD UPWARD]]
|
|
arcvh
|
|
flat (x + extend - [if (extend > 0) 0.01 (-0.01)]) (y - depth)
|
|
curl (x + extend) (y - depth)
|
|
|
|
define [LegShape] : params [[ztop nothing (xt <> top)] [zbot nothing (xs <> bottom)] xb [fine STROKE]] : glyph-construction
|
|
include : dispiro
|
|
widths.lhs fine
|
|
flat xt top [heading DOWNWARD]
|
|
curl xb (bottom + LONGJUT)
|
|
alsothruthem {{0.5 0.94}}
|
|
g4.left.end xs (bottom + fine) [heading LEFTWARD]
|
|
|
|
define [LeftHook x y xextend] : glyph-construction
|
|
local fine : adviceBlackness 4.25
|
|
include : dispiro
|
|
widths.lhs fine
|
|
flat [fallback xextend : x + 1] y
|
|
curl x y
|
|
archv 8
|
|
g4.down.end (x - LeftHook.extension) (y - HOOKX) [heading DOWNWARD]
|
|
set LeftHook.extension [Math.max (WIDTH * 0.15) ([adviceBlackness 4.25] * 1.5)]
|
|
|
|
define [HooktopLeftBar stroke bottom] : glyph-construction
|
|
include : dispiro
|
|
widths.lhs [fallback stroke STROKE]
|
|
g4 RIGHTSB (CAP - HOOK)
|
|
hookstart CAPO
|
|
flat SB (CAP - SMALLSMOOTHA)
|
|
curl SB [fallback bottom 0] [heading DOWNWARD]
|
|
|
|
define [CurlyTail] : params [fine rinner xleft bottom right x2 y2 [adj 0.4] [adj2 0.4] [adj3 0]] : begin
|
|
local ltr : right > xleft
|
|
set right : right - fine * [if ltr 1 (-1)]
|
|
local mid : mix [mix xleft right 0.5] (right - rinner * [if ltr 1 (-1)]) adj
|
|
local midu : mix [mix xleft right 0.5] (right - rinner * [if ltr 1 (-1)]) adj2
|
|
return : list
|
|
g4.[if ltr 'right' 'left'].mid (mid + CORRECTION_OMIDX * fine * adj3 * [if ltr 1 (-1)]) (bottom + fine + O) [widths [if ltr 0 fine] [if ltr fine 0]]
|
|
archv 2
|
|
g4 right (bottom + fine + rinner - 0.1)
|
|
g4 right (bottom + fine + rinner + 0.1)
|
|
arcvh 2
|
|
g4 mid (bottom + fine + rinner * 2 - O)
|
|
alsothruthem {{0.25 0.06} {0.52 0.25}} important
|
|
g4 x2 y2
|
|
|
|
define [HCurlyTail fine wide rinner left m1 _right x1 x2 y2] : glyph-construction
|
|
local right : _right - fine
|
|
local mid : right - rinner + O
|
|
include : dispiro
|
|
widths.rhs wide
|
|
flat left wide [heading RIGHTWARD]
|
|
curl m1 wide [heading RIGHTWARD]
|
|
archv 8
|
|
g4 right (wide + rinner - O / 2) [widths.heading 0 fine {.x (-HVCONTRAST) .y ((wide - fine) / (wide + rinner * 2 - O))}]
|
|
arcvh 8
|
|
g4.left.mid mid (wide + rinner * 2 - O) [heading LEFTWARD]
|
|
quadcontrols ((x1 - mid) / (x2 - mid)) 0 8
|
|
g4 x2 y2
|
|
|
|
define [FlatSlashShape middlex middle fine kx ky] : glyph-construction
|
|
include : dispiro
|
|
flat (middlex - LONGJUT * [fallback kx 0.8]) (middle - LONGJUT * [fallback ky 0.4]) [widths fine fine]
|
|
curl (middlex + LONGJUT * [fallback kx 0.8]) (middle + LONGJUT * [fallback ky 0.4])
|
|
|
|
# Spiro shapes
|
|
define [determineMixR w v u sw] : begin
|
|
local r : piecewise
|
|
(w <= v) 0.5
|
|
true : 1 / ([Math.pow (1 - [Math.pow (1 - v / w) SUPERNESS]) (1 / SUPERNESS)] + 1)
|
|
local idepth : w - sw
|
|
local iwidth : u * r - sw
|
|
if (iwidth > 0 && idepth > 0 && iwidth / idepth >= 2) : begin
|
|
local adjust : clamp 0.975 1 (1 - (iwidth / idepth - 2) * 0.0125)
|
|
#console.log iwidth idepth (iwidth / idepth) adjust
|
|
r = r * adjust
|
|
if (r < 0.5) : set r 0.5
|
|
return r
|
|
|
|
define nHookSegments 12
|
|
define [HookShape toStraight toFinish isStart y tight s kkaf dontadjust] : begin
|
|
local atBottom : toStraight.y > y
|
|
local sw : fallback s STROKE
|
|
local ltr : if isStart (toFinish.x < toStraight.x) (toFinish.x > toStraight.x)
|
|
local dtu : if isStart (y > toFinish.y) (y < toFinish.y)
|
|
|
|
if [not dontadjust] : begin
|
|
toFinish.x = toFinish.x + OXHOOK * [if ltr (-1) 1] * [if isStart (-1) 1]
|
|
if (atBottom && ltr && !isStart) : begin
|
|
toFinish.x = toFinish.x + TAILADJX * TANSLANT
|
|
toFinish.y = toFinish.y - TAILADJY * TANSLANT
|
|
|
|
local w : Math.abs (toStraight.y - y)
|
|
local v : Math.abs (toFinish.y - y)
|
|
local u : Math.abs (toFinish.x - toStraight.x)
|
|
local mixr : determineMixR w v u sw
|
|
local mx ([mix toStraight.x toFinish.x mixr] + ([if (tight && tight.shift) tight.shift (1 - (tight || 0))] * [if atBottom 1 (-1)] * CORRECTION_OMIDX) * sw)
|
|
local keyKnot : g4.[if ltr "right" "left"].mid mx y [fallback kkaf : if tight [let [s : if ltr RIGHTWARD LEFTWARD] [heading {.x (s.x * [fallback tight.skew 1]) .y s.y}]] nothing]
|
|
|
|
local faf toFinish.af
|
|
set toFinish.af : lambda [] : begin
|
|
local rad : Math.min w (mixr * u)
|
|
local skew0 : [clamp 0 w (w - v)] / rad + ([clamp 1 1.5 (mixr * u / w)] - 1) * 0.5
|
|
local depth : v + skew0 * sw - sw
|
|
local shallowLimit (sw * 0.5)
|
|
local skew : clamp 0 (1 / 2) : skew0 + [clamp 0 shallowLimit (shallowLimit - depth)] / rad
|
|
if faf : faf.apply this arguments
|
|
this.heads-to {
|
|
.x (CONTRAST / [Math.sqrt : 1 + skew * skew] * [if dtu (-1) 1])
|
|
.y (skew / [Math.sqrt : 1 + skew * skew] * [if ltr 1 (-1)])
|
|
}
|
|
|
|
local segBefore {}
|
|
local segAfter {}
|
|
foreach [j : range 1 nHookSegments] : begin
|
|
local fraction : j / nHookSegments
|
|
local fractionAfter : fraction * (1 - mixr) / mixr
|
|
local myfinal : superxy ((1 - mixr) / mixr)
|
|
segBefore.push : g4 [mix mx toStraight.x fraction] [mix y toStraight.y (1 - [superxy fraction])] unimportant
|
|
segAfter.push : g4 [mix mx toFinish.x fraction] [mix y toFinish.y ((1 - [superxy fractionAfter]) / (1 - myfinal))] unimportant
|
|
if (!tight && w < u * mixr) : set segAfter {}
|
|
if isStart
|
|
: then : return : list
|
|
segAfter.reverse
|
|
* keyKnot
|
|
* segBefore
|
|
: else : return : list
|
|
segBefore.reverse
|
|
* keyKnot
|
|
* segAfter
|
|
|
|
define [hookstart] : params [y tight sw kkaf dontadjust] : return {
|
|
.type 'interpolate'
|
|
.af [lambda [before after] [HookShape after before true y tight sw kkaf dontadjust]]
|
|
}
|
|
define [hookend] : params [y tight sw kkaf dontadjust] : return {
|
|
.type 'interpolate'
|
|
.af [lambda [before after] [HookShape before after false y tight sw kkaf dontadjust]]
|
|
}
|
|
|
|
define [WaveShape] : params [l r cy extendy tension sw] : glyph-construction
|
|
local cx : mix l r 0.5
|
|
local wavex : (r - l) * tension
|
|
local endwavey : extendy * 0.97
|
|
include : dispiro
|
|
widths.center sw
|
|
g4 l (cy - endwavey)
|
|
bezcontrols.absolute (l + wavex) (cy + extendy) (cx - wavex * 0.8) (cy + extendy) 8 important
|
|
g4 cx cy
|
|
bezcontrols.absolute (cx + wavex * 0.8) (cy - extendy) (r - wavex) (cy - extendy) 8 important
|
|
g4 r (cy + endwavey)
|
|
|
|
define [CyrDescender x shift connex] : glyph-construction
|
|
local descenderOverflow : if SLAB SIDEJUT ((RIGHTSB - SB) * [fallback shift 0.1])
|
|
include : VBarRight (x + descenderOverflow + 0.25 * STROKE) (HALFSTROKE - LONGJUT) STROKE
|
|
if (!SLAB && descenderOverflow > STROKE * 0.75 || connex) : include : HBarTop (x - HALFSTROKE * HVCONTRAST) (x + descenderOverflow) STROKE
|
|
|
|
# Derived subfonts
|
|
define [refair g] : begin
|
|
foreach [j : range 0 g.contours.length] : begin
|
|
set g.contours.(j) : fairify g.contours.(j) globalTransform
|
|
return nothing
|
|
define [Fork gs ps] : begin
|
|
# BFS construct ShouldBuildList
|
|
local sbh {.}
|
|
local found true
|
|
local PENDING 1
|
|
local CHECKED 2
|
|
foreach [glyphid : items-of gs] : set sbh.(glyphid) PENDING
|
|
while found : begin
|
|
set found false
|
|
foreach [glyphid : items-of : Object.keys sbh] : if (sbh.(glyphid) === PENDING) : begin
|
|
set sbh.(glyphid) CHECKED
|
|
if dependencyProfile.(glyphid) : foreach [k : items-of dependencyProfile.(glyphid)] : if [not sbh.(k)] : begin
|
|
set sbh.(k) PENDING
|
|
set found true
|
|
|
|
local shouldBuildList : Object.keys sbh :.filter ([x] => [not [not x]])
|
|
#console.log shouldBuildList
|
|
local shouldBuildUnicodes : shouldBuildList.map ([x] => [if (glyphs.(x) && glyphs.(x).unicode) glyphs.(x).unicode.0 nothing])
|
|
:.filter ([x] => [not [not x]])
|
|
|
|
local p {.}
|
|
foreach [{k v} : pairs-of all ps] : set p.(k) v
|
|
try : begin
|
|
local forkFont : buildFont.call [TempFont] p shouldBuildList shouldBuildUnicodes
|
|
: ex
|
|
: begin
|
|
if ex.glyfMap : return ex.glyfMap
|
|
: else : throw ex
|
|
return forkFont.glyfMap
|
|
|
|
define [Miniature] : params [glyphs crowd scale [slantAngle para.slantAngle] unfair [sbscale 0.5]] : begin
|
|
local forkedPara : Object.create para
|
|
forkedPara.stroke = [adviceBlackness crowd] / scale
|
|
forkedPara.ess = para.ess * forkedPara.stroke / para.stroke
|
|
forkedPara.dotsize = para.dotsize * forkedPara.stroke / para.stroke
|
|
forkedPara.periodsize = para.periodsize * forkedPara.stroke / para.stroke
|
|
forkedPara.sb = SB * sbscale
|
|
forkedPara.slantAngle = slantAngle
|
|
forkedPara.unfair = unfair
|
|
return : Fork glyphs forkedPara
|
|
|
|
define [Thinner glyphs p] : begin
|
|
local forkedPara : Object.create para
|
|
forkedPara.width = WIDTH * p
|
|
forkedPara.accentx = ACCENTX * p
|
|
forkedPara.jut = JUT * p
|
|
forkedPara.longjut = LONGJUT * p
|
|
#forkedPara.hookx = HOOKX * p
|
|
return : Fork glyphs forkedPara
|
|
|
|
define [Widen glyphs p psb] : begin
|
|
local forkedPara : Object.create para
|
|
forkedPara.width = WIDTH * p
|
|
forkedPara.sb = SB * [fallback psb p]
|
|
forkedPara.accentx = ACCENTX * p
|
|
forkedPara.jut = JUT * p
|
|
forkedPara.longjut = LONGJUT * p
|
|
forkedPara.hookx = HOOKX * p
|
|
forkedPara.smoothadjust = para.smoothadjust * p
|
|
return : Fork glyphs forkedPara
|
|
|
|
# Composite transformations
|
|
define [FlipAround x y sx sy] : glyph-construction
|
|
apply-transform : Upright
|
|
apply-transform : Translate (-x) (-y)
|
|
apply-transform : Scale [fallback sx (-1)] [fallback sy sx (-1)]
|
|
apply-transform : Translate x y
|
|
apply-transform : Italify
|
|
|
|
return [object select-variant italic-variant alias composite into-unicode turned dual vdual fwl fwr dwl dwr dwc Ring RingAt DotAt CircleRing CircleRingAt CircleDotAt OShape OBarLeftShape OBarRightShape LeftwardTopSerif LeftwardBottomSerif RightwardTopSerif RightwardBottomSerif CenterTopSerif CenterBottomSerif DownwardRightSerif UpwardRightSerif DownwardLeftSerif UpwardLeftSerif AIVSerifs AIHSerifs AINSerifs AICyrISerifs AIMSerifs halfXStrand xStrand nShoulderKnots nShoulder mShoulderSpiro HBar HBarTop HBarBottom HOverlayBar VBar VBarLeft VBarRight VerticalHook LegShape LeftHook HooktopLeftBar CurlyTail HCurlyTail FlatSlashShape determineMixR HookShape hookstart hookend WaveShape CyrDescender refair Fork Miniature Thinner Widen FlipAround] |