Iosevka/font-src/glyphs/common/derivatives.ptl

188 lines
7.2 KiB
Text

$$include '../../meta/macros.ptl'
import '../../support/transform' as Transform
import [mix linreg clamp fallback] from '../../support/utils'
import [Cv AnyCv AnyDerivingCv Dotless SvInheritableRelations] from '../../support/gr'
import [DesignParameters] from '../../meta/aesthetics'
extern Map
glyph-module
glyph-block Common-Derivatives : begin
glyph-block-import CommonShapes : FlipAround
define [ApplyCv g shapeFrom follow para] : begin
foreach { kPrime prime } para.variants.primes : foreach h [prime.variants.values] : begin
local suffix : h.resolveFor para follow
if suffix : begin
local dstName : shapeFrom + '.' + suffix
local dst : glyphStore.queryByName dstName
if dst : g.dependsOn dst
if (h.tag && h.rank) : begin
[Cv h.tag h.rank].set g dstName
if h.nonDeriving : [Cv h.tag h.rank].setPreventDeriving g
define [select-variant] : params [name unicode [shapeFrom name] [follow name]] : begin
if [not : glyph-is-needed name] : return nothing
local variant para.variantSelector.(follow)
if [not variant] : throw : new Error "Variant for \(name) is not assigned."
create-glyph name unicode : glyph-proc
include [refer-glyph (shapeFrom + '.' + variant)] AS_BASE ALSO_METRICS
ApplyCv currentGlyph shapeFrom follow para
currentGlyph.cloneRankFromGlyph [query-glyph (shapeFrom + '.' + variant)]
foreach gr [items-of SvInheritableRelations] : begin
local v : gr.get [query-glyph (shapeFrom + '.' + variant)]
if v : gr.set this v
define [orthographic-italic name unicode] : if para.isItalic
alias name unicode (name + '.italic')
alias name unicode (name + '.upright')
define [glyph-is-needed name] : [not pickHash] || pickHash.(name)
define [query-glyph id] : return : glyphStore.queryByName id
define [refer-glyph id] : lambda [copyAnchors copyWidth] : begin
local goal : query-glyph id
if [not goal] : throw : new Error "Cannot find glyph '\(id)'"
this.includeGlyph goal copyAnchors copyWidth
define [with-related-glyphs dstGid dstUnicode sourceGid Fn] : begin
if [not : glyph-is-needed sourceGid] : return nothing
local glyphSrc : glyphStore.queryByName sourceGid
local glyphDst : create-glyph dstGid dstUnicode : glyph-proc
include : Fn sourceGid null
local derivedGlyphIdMap : new Map
if glyphDst : foreach [gr : items-of : AnyDerivingCv.query glyphSrc] : begin
local relGidSrc : gr.get glyphSrc
if [derivedGlyphIdMap.get relGidSrc]
: then : gr.set glyphDst : derivedGlyphIdMap.get relGidSrc
: else : begin
local relGidDst : gr.amendName dstGid
create-glyph relGidDst : glyph-proc : include : Fn [gr.get glyphSrc] gr.tag
gr.set glyphDst relGidDst
derivedGlyphIdMap.set relGidSrc relGidDst
define [alias dstGid dstUnicode sourceGid] : begin
if [not dstGid] : throw : new Error "Target ID not specified"
if [not : glyph-is-needed sourceGid] : return nothing
local glyphSrc : glyphStore.queryByNameEnsured sourceGid
local glyphDst : create-glyph dstGid dstUnicode : glyph-proc
include [refer-glyph sourceGid] AS_BASE ALSO_METRICS
if glyphDst : begin
foreach [gr : items-of : AnyCv.query glyphSrc] : begin
gr.set glyphDst [gr.get glyphSrc]
if [gr.getPreventDeriving glyphSrc] : gr.setPreventDeriving glyphDst
if [Dotless.get glyphSrc] : Dotless.set glyphDst [Dotless.get glyphSrc]
define [turned newid unicode id _x _y mark] : begin
if [not newid] : throw : new Error "Target ID not specified"
with-related-glyphs newid unicode id
lambda [src sel] : glyph-proc
include [refer-glyph src] [if mark false AS_BASE] ALSO_METRICS
if mark : include mark
define x : if (_x <@ Function) [_x.call currentGlyph] _x
define y : if (_y <@ Function) [_y.call currentGlyph] _y
include : FlipAround x y
set currentGlyph.autoRefPriority [query-glyph src].autoRefPriority
# Dual derivatives
define [HCombine newid unicode id1 id2 spacing] : begin
if [not newid] : throw : new Error "Target ID not specified"
create-glyph newid unicode : glyph-proc
include [refer-glyph id1] AS_BASE ALSO_METRICS
include : Translate (-spacing) 0
include [refer-glyph id2]
include : Translate (spacing / 2) 0
define [HDual newid unicode id spacing] : begin
if [not newid] : throw : new Error "Target ID not specified"
return : HCombine newid unicode id id spacing
define [VCombine newid unicode id1 id2 spacing] : begin
if [not newid] : throw : new Error "Target ID not specified"
create-glyph newid unicode : glyph-proc
include [refer-glyph id2] AS_BASE ALSO_METRICS
include : Translate (-spacing * TanSlope) (-spacing)
include [refer-glyph id1]
include : Translate (spacing * TanSlope / 2) (spacing / 2)
define [VDual newid unicode id spacing] : begin
if [not newid] : throw : new Error "Target ID not specified"
return : VCombine newid unicode id id spacing
glyph-block-export select-variant orthographic-italic refer-glyph query-glyph with-related-glyphs
glyph-block-export alias turned HDual HCombine VDual VCombine glyph-is-needed
glyph-block Recursive-Build : begin
define [Fork gs ps] : begin
# BFS construct ShouldBuildList
local sbh : new Map
local PENDING 1
local CHECKED 2
foreach [glyphid : items-of gs] : sbh.set glyphid PENDING
local found true
while found : begin
set found false
foreach glyphid [sbh.keys] : if ([sbh.get glyphid] === PENDING) : begin
sbh.set glyphid CHECKED
local g : glyphStore.queryByName glyphid
if (g && g.dependencies) : foreach [k : items-of g.dependencies] : begin
if [not : sbh.has k] : begin
sbh.set k PENDING
set found true
local shouldBuildList { }
local shouldBuildUnicodes { }
foreach gn [sbh.keys] : if gn : begin
shouldBuildList.push gn
if [glyphStore.queryUnicodeOfName gn] : begin
shouldBuildUnicodes.push [glyphStore.queryUnicodeArrayOfName gn].0
local p {.}
foreach {k v} [pairs-of all ps] : set p.(k) v
local gs : buildGlyphs p shouldBuildList shouldBuildUnicodes
return gs.glyphStore
define [Miniature] : params [glyphs crowd scale [slopeAngle para.slopeAngle] [sbscale (Width / UPM)] [mono false]] : begin
local forkedPara : Object.create para
forkedPara.stroke = [AdviceStroke crowd : Math.pow [clamp 0 1 (HalfUPM / Width)] 0.5] / 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.slopeAngle = slopeAngle
if mono : begin
forkedPara.diversityM = 1
return : Fork glyphs forkedPara
define [Thinner glyphs p crowd] : begin
local forkedPara : Object.create para
forkedPara.stroke = [AdviceStroke : fallback crowd 1]
forkedPara.width = Width * p
forkedPara.accentx = AccentX * p
forkedPara.jut = Jut * p
forkedPara.longjut = LongJut * p
forkedPara.diversityM = 1
#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
return : Fork glyphs forkedPara
glyph-block-export Fork Miniature Thinner Widen