Move the glyph saving logic to MJS side (#2479)

This commit is contained in:
Belleve 2024-08-21 21:27:21 -10:00 committed by GitHub
parent 499b97e3a1
commit 5ee209c97f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 84 additions and 68 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}
}