Refactor recursive build mechanism

This commit is contained in:
be5invis 2022-12-19 07:46:41 -08:00
parent 5b359dbbfe
commit 2d938dd309
11 changed files with 153 additions and 105 deletions

View file

@ -68,8 +68,7 @@ glyph-block AutoBuild-Accents : begin
local foundDecompositions {.}
# When recursively building, `recursiveCodes` contain an array of "needed" Unicode list
local goalCodes : recursiveCodes || [range 0x0000 0xFFFF]
local goalCodes : range 0x0000 0xFFFF
foreach code goalCodes : if [not : glyphStore.queryByUnicode code] : do
local parts { }
local allFound true

View file

@ -17,3 +17,11 @@ glyph-block Autobuild-DCaron : begin
local f : Widen {base} 0.95 1
include : f.queryByName base
include : MarkSet.b
WithDotVariants 'LDotDot' null : function [DrawAt kdr overshoot] : glyph-proc
set-width 0
include : DrawAt 0 0 (DotRadius * kdr - overshoot)
set-mark-anchor 'cvDecompose' 0 0
derive-composites 'LDot' 0x13F 'L' 'LDotDot'
derive-composites 'lDot' 0x140 'lDotBase' 'LDotDot'

View file

@ -615,7 +615,6 @@ glyph-block Autobuild-Transformed-Mathematical : begin
define ObliqueBlackboardBolds : Array.from '𝔻𝕕𝕖𝕚𝕛'
define [CreateMathDerivatives groupName tfm gr base letters overrides] : begin
if recursive : return nothing
local jobs {}
local overrideMap : new Map (overrides || {})
foreach j [range 0 letters.length] : begin
@ -628,7 +627,6 @@ glyph-block Autobuild-Transformed-Mathematical : begin
createMathDerivedSeriesImpl groupName tfm jobs
define [CreateMathAliasableImpl groupName altGroupName tfm gr base letters overrides] : begin
if recursive : return nothing
local overrideMap : new Map (overrides || {})
foreach j [range 0 letters.length] : begin
local letter letters.(j)

View file

@ -46,9 +46,6 @@ glyph-block Common-Derivatives : begin
alias name unicode (name + '.slanted')
alias name unicode (name + '.upright')
glyph-block-export glyph-is-needed
define [glyph-is-needed name] : [not pickHash] || pickHash.(name)
glyph-block-export query-glyph
define [query-glyph id] : return : glyphStore.queryByName id
@ -212,34 +209,12 @@ glyph-block Common-Derivatives : begin
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 glyphs {}
foreach [glyphid : items-of gs] : begin
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
if g : glyphs.push g
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
local gs : buildGlyphs ps [$execState$.dependencyManager.traverseDependencies glyphs]
return gs.glyphStore
define [MiniatureParaT] : params [pp crowd scale [sbscale (Width / UPM)] [mono false] [mono2 false] [forceUpright false]] : begin

View file

@ -1,6 +1,6 @@
import [Glyph] from"../support/glyph/index.mjs"
import [GlyphStore] from"../support/glyph-store.mjs"
import [GlyphBlock] from"../support/glyph-block.mjs"
import [GlyphBlock GlyphBlockExecState] from"../support/glyph-block.mjs"
import as Gr from"../support/gr.mjs"
import as SpiroKit from"../kits/spiro-kit.mjs"
import as BooleKit from"../kits/boole-kit.mjs"
@ -18,58 +18,50 @@ define [$NamedParameterPair$ l r] : begin
set this.right r
return this
define [$donothing$] nothing
define [$DoNothing$] nothing
export : define [buildGlyphs para recursive recursiveCodes] : begin
export : define [buildGlyphs para recursive] : begin
local glyphStore : new GlyphStore
define metrics : calculateMetrics para
define [object GlobalTransform UPM Middle CAP XH SB RightSB Contrast Stroke Width TanSlope OverlayPos Descender SymbolMid ParenTop ParenBot OperTop OperBot PlusTop PlusBot TackTop TackBot AdviceStroke] metrics
define Metrics : calculateMetrics para
define fontMetrics { .head {.} .hhea {.} .os2 {.} .post {.} }
setFontMetrics para metrics fontMetrics
setFontMetrics para Metrics fontMetrics
# Anchor parameters
define {AS_BASE ALSO_METRICS} {'AS-BASE' 'ALSO-METRICS'}
define DivFrame : GenDivFrame metrics
define DivFrame : GenDivFrame Metrics
define MarkSet [DivFrame 1 2].markSet
local nPending 0
local pickHash : if recursive
then : let [h {.}] : begin
foreach j [items-of recursive] : set h.(j) j
set nPending recursive.length
* h
else nothing
define [glyph-is-needed name] : [not recursive] || [recursive.glyphIsNeeded name]
define [$createAndSaveGlyphImpl$ _1 _2 actions] : begin
local saveGlyphName null
local ensuredGlyphName null
local unicode null
piecewise
([typeof _1] === 'number' && _1) : begin
set saveGlyphName : 'uni' + [_1.toString 16 :.padStart 4 '0' :.toUpperCase]
set ensuredGlyphName saveGlyphName
set unicode _1
([typeof _1] === 'string' && _1) : begin
set saveGlyphName _1
set ensuredGlyphName saveGlyphName
set unicode _2
true : begin
set saveGlyphName null
set ensuredGlyphName "Temporary Glyph"
set unicode null
if (saveGlyphName && pickHash && [not pickHash.(saveGlyphName)]) : return nothing
if para.verbose : console.log ensuredGlyphName
if (saveGlyphName && [not : glyph-is-needed saveGlyphName]) : return nothing
if para.verbose : console.log saveGlyphName
local glyphObject [new Glyph saveGlyphName]
glyphObject.setWidth Width
glyphObject.gizmo = GlobalTransform
glyphObject.setWidth Metrics.Width
glyphObject.gizmo = Metrics.GlobalTransform
glyphObject._m_dependencyManager = $execState$.dependencyManager
glyphObject.include actions true true
warnAboutBrokenGlyph glyphObject ensuredGlyphName saveGlyphName
$execState$.setGlyphToBlockDependency glyphObject
if saveGlyphName : begin
if (saveGlyphName.0 != '.' && [glyphStore.queryByName saveGlyphName])
@ -77,34 +69,31 @@ export : define [buildGlyphs para recursive recursiveCodes] : begin
glyphStore.addGlyph saveGlyphName glyphObject
if unicode : $assignUnicodeImpl$ glyphObject unicode
dec nPending
return glyphObject
define [warnAboutBrokenGlyph g ensuredGlyphName saveGlyphName] : begin
local complexity : g.geometry.measureComplexity
if ([not recursive] && complexity > 4096) : begin
console.log 'Possible broken shape found in' ensuredGlyphName 'Complexity' complexity
console.log 'Family' para.naming.family para.naming.weight para.naming.width para.naming.slope
if saveGlyphName : throw : new Error "Overcomplicated \(saveGlyphName)"
define [$assignUnicodeImpl$ g unicode] : begin
local u unicode
if ([typeof unicode] === "string") : begin
set u [unicode.codePointAt 0]
glyphStore.encodeGlyph u g
local $pendingGlyphBlocks$ {}
local $execState$ : new GlyphBlockExecState
define [$defineGlyphBlockImpl$ $Capture$ blockName body] : begin
local glyphBlock : new GlyphBlock $Capture$ blockName body
local glyphBlock : new GlyphBlock $Capture$ $execState$ blockName body
if [not $Capture$.(blockName)] : set $Capture$.(blockName) glyphBlock
if [not $Capture$.$pendingGlyphBlocks$] : set $Capture$.$pendingGlyphBlocks$ {}
$Capture$.$pendingGlyphBlocks$.push glyphBlock
$pendingGlyphBlocks$.push glyphBlock
### Spiro constructions
# Basic knots
define SpiroFns : SpiroKit.SetupBuilders : object GlobalTransform Contrast Stroke [Superness DesignParameters.superness]
define BooleFns : BooleKit.SetupBuilders : object GlobalTransform Glyph
define SpiroFns : SpiroKit.SetupBuilders : object
globalTransform Metrics.GlobalTransform
Contrast Metrics.Contrast
Stroke Metrics.Stroke
Superness DesignParameters.superness
define BooleFns : BooleKit.SetupBuilders : object
globalTransform Metrics.GlobalTransform
Glyph Glyph
# Meta
define [tagged tag component] : function [ca cw] : begin
@ -114,8 +103,27 @@ export : define [buildGlyphs para recursive recursiveCodes] : begin
set this.ctxTag t
return ret
# IDKY, but wrapping "metrics" prevents Node.js on Arch modifying it.
define $$Capture$$ : object [metrics : Object.create metrics] $NamedParameterPair$ $donothing$ para recursive recursiveCodes glyphStore $createAndSaveGlyphImpl$ SpiroFns BooleFns MarkSet AS_BASE ALSO_METRICS pickHash buildGlyphs tagged DivFrame fontMetrics $assignUnicodeImpl$ $defineGlyphBlockImpl$
define $$Capture$$ : object
$createAndSaveGlyphImpl$
$NamedParameterPair$
$assignUnicodeImpl$
$defineGlyphBlockImpl$
$execState$
$DoNothing$
Metrics : Object.assign {.} Metrics
para
recursive
glyphStore
SpiroFns
BooleFns
DivFrame
MarkSet
AS_BASE
ALSO_METRICS
glyph-is-needed
buildGlyphs
tagged
fontMetrics
### HERE WE GO
run-glyph-module "./common/shapes.mjs"
@ -145,14 +153,15 @@ export : define [buildGlyphs para recursive recursiveCodes] : begin
run-glyph-module "./symbol/pictograph.mjs"
run-glyph-module "./symbol/ligation.mjs"
# Autobuilds
# Auto-builds
if [not recursive] : begin
run-glyph-module "./auto-build/special-accented-letters.mjs"
run-glyph-module "./auto-build/mark-doppelganger.mjs"
run-glyph-module "./auto-build/accents.mjs"
run-glyph-module "./auto-build/composite.mjs"
run-glyph-module "./auto-build/transformed.mjs"
foreach [gb : items-of $$Capture$$.$pendingGlyphBlocks$] : gb.resolve
foreach [gb : items-of $pendingGlyphBlocks$] : gb.resolve
Gr.linkSuffixPairGr glyphStore 'NWID' 'WWID' Gr.Nwid Gr.Wwid
Gr.linkSuffixPairGr glyphStore 'lnum' 'onum' Gr.Lnum Gr.Onum

View file

@ -11,6 +11,5 @@ export : define [apply] : begin
run-glyph-module "./overlay.mjs"
run-glyph-module "./tie.mjs"
run-glyph-module "./composite.mjs"
run-glyph-module "./doppelganger.mjs"
run-glyph-module "./adjust.mjs"

View file

@ -244,19 +244,6 @@ glyph-block Symbol-Cyrl-Thousands : begin
include : ExtLineCenter (-0.1) fine [mix SB RightSB 0.1] [mix Descender XH 0.8] [mix SB RightSB 1.1] [mix Descender XH 0.5]
include : ExtLineCenter (-0.1) fine [mix SB RightSB (-0.1)] [mix Descender XH 0.5] [mix SB RightSB 0.9] [mix Descender XH 0.2]
glyph-block Symbol-Letter-Punctuation-Composite : begin
glyph-block-import CommonShapes
glyph-block-import Common-Derivatives
WithDotVariants 'LDotDot' null : function [DrawAt kdr overshoot] : glyph-proc
set-width 0
include : DrawAt 0 0 (DotRadius * kdr - overshoot)
set-mark-anchor 'cvDecompose' 0 0
derive-composites 'LDot' 0x13F 'L' 'LDotDot'
derive-composites 'lDot' 0x140 'lDotBase' 'LDotDot'
glyph-block Symbol-Letter-Phonetic : begin
create-glyph 'modifierArchBreve' 0xAB5B : glyph-proc
include : MarkSet.e

View file

@ -140,8 +140,8 @@ define-macro glyph-block-import : syntax-rules
define allExports : object
Common-Derivatives `[select-variant orthographic-italic orthographic-slanted
refer-glyph query-glyph alias turned HDual HCombine VDual VCombine derive-glyphs
derive-composites link-reduced-variant alias-reduced-variant glyph-is-needed
HalfAdvance TurnMarks derive-multi-part-glyphs DeriveMeshT]
derive-composites link-reduced-variant alias-reduced-variant HalfAdvance TurnMarks
derive-multi-part-glyphs DeriveMeshT]
CommonShapes `[no-shape Rect SquareAt Ring RingAt DotAt RingStroke RingStrokeAt
DotStrokeAt CircleRing CircleRingAt CircleDotAt RoundStrokeTerminalAt OShapeT OShape
@ -178,8 +178,8 @@ define-macro glyph-block-export : syntax-rules
define-macro for-width-kinds : syntax-rules
`[for-width-kinds @_desired @::_body] : dirty `[ do \\
define WidthKinds {
{ 0 '.NWID' $Capture$.metrics.Width 1 }
{ 1 '.WWID' $Capture$.metrics.WideWidth0 2 }
{ 0 '.NWID' $Capture$.Metrics.Width 1 }
{ 1 '.WWID' $Capture$.Metrics.WideWidth0 2 }
}
foreach {FMosaicWide MosaicNameSuffix MosaicWidth MosaicWidthScalar} [items-of WidthKinds] : do
define MosaicDesiredWidth @[formOf _desired]
@ -209,14 +209,14 @@ define-macro glyph-block : syntax-rules
([typeof form] === "string") : set variableSet.(form) true
traceBody body
traceBody `[$NamedParameterPair$ $donothing$ $createAndSaveGlyphImpl$ $assignUnicodeImpl$]
traceBody `[$NamedParameterPair$ $DoNothing$ $createAndSaveGlyphImpl$ $assignUnicodeImpl$]
set externEnv.$glyphBlockVariableUsage$ variableSet
define captureImports `[metrics $NamedParameterPair$ $donothing$ para recursive
recursiveCodes glyphStore $createAndSaveGlyphImpl$
SpiroFns BooleFns MarkSet AS_BASE ALSO_METRICS pickHash
buildGlyphs tagged DivFrame fontMetrics $assignUnicodeImpl$]
define captureImports `[$createAndSaveGlyphImpl$ $NamedParameterPair$
$assignUnicodeImpl$ $DoNothing$ $execState$
Metrics para recursive glyphStore glyph-is-needed SpiroFns BooleFns MarkSet AS_BASE
ALSO_METRICS buildGlyphs tagged DivFrame fontMetrics]
define metricImports `[DesignParameters UPM HalfUPM Width SB CAP XH Ascender Descender
Contrast SymbolMid ParenTop ParenBot OperTop OperBot TackTop TackBot PlusTop PlusBot
@ -242,7 +242,7 @@ define-macro glyph-block : syntax-rules
$Capture_Ext$.$defineGlyphBlockImpl$ $Capture_Ext$ @blockName
function [$Capture$ $ExportCapture$] : begin
define [object @::[captureImports.filter : lambda [x] variableSet.(x)]] $Capture$
define [object @::[metricImports.filter : lambda [x] variableSet.(x)]] $Capture$.metrics
define [object @::[metricImports.filter : lambda [x] variableSet.(x)]] $Capture$.Metrics
define [object @::[spiroFnImports.filter : lambda [x] variableSet.(x)]] $Capture$.SpiroFns
define [object @::[booleFnImports.filter : lambda [x] variableSet.(x)]] $Capture$.BooleFns

View file

@ -1,6 +1,69 @@
export class RecursiveBuildFilter {
constructor(glyphIdFilter) {
this.glyphIdFilter = glyphIdFilter;
}
glyphIsNeeded(id) {
return this.glyphIdFilter.has(id);
}
}
export class DependencyManager {
constructor() {
this.glyphToGlyph = new WeakMap();
this.glyphToBlock = new WeakMap();
}
addDependency(dependent, dependency) {
let s = this.glyphToGlyph.get(dependent);
if (!s) {
s = new Set();
this.glyphToGlyph.set(dependent, s);
}
s.add(dependency);
}
traverseDependencies(glyphs) {
let state = new Map();
const PENDING = 1,
CHECKED = 2;
for (const glyph of glyphs) state.set(glyph, PENDING);
for (;;) {
let found = false;
for (const [glyph, s] of state) {
if (s !== PENDING) continue;
const deps = this.glyphToGlyph.get(glyph);
if (deps) {
for (const g of deps) state.set(g, PENDING);
found = true;
}
state.set(glyph, CHECKED);
}
if (!found) break;
}
let glyphIdFilter = new Set();
for (const g of state.keys()) {
if (g.identifier) glyphIdFilter.add(g.identifier);
}
return new RecursiveBuildFilter(glyphIdFilter);
}
}
export class GlyphBlockExecState {
constructor() {
this.currentBlockName = null;
this.dependencyManager = new DependencyManager();
}
setGlyphToBlockDependency(glyph) {
if (this.currentBlockName) {
this.dependencyManager.glyphToBlock.set(glyph, this.currentBlockName);
}
}
}
export class GlyphBlock {
constructor(capture, blockName, body) {
constructor(capture, execState, blockName, body) {
this.capture = capture;
this.execState = execState;
this.blockName = blockName;
this.body = body;
this.resolved = false;
@ -8,6 +71,10 @@ export class GlyphBlock {
}
resolve() {
if (this.resolved) return this.exports;
const prevBlockName = this.execState.currentBlockName;
this.execState.currentBlockName = this.blockName;
this.resolved = true;
const pendingApplications = [];
const ExportCapture = fnObj => {
@ -19,6 +86,8 @@ export class GlyphBlock {
};
this.body(this.capture, ExportCapture);
for (const f of pendingApplications) f();
this.execState.currentBlockName = prevBlockName;
return this.exports;
}
}

View file

@ -19,9 +19,13 @@ export class Glyph {
this.markAnchors = {};
this.baseAnchors = {};
// Tracking
this.dependencies = [];
this._m_dependencyManager = null;
this.ctxTag = null;
}
get identifier() {
return this._m_identifier;
}
get contours() {
throw new TypeError("Glyph::contours has been deprecated");
}
@ -48,8 +52,8 @@ export class Glyph {
}
// Dependency
dependsOn(glyph) {
if (glyph._m_identifier) this.dependencies.push(glyph._m_identifier);
if (glyph.dependencies) for (const dep of glyph.dependencies) this.dependencies.push(dep);
if (!this._m_dependencyManager) return;
this._m_dependencyManager.addDependency(this, glyph);
}
// Inclusion
include(component, copyAnchors, copyWidth) {