diff --git a/changes/17.2.0.md b/changes/17.2.0.md new file mode 100644 index 000000000..9392c84be --- /dev/null +++ b/changes/17.2.0.md @@ -0,0 +1 @@ +* Add support of Unicode Variation Sequence for `0` that adds a slash (#1534). diff --git a/font-src/gen/finalize/gc.mjs b/font-src/gen/finalize/gc.mjs index 18fe0622b..858c08840 100644 --- a/font-src/gen/finalize/gc.mjs +++ b/font-src/gen/finalize/gc.mjs @@ -1,4 +1,11 @@ -import { Radical } from "../../support/gr.mjs"; +import { Radical, VS01 } from "../../support/gr.mjs"; + +export function gcFont(glyphStore, excludedChars, otl, cfg) { + markSweepOtlLookups(otl.GSUB); + markSweepOtlLookups(otl.GPOS); + const sink = markGlyphs(glyphStore, excludedChars, otl, cfg); + return sweepGlyphs(glyphStore, sink); +} function markSweepOtlLookups(table) { if (!table || !table.features || !table.lookups) return; @@ -56,6 +63,7 @@ function sweepFeatures(table, accessibleLookupsIds) { } table.features = features1; } + function markGlyphs(glyphStore, excludedChars, otl, cfg) { const sink = markGlyphsInitial(glyphStore, excludedChars); while (markGlyphsStep(glyphStore, sink, otl, cfg)); @@ -78,6 +86,9 @@ function markGlyphsInitial(glyphStore, excludedChars) { } function markGlyphsStep(glyphStore, sink, otl, cfg) { const glyphCount = sink.size; + for (const g of glyphStore.glyphs()) { + markLinkedGlyph(sink, g, VS01); + } if (otl.GSUB) { for (const l in otl.GSUB.lookups) { const lookup = otl.GSUB.lookups[l]; @@ -88,6 +99,10 @@ function markGlyphsStep(glyphStore, sink, otl, cfg) { const glyphCount1 = sink.size; return glyphCount1 > glyphCount; } +function markLinkedGlyph(sink, g, gr) { + const linked = gr.get(g); + if (linked) sink.add(linked); +} function markGlyphsLookupImpl(sink, lookup, cfg) { switch (lookup.type) { case "gsub_single": @@ -136,12 +151,7 @@ function markGlyphsGsubReverse(sink, lookup, cfg) { } } } -function sweep(glyphStore, gnSet) { + +function sweepGlyphs(glyphStore, gnSet) { return glyphStore.filterByName(gnSet); } -export function gcFont(glyphStore, excludedChars, otl, cfg) { - markSweepOtlLookups(otl.GSUB); - markSweepOtlLookups(otl.GPOS); - const sink = markGlyphs(glyphStore, excludedChars, otl, cfg); - return sweep(glyphStore, sink); -} diff --git a/font-src/gen/otd-conv/glyphs.mjs b/font-src/gen/otd-conv/glyphs.mjs index ceeb994fb..919bdd7b0 100644 --- a/font-src/gen/otd-conv/glyphs.mjs +++ b/font-src/gen/otd-conv/glyphs.mjs @@ -122,10 +122,13 @@ class MappedGlyphStore { g.geometry = cs; } } + export function convertGlyphs(gsOrig) { const sortedEntries = Array.from(gsOrig.namedEntries(Gr.Nwid, Gr.Wwid)).sort(byRank); const gs = new MappedGlyphStore(); const cmap = new Ot.Cmap.Table(); + + // initialize for (const [name, gSrc] of sortedEntries) { gs.declare(name, gSrc); const us = gsOrig.queryUnicodeOf(gSrc); @@ -137,7 +140,36 @@ export function convertGlyphs(gsOrig) { } } } + + // fill geometry for (const [name, gSrc] of sortedEntries) gs.fill(name, gSrc); + + // fill VS + addVsLinks(gsOrig, gs, cmap, Gr.VS01, 0xfe00); + + // fill glyph names gs.fillOtGlyphNames(); + return { glyphs: gs, cmap }; } + +function addVsLinks(gsOrig, gs, cmap, gr, vs) { + for (const gSrc of gsOrig.glyphs()) { + const us = gsOrig.queryUnicodeOf(gSrc); + if (!us) continue; + + const gnSrcLinked = gr.get(gSrc); + if (!gnSrcLinked) continue; + + const gSrcLinked = gsOrig.queryByName(gnSrcLinked); + if (!gSrcLinked) continue; + + const gDstLinked = gs.queryBySourceGlyph(gSrcLinked); + if (!gDstLinked) continue; + + for (const u of us) { + if (!(isFinite(u - 0) && u)) continue; + cmap.vs.set(u, vs, gDstLinked); + } + } +} diff --git a/font-src/glyphs/number/0.ptl b/font-src/glyphs/number/0.ptl index 86d34ea76..5b95e5f77 100644 --- a/font-src/glyphs/number/0.ptl +++ b/font-src/glyphs/number/0.ptl @@ -1,7 +1,7 @@ $$include '../../meta/macros.ptl' import [mix linreg clamp fallback] from"../../support/utils.mjs" -import [AnyCv getGrMesh] from"../../support/gr.mjs" +import [AnyCv getGrMesh VS01] from"../../support/gr.mjs" glyph-module @@ -120,6 +120,9 @@ glyph-block Digits-Zero : begin select-variant 'zero.lnum/forceUnslashed' (follow -- 'zero/forceUnslashed') (shapeFrom -- 'zero.lnum') select-variant 'zero.onum/forceUnslashed' (follow -- 'zero/forceUnslashed') (shapeFrom -- 'zero.onum') + if [query-glyph 'zero.lnum'] : VS01.set [query-glyph 'zero.lnum'] 'zero.lnum/forceSlashed' + if [query-glyph 'zero.onum'] : VS01.set [query-glyph 'zero.onum'] 'zero.onum/forceSlashed' + glyph-block-import Letter-Blackboard : BBS BBD create-glyph 'mathbb/zero' 0x1D7D8 : glyph-proc include : MarkSet.capital diff --git a/font-src/support/gr.mjs b/font-src/support/gr.mjs index f31c1e2ff..84b5a91c5 100644 --- a/font-src/support/gr.mjs +++ b/font-src/support/gr.mjs @@ -19,6 +19,7 @@ export const Dotless = { export const LowerYDotAtBelow = LinkedGlyphProp("LowerYDotAtBelow"); export const DependentSelector = LinkedGlyphProp("DependentSelector"); export const MathSansSerif = LinkedGlyphProp("MathSansSerif"); +export const VS01 = LinkedGlyphProp("VS01"); function LinkedGlyphProp(key) { return { get(glyph) {