Move the glyph saving logic to MJS side (#2479)
This commit is contained in:
parent
499b97e3a1
commit
5ee209c97f
5 changed files with 84 additions and 68 deletions
|
@ -1,6 +1,6 @@
|
|||
import [Glyph GlyphProc ForkGlyphProc] from "@iosevka/glyph"
|
||||
import [GlyphStore] from "@iosevka/glyph/store"
|
||||
import [GlyphBlock GlyphBuildExecutor] from "@iosevka/glyph/block"
|
||||
import [GlyphBlock GlyphBuildExecutor GlyphSaveSink] from "@iosevka/glyph/block"
|
||||
import as Gr from "@iosevka/glyph/relation"
|
||||
import as SpiroKit from "@iosevka/font-kits/spiro-kit"
|
||||
import as BooleKit from "@iosevka/font-kits/boole-kit"
|
||||
|
@ -15,7 +15,6 @@ $$include './meta/macros.ptl'
|
|||
export : define [buildGlyphs para recursive] : begin
|
||||
# Execution and dependency management
|
||||
local $Exec$ : new GlyphBuildExecutor recursive
|
||||
define [glyph-is-needed name] : [not recursive] || [recursive.glyphIsNeeded name]
|
||||
|
||||
# Initialize glyph store
|
||||
local glyphStore : new GlyphStore
|
||||
|
@ -32,45 +31,8 @@ export : define [buildGlyphs para recursive] : begin
|
|||
# Anchor parameters
|
||||
define {AS_BASE ALSO_METRICS} {'AS-BASE' 'ALSO-METRICS'}
|
||||
|
||||
# The callback used to create and save glyphs
|
||||
define [$createAndSaveGlyphImpl$ _1 _2 actions] : begin
|
||||
local saveGlyphName null
|
||||
local unicode null
|
||||
|
||||
piecewise
|
||||
([typeof _1] === 'number' && _1) : begin
|
||||
set saveGlyphName : 'uni' + [_1.toString 16 :.padStart 4 '0' :.toUpperCase]
|
||||
set unicode _1
|
||||
([typeof _1] === 'string' && _1) : begin
|
||||
set saveGlyphName _1
|
||||
set unicode _2
|
||||
true : begin
|
||||
set saveGlyphName null
|
||||
set unicode null
|
||||
|
||||
if (saveGlyphName && [not : glyph-is-needed saveGlyphName]) : return nothing
|
||||
if para.verbose : console.log saveGlyphName
|
||||
|
||||
local glyphObject [new Glyph saveGlyphName]
|
||||
glyphObject.setWidth Metrics.Width
|
||||
glyphObject.gizmo = Metrics.GlobalTransform
|
||||
glyphObject._m_dependencyManager = $Exec$.dependencyManager
|
||||
|
||||
glyphObject.include actions true true
|
||||
|
||||
$Exec$.setGlyphToBlockDependency glyphObject
|
||||
|
||||
if saveGlyphName : begin
|
||||
if (saveGlyphName.0 != '.' && [glyphStore.queryByName saveGlyphName])
|
||||
throw : new Error "Glyph \(saveGlyphName) already exists"
|
||||
glyphStore.addGlyph saveGlyphName glyphObject
|
||||
if unicode : begin
|
||||
local u unicode
|
||||
if ([typeof unicode] === "string") : begin
|
||||
set u [unicode.codePointAt 0]
|
||||
glyphStore.encodeGlyph u glyphObject
|
||||
|
||||
return glyphObject
|
||||
# Glyph saving sink
|
||||
define $GlyphSaveSink$ : new GlyphSaveSink $Exec$ Metrics glyphStore
|
||||
|
||||
# Spiro kit and boole kit
|
||||
define SpiroFns : SpiroKit.SetupBuilders : object
|
||||
|
@ -86,9 +48,9 @@ export : define [buildGlyphs para recursive] : begin
|
|||
|
||||
# Setup the capture
|
||||
define $$Capture$$ : object
|
||||
$createAndSaveGlyphImpl$
|
||||
$NamedParameterPair$
|
||||
$Exec$
|
||||
$GlyphSaveSink$
|
||||
Metrics : Object.assign {.} Metrics
|
||||
para
|
||||
recursive
|
||||
|
@ -100,7 +62,6 @@ export : define [buildGlyphs para recursive] : begin
|
|||
MarkSet
|
||||
AS_BASE
|
||||
ALSO_METRICS
|
||||
glyph-is-needed
|
||||
buildGlyphs
|
||||
fontMetrics
|
||||
GlyphProc
|
||||
|
@ -148,8 +109,4 @@ export : define [buildGlyphs para recursive] : begin
|
|||
|
||||
$Exec$.executePendingBlocks
|
||||
|
||||
Gr.linkSuffixPairGr glyphStore 'NWID' 'WWID' Gr.Nwid Gr.Wwid
|
||||
Gr.linkSuffixPairGr glyphStore 'lnum' 'onum' Gr.Lnum Gr.Onum
|
||||
Gr.linkSuffixGr glyphStore 'aplForm' Gr.AplForm
|
||||
|
||||
return : object glyphStore fontMetrics
|
||||
|
|
|
@ -51,7 +51,7 @@ glyph-block Letter-Latin-Lower-G : begin
|
|||
set-base-anchor 'overlay' Middle [mix (Descender + O) groundy 0.5]
|
||||
set-base-anchor 'strike' Middle (XH / 2)
|
||||
|
||||
create-forked-glyph 'gBar.doubleStorey' : OverlayW obwDoubleStorey
|
||||
derive-composites "gBar.doubleStorey" null "g.doubleStorey" [OverlayW obwDoubleStorey]
|
||||
|
||||
create-glyph 'g.openDoubleStorey' : glyph-proc
|
||||
include : MarkSet.p
|
||||
|
@ -81,7 +81,7 @@ glyph-block Letter-Latin-Lower-G : begin
|
|||
set-base-anchor 'overlay' Middle [mix (Descender + O) groundy 0.5]
|
||||
set-base-anchor 'strike' Middle (XH / 2)
|
||||
|
||||
create-forked-glyph 'gBar.openDoubleStorey' : OverlayW obwDoubleStorey
|
||||
derive-composites "gBar.openDoubleStorey" null "g.openDoubleStorey" [OverlayW obwDoubleStorey]
|
||||
|
||||
define SingleStorey : namespace
|
||||
export : define [RoundHookT sink df yTop offset sw] : sink
|
||||
|
|
|
@ -149,40 +149,35 @@ define-macro eject-contour : syntax-rules
|
|||
###### Canvas-based mechanism
|
||||
define-macro new-glyph : syntax-rules
|
||||
`[new-glyph @body] : begin
|
||||
dirty `[$createAndSaveGlyphImpl$ null null @[formOf body]]
|
||||
dirty `[$GlyphSaveSink$.save null null @[formOf body]]
|
||||
|
||||
define-macro create-glyph : syntax-rules
|
||||
`[create-glyph @body] : begin
|
||||
if [not externEnv.$nWFGlyphs$] : set externEnv.$nWFGlyphs$ 0
|
||||
inc externEnv.$nWFGlyphs$
|
||||
local f0 : '.' + [[env.macros.get 'input-path']].1 + '.'
|
||||
local tcn {".quote" (".WF" + f0 + externEnv.$nWFGlyphs$)}
|
||||
dirty `[$createAndSaveGlyphImpl$ @tcn null @[formOf body]]
|
||||
dirty `[$GlyphSaveSink$.save null null @[formOf body]]
|
||||
`[create-glyph @name @body] : begin
|
||||
dirty `[$createAndSaveGlyphImpl$ @[formOf name] null @[formOf body]]
|
||||
dirty `[$GlyphSaveSink$.save @[formOf name] null @[formOf body]]
|
||||
`[create-glyph @name @code @body] : begin
|
||||
dirty `[$createAndSaveGlyphImpl$ @[formOf name] @[formOf code] @[formOf body]]
|
||||
dirty `[$GlyphSaveSink$.save @[formOf name] @[formOf code] @[formOf body]]
|
||||
|
||||
define-macro create-aliased-glyph : syntax-rules
|
||||
`[create-aliased-glyph @name] : begin
|
||||
dirty `[create-aliased-glyph @[formOf name] null]
|
||||
`[create-aliased-glyph @name @code] : begin
|
||||
dirty `[$createAndSaveGlyphImpl$ @[formOf name] @[formOf code]
|
||||
dirty `[$GlyphSaveSink$.save @[formOf name] @[formOf code]
|
||||
[new $Capture$.ForkGlyphProc currentGlyph null] ]
|
||||
|
||||
define-macro create-forked-glyph : syntax-rules
|
||||
`[create-forked-glyph @body] : begin
|
||||
if [not externEnv.$nWFGlyphs$] : set externEnv.$nWFGlyphs$ 0
|
||||
inc externEnv.$nWFGlyphs$
|
||||
local f0 : '.' + [[env.macros.get 'input-path']].1 + '.'
|
||||
local tcn {".quote" (".WF" + f0 + externEnv.$nWFGlyphs$)}
|
||||
dirty `[create-forked-glyph @tcn null @[formOf body]]
|
||||
dirty `[create-forked-glyph null null @[formOf body]]
|
||||
`[create-forked-glyph @name @body] : begin
|
||||
dirty `[create-forked-glyph @[formOf name] null @[formOf body]]
|
||||
`[create-forked-glyph @name @code @body] : begin
|
||||
dirty `[$createAndSaveGlyphImpl$ @[formOf name] @[formOf code]
|
||||
dirty `[$GlyphSaveSink$.save @[formOf name] @[formOf code]
|
||||
[new $Capture$.ForkGlyphProc currentGlyph @[formOf body]] ]
|
||||
|
||||
define-macro glyph-is-needed : syntax-rules
|
||||
`[glyph-is-needed @name] : dirty `[$GlyphSaveSink$.glyphIsNeeded @[formOf name]]
|
||||
|
||||
###### Glyph modules and Glyph blocks
|
||||
|
||||
define-macro glyph-module : syntax-rules
|
||||
|
@ -265,13 +260,13 @@ define-macro glyph-block : syntax-rules
|
|||
([typeof form] === "string") : set variableSet.(form) true
|
||||
|
||||
traceBody body
|
||||
traceBody `[$NamedParameterPair$ $createAndSaveGlyphImpl$ $Exec$]
|
||||
traceBody `[$NamedParameterPair$ $GlyphSaveSink$ $Exec$]
|
||||
|
||||
set externEnv.$glyphBlockVariableUsage$ variableSet
|
||||
|
||||
define captureImports `[$createAndSaveGlyphImpl$ $NamedParameterPair$ $Exec$ Metrics para
|
||||
recursive glyphStore glyph-is-needed SpiroFns BooleFns MarkSet AS_BASE ALSO_METRICS
|
||||
buildGlyphs DivFrame fontMetrics]
|
||||
define captureImports `[$GlyphSaveSink$ $NamedParameterPair$ $Exec$ Metrics para recursive
|
||||
glyphStore SpiroFns BooleFns MarkSet AS_BASE ALSO_METRICS buildGlyphs DivFrame
|
||||
fontMetrics]
|
||||
|
||||
define metricImports `[DesignParameters UPM HalfUPM Width SB CAP XH Ascender Descender
|
||||
Contrast SymbolMid ParenTop ParenBot OperTop OperBot TackTop TackBot PlusTop PlusBot
|
||||
|
|
|
@ -108,6 +108,11 @@ define [buildGDEF para glyphStore markGlyphs] : begin
|
|||
return GDEF
|
||||
|
||||
export : define [buildOtl para glyphStore] : begin
|
||||
# Link glyph pairs by suffix
|
||||
Gr.linkSuffixPairGr glyphStore 'NWID' 'WWID' Gr.Nwid Gr.Wwid
|
||||
Gr.linkSuffixPairGr glyphStore 'lnum' 'onum' Gr.Lnum Gr.Onum
|
||||
Gr.linkSuffixGr glyphStore 'aplForm' Gr.AplForm
|
||||
|
||||
local markGlyphs { .all [new Set] .markAttachClassDef [new Map] .markGlyphSets {} }
|
||||
local GPOS : buildGPOS para glyphStore markGlyphs
|
||||
local GDEF : buildGDEF para glyphStore markGlyphs
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { Glyph } from "./glyph.mjs";
|
||||
|
||||
export class GlyphBuildExecutor {
|
||||
constructor(recursiveBuildFilter) {
|
||||
this.recursiveBuildFilter = recursiveBuildFilter;
|
||||
|
@ -174,3 +176,60 @@ export class GlyphBlock {
|
|||
return this.exports;
|
||||
}
|
||||
}
|
||||
|
||||
/// The class used to handle glyph saving.
|
||||
export class GlyphSaveSink {
|
||||
constructor(exec, metrics, store) {
|
||||
this.exec = exec;
|
||||
this.metrics = metrics;
|
||||
this.glyphStore = store;
|
||||
}
|
||||
|
||||
glyphIsNeeded(name) {
|
||||
return (
|
||||
!this.exec.recursiveBuildFilter || this.exec.recursiveBuildFilter.glyphIsNeeded(name)
|
||||
);
|
||||
}
|
||||
|
||||
save($1, $2, contents) {
|
||||
// Figure out the glyph name and unicode to save
|
||||
let saveGlyphName = null;
|
||||
let unicode = null;
|
||||
if ($1 && typeof $1 === "string") {
|
||||
saveGlyphName = $1;
|
||||
unicode = $2 || 0;
|
||||
} else if ($1 && typeof $1 === "number") {
|
||||
saveGlyphName = "uni" + $1.toString(16).padStart(4, "0").toUpperCase();
|
||||
unicode = $1;
|
||||
}
|
||||
|
||||
// If we are in a recursive build run, and the glyph is not needed, skip it
|
||||
if (saveGlyphName && !this.glyphIsNeeded(saveGlyphName)) return;
|
||||
|
||||
// Create the glyph object & include the contents
|
||||
const glyphObject = new Glyph(saveGlyphName);
|
||||
glyphObject.setWidth(this.metrics.Width);
|
||||
glyphObject.gizmo = this.metrics.GlobalTransform;
|
||||
glyphObject._m_dependencyManager = this.exec.dependencyManager;
|
||||
|
||||
glyphObject.include(contents, true, true);
|
||||
|
||||
// Set the glyph-to-block dependency
|
||||
this.exec.setGlyphToBlockDependency(glyphObject);
|
||||
|
||||
// Save the glyph if requested
|
||||
if (saveGlyphName) {
|
||||
if (this.glyphStore.queryByName(saveGlyphName)) {
|
||||
throw new Error(`Duplicate glyph: ${saveGlyphName}`);
|
||||
}
|
||||
|
||||
this.glyphStore.addGlyph(saveGlyphName, glyphObject);
|
||||
if (unicode) {
|
||||
let u = typeof unicode === "string" ? unicode.codePointAt(0) : unicode;
|
||||
this.glyphStore.encodeGlyph(u, glyphObject);
|
||||
}
|
||||
}
|
||||
|
||||
return glyphObject;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue