Skip to content

Commit

Permalink
Optimize glyph quantity; Fix glyph visual for COMBINING DOUBLE CIRCUM…
Browse files Browse the repository at this point in the history
…FLEX ABOVE (`U+1DCD`). (#2252)
  • Loading branch information
be5invis authored Mar 22, 2024
1 parent 96456df commit 63ec70d
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 65 deletions.
1 change: 1 addition & 0 deletions changes/29.0.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
* Fix width of PUNCTUATION SPACE (`U+2008`) under Quasi-Proportional.
* Fix `percent`=`dots` glyphs for PER {MILLE|TEN THOUSAND} SIGN (`U+2030`..`U+2031`) under Quasi-Proportional when `NWID` is enabled.
* Remove untagged variant selector for Cyrillic Capital Ef (`Ф`).
* Fix glyph visual for COMBINING DOUBLE CIRCUMFLEX ABOVE (`U+1DCD`).
31 changes: 16 additions & 15 deletions packages/font-glyphs/src/letter/shared.ptl
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,24 @@ glyph-block Letter-Shared : begin
glyph-block-import Common-Derivatives
glyph-block-import Mark-Adjustment : TurnMarks LeaningAnchorMap

glyph-block-export CreateAccentedComposition
define [CreateAccentedComposition dst u srcGid accentGid]
derive-multi-part-glyphs dst u { srcGid accentGid } : function [gns gr] : glyph-proc
local { base mark } gns
local gMark : query-glyph mark
glyph-block-export CreateMultiAccentedComposition
define [CreateMultiAccentedComposition dst u gnSrc gnAccents]
derive-multi-part-glyphs dst u { gnSrc :: gnAccents } : function [gns gr] : glyph-proc
local { gnBase :: gnAccents } gns

include [refer-glyph base] AS_BASE ALSO_METRICS
currentGlyph.includeMarkWithLeaningSupport gMark LeaningAnchorMap
include [refer-glyph gnBase] AS_BASE ALSO_METRICS
foreach gnAccent [items-of gnAccents] : begin
local gAccent : query-glyph gnAccent
currentGlyph.includeMarkWithLeaningSupport gAccent LeaningAnchorMap

if (!gr && accentGid === 'dotAbove') : Dotless.set currentGlyph base
if (!gr) : begin
if (gnAccents.length === 1 && gnAccents.0 === 'dotAbove')
: then : Dotless.set currentGlyph gnBase
: else : CvDecompose.set currentGlyph { gnSrc :: gnAccents }

glyph-block-export CreateAccentedComposition
define [CreateAccentedComposition dst u srcGid accentGid]
CreateMultiAccentedComposition dst u srcGid { accentGid }

glyph-block-export CreateOgonekComposition
define [CreateOgonekComposition dst u srcGid]
Expand All @@ -44,13 +52,6 @@ glyph-block Letter-Shared : begin
include : ApparentTranslate commaOffset 0
include [refer-glyph base] AS_BASE ALSO_METRICS

glyph-block-export CreateMultiAccentedComposition
define [CreateMultiAccentedComposition dstGid unicode srcGid accentGids fDontDecompose]
derive-glyphs dstGid unicode srcGid : lambda [src gr] : glyph-proc
include [refer-glyph src] AS_BASE ALSO_METRICS
foreach accentGid [items-of accentGids] : include [refer-glyph accentGid]
if (!fDontDecompose && !gr) : CvDecompose.set currentGlyph { src :: accentGids }

glyph-block-export CreateDependentComposite
define [CreateDependentComposite gidDst unicode gidPart1 gidPart2Map] : begin
local sourceGidList { gidPart1 }
Expand Down
25 changes: 18 additions & 7 deletions packages/font-glyphs/src/marks/tie.ptl
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,21 @@ glyph-block Mark-Tie : begin
set-base-anchor 'aboveBraceR' (0 + 0.5 * markExtend) aboveTieMid

TieGlyph.set currentGlyph
include : CaretShape
xMiddle -- 0
width -- CaretCaronWidth
top -- aboveTieTop + markFine * 0.7
bottom -- aboveTieBottom + markStress - markFine
swEnd -- CaretCaronTerminalSw
swMid -- CaretCaronMidSw

local leftHalf : include : dispiro
flat tieLeft aboveTieBottom [widths.center CaretCaronTerminalSw]
curl 0 aboveTieTop [widths.center CaretCaronMidSw]
local rightHalf : include : dispiro
flat tieRight aboveTieBottom [widths.center CaretCaronTerminalSw]
curl 0 aboveTieTop [widths.center CaretCaronMidSw]

local a leftHalf.lhsKnots.1
local b rightHalf.rhsKnots.1
local c leftHalf.rhsKnots.1
local d rightHalf.lhsKnots.1

include : spiro-outline
corner a.x a.y
corner b.x b.y
corner [Math.max c.x d.x] d.y
corner [Math.min c.x d.x] c.y
31 changes: 22 additions & 9 deletions packages/font/src/finalize/gc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,14 @@ function rectifyGlyphAndMarkComponents(glyphStore, aliasMap, markedGlyphs, memo,
if (memo.has(g)) return;
memo.add(g);

let refs = g.geometry.toReferences();
if (refs) {
let parts = [];
analyzeRefs: {
let refs = g.geometry.toReferences();
if (!refs) break analyzeRefs;

let partGns = []; // The names of the referenced glyphs
let parts = []; // The parts of the new geometry
let hasMarked = false; // Whether any of the referenced glyphs is marked

for (let sr of refs) {
// Resolve alias
const alias = aliasMap.get(sr.glyph);
Expand All @@ -371,14 +376,14 @@ function rectifyGlyphAndMarkComponents(glyphStore, aliasMap, markedGlyphs, memo,
sr.y += alias.y;
}

// Resolve reference
const gn = glyphStore.queryNameOf(sr.glyph);
if (!gn) {
// Reference is invalid. The root glyph will be radicalized.
g.geometry = new Geometry.RadicalGeometry(g.geometry.unlinkReferences());
return;
break analyzeRefs;
} else {
// Reference is valid. Process the referenced glyph.
if (!markedGlyphs.has(gn)) markedGlyphs.set(gn, d + 0x10000);
if (markedGlyphs.has(gn)) hasMarked = true;
rectifyGlyphAndMarkComponents(
glyphStore,
aliasMap,
Expand All @@ -388,10 +393,18 @@ function rectifyGlyphAndMarkComponents(glyphStore, aliasMap, markedGlyphs, memo,
d + 0x10000,
);
parts.push(new Geometry.ReferenceGeometry(sr.glyph, sr.x, sr.y));
partGns.push(gn);
}
}
g.geometry = new Geometry.CombineGeometry(parts);
} else {
g.geometry = new Geometry.RadicalGeometry(g.geometry.unlinkReferences());

// If any of the referenced glyphs is marked, mark all the remaining references.
if (hasMarked) {
for (const gn of partGns) if (!markedGlyphs.has(gn)) markedGlyphs.set(gn, d + 0x10000);
g.geometry = new Geometry.CombineGeometry(parts);
return;
}
}

// Make the glyph radical if it has no marked references.
g.geometry = g.geometry.unlinkReferences();
}
34 changes: 1 addition & 33 deletions packages/font/src/finalize/glyphs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,12 @@ export function finalizeGlyphs(cache, para, glyphStore) {
///////////////////////////////////////////////////////////////////////////////////////////////////

function regulateGlyphStore(cache, skew, glyphStore) {
const compositeMemo = new Map();
for (const g of glyphStore.glyphs()) {
if (!(g.geometry.measureComplexity() & Geom.CPLX_NON_EMPTY)) continue;
if (!regulateCompositeGlyph(glyphStore, compositeMemo, g)) {
g.geometry = g.geometry.unlinkReferences();
}
}
for (const g of glyphStore.glyphs()) {
if (!compositeMemo.get(g)) flattenSimpleGlyph(cache, skew, g);
if (!g.geometry.toReferences()) flattenSimpleGlyph(cache, skew, g);
}
}

///////////////////////////////////////////////////////////////////////////////////////////////////

function regulateCompositeGlyph(glyphStore, memo, g) {
if (memo.has(g)) return memo.get(g);

let refs = g.geometry.toReferences();
if (!refs) return memoSet(memo, g, false);

for (const sr of refs) {
const gn = glyphStore.queryNameOf(sr.glyph);
if (!gn) return memoSet(memo, g, false);
}

let refGeometries = [];
for (const sr of refs) refGeometries.push(new Geom.ReferenceGeometry(sr.glyph, sr.x, sr.y));
g.geometry = new Geom.CombineGeometry(refGeometries);
return memoSet(memo, g, true);
}

function memoSet(memo, g, v) {
memo.set(g, v);
return v;
}

///////////////////////////////////////////////////////////////////////////////////////////////////

function flattenSimpleGlyph(cache, skew, g) {
const ck = Geom.hashGeometry(g.geometry);
const cached = cache.getGF(ck);
Expand Down
2 changes: 1 addition & 1 deletion packages/font/src/otd-conv/glyphs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class MappedGlyphStore {
const gl = new Ot.Glyph.GeometryList();
for (const ref of rs) {
const target = this.queryBySourceGlyph(ref.glyph);
if (!target) throw new Error("Unreachable");
if (!target) throw new Error("Unreachable: glyph not found");
const tfm = Ot.Glyph.Transform2X3.Translate(ref.x, ref.y);
gl.items.push(new Ot.Glyph.TtReference(target, tfm));
}
Expand Down

0 comments on commit 63ec70d

Please sign in to comment.