fix: 修复行缘、切分还原与语言解析并同步文档
保留逐字 margin/jiya.bias 字体后备方案;补齐 demo 重排、量测边界说明及共享规则 1.0.1 反例向量。 验证:完整构建通过,Node 376 项、WKWebView 64 项及原生 demo 9 项通过;Firefox 仍暂缓。
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { mkdtempSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { test } from "node:test";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const python = "python3";
|
||||
const available = spawnSync(python, [ "-c", "import fontTools" ]).status === 0;
|
||||
const tool = fileURLToPath(new URL("../tools/measure-bias.py", import.meta.url));
|
||||
const fixture = `
|
||||
from fontTools.fontBuilder import FontBuilder
|
||||
from fontTools.pens.ttGlyphPen import TTGlyphPen
|
||||
from fontTools.feaLib.builder import addOpenTypeFeaturesFromString
|
||||
import sys
|
||||
fb = FontBuilder(1000, isTTF=True)
|
||||
names = ['.notdef', 'comma', 'commaHant', 'fullstop']
|
||||
fb.setupGlyphOrder(names)
|
||||
fb.setupCharacterMap({0xff0c: 'comma', 0xff0e: 'fullstop'})
|
||||
glyphs = {}
|
||||
for name, left, right in [('.notdef', 0, 0), ('comma', 50, 250),
|
||||
('commaHant', 450, 550), ('fullstop', 650, 850)]:
|
||||
p = TTGlyphPen(None)
|
||||
if right > left:
|
||||
p.moveTo((left, 0)); p.lineTo((right, 0)); p.lineTo((right, 150))
|
||||
p.lineTo((left, 150)); p.closePath()
|
||||
glyphs[name] = p.glyph()
|
||||
fb.setupGlyf(glyphs)
|
||||
fb.setupHorizontalMetrics({'.notdef': (1000, 0), 'comma': (1000, 50),
|
||||
'commaHant': (1000, 450), 'fullstop': (1000, 650)})
|
||||
fb.setupHorizontalHeader(ascent=800, descent=-200)
|
||||
fb.setupNameTable({'familyName': 'BiasFixture', 'styleName': 'Regular',
|
||||
'uniqueFontIdentifier': 'BiasFixture', 'fullName': 'BiasFixture',
|
||||
'psName': 'BiasFixture'})
|
||||
fb.setupOS2(sTypoAscender=800, sTypoDescender=-200, usWinAscent=800, usWinDescent=200)
|
||||
fb.setupPost(); fb.setupMaxp()
|
||||
features = 'languagesystem hani ZHT; feature locl { script hani; language ZHT; sub comma by commaHant; } locl;'
|
||||
if sys.argv[2] == 'halt':
|
||||
features += ' feature halt { sub fullstop by comma; } halt;'
|
||||
addOpenTypeFeaturesFromString(fb.font, features)
|
||||
fb.save(sys.argv[1])
|
||||
`;
|
||||
|
||||
function run(args)
|
||||
{
|
||||
const result = spawnSync(python, args, { encoding: "utf8" });
|
||||
assert.equal(result.status, 0, result.stderr || String(result.error));
|
||||
return result.stdout;
|
||||
}
|
||||
|
||||
function withFont(feature, check)
|
||||
{
|
||||
const dir = mkdtempSync(join(tmpdir(), "juzhen-bias-test-"));
|
||||
try
|
||||
{
|
||||
const font = join(dir, "fixture.ttf");
|
||||
run([ "-c", fixture, font, feature ]);
|
||||
check(font);
|
||||
}
|
||||
finally { rmSync(dir, { recursive: true, force: true }); }
|
||||
}
|
||||
|
||||
function table(output)
|
||||
{
|
||||
return JSON.parse(output.slice(output.indexOf("\n{") + 1));
|
||||
}
|
||||
|
||||
test("measure-bias:全角句點入表,lang 僅選鍵且輸出說明 cmap/locl 限制",
|
||||
{ skip: available ? false : "需工具本身的 Python fonttools 依賴" }, () =>
|
||||
{
|
||||
withFont("none", (font) =>
|
||||
{
|
||||
for (const lang of [ "zh-Hans", "zh-Hant" ])
|
||||
{
|
||||
const output = run([ tool, font, lang ]);
|
||||
assert.equal(table(output)[lang]["."], "right");
|
||||
assert.equal(table(output)[lang][","], "left", "仍量預設 cmap,未套 ZHT locl 替代字形");
|
||||
assert.match(output, /未做 shaping.*未應用 locl/);
|
||||
assert.match(output, /語言參數僅選 JSON 分類鍵/);
|
||||
assert.match(output, /瀏覽器實際字形逐字微調/);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test("measure-bias:halt feature 存在只報存在,不承諾逐字覆蓋",
|
||||
{ skip: available ? false : "需工具本身的 Python fonttools 依賴" }, () =>
|
||||
{
|
||||
withFont("halt", (font) =>
|
||||
{
|
||||
const output = run([ tool, font ]);
|
||||
assert.match(output, /halt:有.*不保證涵蓋所有標點/);
|
||||
assert.equal(table(output)["zh-Hans"]["."], "right", "feature 偵測不改預設輪廓分類");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user