Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize glyph quantity; Fix glyph visual for COMBINING DOUBLE CIRCUMFLEX ABOVE (U+1DCD). #2252

Merged
merged 1 commit into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading