* Add special k-dot shape (#1978).
This commit is contained in:
parent
35c252a174
commit
0e6967c328
5 changed files with 108 additions and 42 deletions
|
@ -1 +1,2 @@
|
|||
* Remove duplicate serifed variant for LATIN SMALL LETTER N WITH LEFT HOOK (`U+0272`).
|
||||
* Add special k-dot shape (#1978).
|
||||
|
|
|
@ -2,62 +2,95 @@ import ttfaRanges from "../../generated/ttfa-ranges.mjs";
|
|||
import * as Gr from "../../support/gr.mjs";
|
||||
import { ArrayUtil } from "../../support/utils.mjs";
|
||||
|
||||
export async function generateTtfaControls(gsOrig, gs) {
|
||||
export async function generateTtfaControls(gsOrig, gsTtf) {
|
||||
let ttfaControls = [`# Machine generated. Do not modify.`];
|
||||
|
||||
for (const alignment of ttfaRanges) {
|
||||
generateTTFAAlignments(ttfaControls, alignment, gsOrig, gs);
|
||||
let alignments = [];
|
||||
for (const cfg of ttfaRanges) {
|
||||
const alignment = new Alignment(cfg.scriptTag, cfg.featureTag, cfg.ranges);
|
||||
alignment.collectDefault(gsOrig, gsTtf);
|
||||
alignments.push(alignment);
|
||||
}
|
||||
|
||||
for (const go of gsOrig.glyphs()) {
|
||||
const hc = Gr.HintClass.get(go);
|
||||
if (!hc) continue;
|
||||
const gd = gsTtf.queryBySourceGlyph(go);
|
||||
if (!gd) continue;
|
||||
const [s, f] = hc;
|
||||
for (const alignment of alignments) {
|
||||
if (s === alignment.scriptTag && f === alignment.featureTag)
|
||||
alignment.allGlyphs.set(go, gd);
|
||||
}
|
||||
}
|
||||
|
||||
for (const alignment of alignments) {
|
||||
alignment.extend(gsOrig, gsTtf);
|
||||
alignment.write(ttfaControls, gsTtf);
|
||||
}
|
||||
|
||||
return ttfaControls;
|
||||
}
|
||||
|
||||
function generateTTFAAlignments(sink, alignment, gsOrig, gsTtf) {
|
||||
let allGlyphs = new Map();
|
||||
let defaultGlyphs = new Map();
|
||||
for (const [lo, hi] of alignment.ranges) {
|
||||
for (let lch = lo; lch <= hi; lch++) {
|
||||
const go = gsOrig.queryByUnicode(lch);
|
||||
if (!go) continue;
|
||||
const gd = gsTtf.queryBySourceGlyph(go);
|
||||
if (!gd) continue;
|
||||
allGlyphs.set(go, gd);
|
||||
defaultGlyphs.set(go, gd);
|
||||
}
|
||||
class Alignment {
|
||||
constructor(scriptTag, featureTag, ranges) {
|
||||
this.scriptTag = scriptTag;
|
||||
this.featureTag = featureTag;
|
||||
this.ranges = ranges;
|
||||
|
||||
this.defaultGlyphs = new Map();
|
||||
this.allGlyphs = new Map();
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
let sizeBefore = allGlyphs.size;
|
||||
|
||||
for (const [go, gd] of allGlyphs) {
|
||||
const cvs = Gr.AnyCv.query(go);
|
||||
for (const gr of cvs) {
|
||||
const gnLinked = gr.get(go);
|
||||
if (!gnLinked) continue;
|
||||
const goLinked = gsOrig.queryByName(gnLinked);
|
||||
if (!goLinked) continue;
|
||||
const gdLinked = gsTtf.queryBySourceGlyph(goLinked);
|
||||
if (!gdLinked) continue;
|
||||
allGlyphs.set(goLinked, gdLinked);
|
||||
collectDefault(gsOrig, gsTtf) {
|
||||
for (const [lo, hi] of this.ranges) {
|
||||
for (let lch = lo; lch <= hi; lch++) {
|
||||
const go = gsOrig.queryByUnicode(lch);
|
||||
if (!go) continue;
|
||||
const gd = gsTtf.queryBySourceGlyph(go);
|
||||
if (!gd) continue;
|
||||
this.allGlyphs.set(go, gd);
|
||||
this.defaultGlyphs.set(go, gd);
|
||||
}
|
||||
}
|
||||
|
||||
let sizeAfter = allGlyphs.size;
|
||||
if (sizeAfter <= sizeBefore) break;
|
||||
}
|
||||
|
||||
const gOrd = gsTtf.decideOrder();
|
||||
let nonDefaultGlyphIndices = [];
|
||||
for (const [go, gd] of allGlyphs) {
|
||||
if (defaultGlyphs.has(go)) continue;
|
||||
nonDefaultGlyphIndices.push(gOrd.reverse(gd));
|
||||
extend(gsOrig, gsTtf) {
|
||||
for (;;) {
|
||||
let sizeBefore = this.allGlyphs.size;
|
||||
|
||||
for (const [go, gd] of this.allGlyphs) {
|
||||
const cvs = Gr.AnyCv.query(go);
|
||||
for (const gr of cvs) {
|
||||
const gnLinked = gr.get(go);
|
||||
if (!gnLinked) continue;
|
||||
const goLinked = gsOrig.queryByName(gnLinked);
|
||||
if (!goLinked) continue;
|
||||
const gdLinked = gsTtf.queryBySourceGlyph(goLinked);
|
||||
if (!gdLinked) continue;
|
||||
this.allGlyphs.set(goLinked, gdLinked);
|
||||
}
|
||||
}
|
||||
|
||||
let sizeAfter = this.allGlyphs.size;
|
||||
if (sizeAfter <= sizeBefore) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nonDefaultGlyphIndices.length) return;
|
||||
write(sink, gsTtf) {
|
||||
const gOrd = gsTtf.decideOrder();
|
||||
let nonDefaultGlyphIndices = [];
|
||||
for (const [go, gd] of this.allGlyphs) {
|
||||
if (this.defaultGlyphs.has(go)) continue;
|
||||
nonDefaultGlyphIndices.push(gOrd.reverse(gd));
|
||||
}
|
||||
|
||||
const glyphIndicesRangesStr = ArrayUtil.toRanges(nonDefaultGlyphIndices)
|
||||
.map(([lo, hi]) => (lo === hi ? `${lo}` : `${lo}-${hi}`))
|
||||
.join(", ");
|
||||
if (!nonDefaultGlyphIndices.length) return;
|
||||
|
||||
sink.push(`${alignment.scriptTag} ${alignment.featureTag} @ ${glyphIndicesRangesStr}`);
|
||||
const glyphIndicesRangesStr = ArrayUtil.toRanges(nonDefaultGlyphIndices)
|
||||
.map(([lo, hi]) => (lo === hi ? `${lo}` : `${lo}-${hi}`))
|
||||
.join(", ");
|
||||
|
||||
sink.push(`${this.scriptTag} ${this.featureTag} @ ${glyphIndicesRangesStr}`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
$$include '../../../meta/macros.ptl'
|
||||
|
||||
import [mix clamp fallback linreg SuffixCfg] from"../../../support/utils.mjs"
|
||||
import [Dotless CvDecompose MathSansSerif] from"../../../support/gr.mjs"
|
||||
import [Dotless CvDecompose MathSansSerif HintClass] from"../../../support/gr.mjs"
|
||||
import [maskBit] from"../../../support/util/mask-bit.mjs"
|
||||
|
||||
glyph-module
|
||||
|
@ -583,6 +583,14 @@ glyph-block Letter-Latin-K : begin
|
|||
|
||||
select-variant 'grek/KaiSymbol' 0x3CF
|
||||
|
||||
derive-multi-part-glyphs 'kDot' null {'k' 'dotAbove'} : lambda [srcs gr] : glyph-proc
|
||||
local { base mark } srcs
|
||||
include : refer-glyph mark
|
||||
include : Translate (Width + [HSwToV HalfStroke]) 0
|
||||
include [refer-glyph base] AS_BASE
|
||||
include : LeaningAnchor.Above.VBar.l Middle
|
||||
HintClass.set currentGlyph 'latn' 'dflt'
|
||||
|
||||
glyph-block-import Letter-Blackboard : BBS BBD BBBarLeft
|
||||
define [BBKLegShape top left right] : begin
|
||||
local kDiag : DiagCorDs (top / 2) (right - left) BBD
|
||||
|
|
|
@ -103,6 +103,17 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
|||
inputEnds 3
|
||||
apply {{.at 1 .lookup lookupTieMarkLigature}}
|
||||
|
||||
Ccmp-Group "Special dot-above transformation" : begin
|
||||
# b-dot, d-dot, h-dot, k-dot
|
||||
export-lookup : AddLookup sink : object
|
||||
.type 'gsub_ligature'
|
||||
.ignoreGlyphs [filterMarkByClassNegated markGlyphs 'above']
|
||||
.substitutions : list
|
||||
object [from : list "b" "dotAbove"] [to "bDot"]
|
||||
object [from : list "d" "dotAbove"] [to "dDot"]
|
||||
object [from : list "h" "dotAbove"] [to "hDot"]
|
||||
object [from : list "k" "dotAbove"] [to "kDot"]
|
||||
|
||||
Ccmp-Group "Leaning Mark Trasnform" : begin
|
||||
define LeaningAnchorMap : list
|
||||
list 'above' 'leaningAbove'
|
||||
|
@ -137,6 +148,8 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
|||
.inputEnds 2
|
||||
.apply {{.at 1 .lookup lookupTurnMarkIntoLeaningAndSpacer}}
|
||||
|
||||
|
||||
|
||||
Ccmp-Group "Rhotic Hook Transform" : begin
|
||||
define superscripts {}
|
||||
define subscripts {}
|
||||
|
|
|
@ -132,6 +132,17 @@ export const Joining = {
|
|||
}
|
||||
};
|
||||
|
||||
export const HintClass = {
|
||||
get(glyph) {
|
||||
if (glyph && glyph.related) return glyph.related.hintClass;
|
||||
else return null;
|
||||
},
|
||||
set(glyph, script, style) {
|
||||
if (!glyph.related) glyph.related = {};
|
||||
glyph.related.hintClass = [script, style];
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const CvTagCache = new Map();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue