1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-spacing-trim-property">
<!--
Test patterns are from "Fullwidth Punctuation Collapsing":
https://drafts.csswg.org/css-text-4/#fullwidth-collapsing
-->
<meta name="variant" content="?class=htb&test=CC:HF">
<meta name="variant" content="?class=htb&test=CM:HF">
<meta name="variant" content="?class=htb&test=CO:FH">
<meta name="variant" content="?class=htb&test=MO:FH">
<meta name="variant" content="?class=htb&test=OO:FH">
<meta name="variant" content="?class=vrl&test=CC:HF">
<meta name="variant" content="?class=vrl&test=CM:HF">
<meta name="variant" content="?class=vrl&test=CO:FH">
<meta name="variant" content="?class=vrl&test=MO:FH">
<meta name="variant" content="?class=vrl&test=OO:FH">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/variant-class.js"></script>
<script src="../support/get-char-advances.js"></script>
<style>
@font-face {
font-family: halt-font;
src: url('/fonts/noto/cjk/NotoSansCJKjp-Regular-subset-halt.otf');
}
#container {
font-family: halt-font;
font-size: 20px;
}
.vrl #container {
writing-mode: vertical-rl;
}
</style>
<div id="log"></div>
<div id="container"></div>
<script>
const classes = {
// Open. Noto CJK doesn't have these glyphs or `halt`/`valt`:
// \u3008\u301A\u3010\uFF3B
'O': '\u300A\u300C\u300E\u3014\u3016\u3018\u301D' +
'\uFF08\uFF5B\uFF5F',
// Close. Noto CJK doesn't have these glyphs or `halt`/`valt`:
// \u3009\u301B\u3011\u301E\uFF3D
'C': '\u300B\u300D\u300F\u3015\u3017\u3019\u301F' +
'\uFF09\uFF5D\uFF60',
// Open Quotes.
'Q': '\u2018\u201C',
// Close quotes.
'R': '\u2019\u201D',
// Middle and ideographic space.
'M': '\u30FB\u3000',
// Dot (comma and full stops.)
'D': '\u3001\u3002\uFF0C\uFF0E',
// Colon.
'L': '\uFF1A',
// Semicolon. Colon and Semicolon may be different in vertical flow.
'S': '\uFF1B',
// Exclamation marks.
'E': '\uFF01\uFF1F',
};
const container = document.getElementById('container');
const em = parseInt(getComputedStyle(container).fontSize);
const threshold = em * .8;
// Generate a list of text from a pattern.
// For example, a pattern 'OC' generates all combinations from
// characters in `classes['O']` and `classes['C']`.
function* textFromPattern(pattern, prefix = '') {
const key = pattern[0];
const rest = pattern.substr(1);
for (const ch of classes[key]) {
if (!rest) {
yield prefix + ch;
continue;
}
yield *textFromPattern(rest, prefix + ch);
}
}
class TestData {
constructor(text, expect) {
const element = document.createElement('div');
element.textContent = text;
this.text = text;
this.element = element;
this.expect = expect;
}
static all = [];
static generate(pattern, expect, container) {
for (const text of textFromPattern(pattern)) {
const data = new TestData(text, expect);
container.appendChild(data.element);
TestData.all.push(data);
}
}
static runAll(indices) {
if (indices && indices.length) {
for (const index of indices) {
TestData.all[index].run(index);
}
return;
}
TestData.all.forEach((data, i) => {
data.run(i);
})
}
run(index) {
const advances = getCharAdvances(this.element);
const results = advances.map(advance => advance >= threshold ? 'F' : 'H');
const result = results.join('');
test(() => {
assert_equals(result, this.expect);
}, `${index}: ${this.text}`);
}
}
setup(() => {
assert_implements(CSS.supports('text-spacing-trim', 'initial'));
}, {explicit_done: true});
(async function () {
const params = new URLSearchParams(window.location.search);
const style= getComputedStyle(container);
const is_vertical = style.writingMode.startsWith('vertical');
// Assign dots and colons using the Noto's Japanese convention.
classes['C'] += classes['D'];
classes['M'] += classes['L'];
if (!is_vertical) classes['M'] += classes['S'];
const args = params.getAll('test').flatMap(i => i.split(','));
for (const arg of args) {
const [pattern, expect] = arg.split(':');
TestData.generate(pattern, expect, container);
}
await document.fonts.ready;
const indices = params.getAll('i').flatMap(i => i.split(','))
.map(i => parseInt(i));
TestData.runAll(indices);
done();
})();
</script>
|