summaryrefslogtreecommitdiffstats
path: root/layout/style/test/test_unicode_range_loading.html
diff options
context:
space:
mode:
Diffstat (limited to 'layout/style/test/test_unicode_range_loading.html')
-rw-r--r--layout/style/test/test_unicode_range_loading.html366
1 files changed, 366 insertions, 0 deletions
diff --git a/layout/style/test/test_unicode_range_loading.html b/layout/style/test/test_unicode_range_loading.html
new file mode 100644
index 000000000..43622e2ae
--- /dev/null
+++ b/layout/style/test/test_unicode_range_loading.html
@@ -0,0 +1,366 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>unicode-range load tests using font loading api</title>
+ <link rel="author" title="John Daggett" href="mailto:jdaggett@mozilla.com">
+ <link rel="help" href="http://www.w3.org/TR/css-fonts-3/#unicode-range-desc" />
+ <link rel="help" href="http://dev.w3.org/csswg/css-font-loading/" />
+ <meta name="assert" content="unicode-range descriptor defines precisely which fonts should be loaded" />
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <style type="text/css">
+ </style>
+</head>
+<body>
+<div id="log"></div>
+<pre id="display"></pre>
+<style id="testfonts"></style>
+<style id="teststyle"></style>
+<div id="testcontent"></div>
+
+<script>
+
+const kSheetFonts = 1;
+const kSheetStyles = 2;
+
+const redSquDataURL = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10' width='100%' height='100%'><rect fill='red' x='0' y='0' width='10' height='10'/></svg>";
+
+var unicodeRangeTests = [
+ { test: "simple load sanity check, unused fonts not loaded",
+ fonts: [{ family: "a", src: "markA", descriptors: { }, loaded: false}],
+ content: "AAA", style: { "font-family": "unused" } },
+ { test: "simple load sanity check, font for a used character loaded",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+41" }, loaded: true}],
+ content: "AAA" },
+ { test: "simple load sanity check, font for an unused character not loaded",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+41" }, loaded: false}],
+ content: "BBB" },
+ { test: "simple load sanity check, with two fonts only font for used character loaded A",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+41" }, loaded: true},
+ { family: "a", src: "markB", descriptors: { unicodeRange: "u+42" }, loaded: false}],
+ content: "AAA" },
+ { test: "simple load sanity check, with two fonts only font for used character loaded B",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+41" }, loaded: false},
+ { family: "a", src: "markB", descriptors: { unicodeRange: "u+42" }, loaded: true}],
+ content: "BBB" },
+ { test: "simple load sanity check, two fonts but neither supports characters used",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+41" }, loaded: false},
+ { family: "a", src: "markB", descriptors: { unicodeRange: "u+42" }, loaded: false}],
+ content: "CCC" },
+ { test: "simple load sanity check, two fonts and both are used",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+41" }, loaded: true},
+ { family: "a", src: "markB", descriptors: { unicodeRange: "u+42" }, loaded: true}],
+ content: "ABC" },
+ { test: "simple load sanity check, one with Han ranges",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+3???,u+5???,u+7???,u+8???" }, loaded: true},
+ { family: "a", src: "markB", descriptors: { unicodeRange: "u+42" }, loaded: false}],
+ content: "納豆嫌い" },
+ { test: "simple load sanity check, two fonts with different styles A",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+41" }, loaded: true},
+ { family: "a", src: "markB", descriptors: { weight: "bold", unicodeRange: "u+42" }, loaded: false}],
+ content: "ABC" },
+ { test: "simple load sanity check, two fonts with different styles B",
+ fonts: [{ family: "a", src: "markA", descriptors: { weight: "bold", unicodeRange: "u+41" }, loaded: false},
+ { family: "a", src: "markB", descriptors: { unicodeRange: "u+42" }, loaded: true}],
+ content: "ABC" },
+ { test: "multiple fonts with overlapping ranges, all with default ranges, only last one supports character used",
+ fonts: [{ family: "a", src: "markC", descriptors: { }, loaded: true},
+ { family: "a", src: "markA", descriptors: { }, loaded: true},
+ { family: "a", src: "markB", descriptors: { }, loaded: true}],
+ content: "CCC" },
+ { test: "multiple fonts with overlapping ranges, all with default ranges, first one supports character used",
+ fonts: [{ family: "a", src: "markB", descriptors: { }, loaded: false},
+ { family: "a", src: "markA", descriptors: { }, loaded: false},
+ { family: "a", src: "markC", descriptors: { }, loaded: true}],
+ content: "CCC" },
+ { test: "multiple fonts with overlapping ranges, one with default value in the fallback position",
+ fonts: [{ family: "a", src: "markC", descriptors: { }, loaded: true},
+ { family: "a", src: "markA", descriptors: { unicodeRange: "u+41" }, loaded: true},
+ { family: "a", src: "markB", descriptors: { unicodeRange: "u+42" }, loaded: true}],
+ content: "ABC" },
+ { test: "multiple fonts with overlapping ranges, one with default value in the primary use position, fallback to one",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+41" }, loaded: true},
+ { family: "a", src: "markB", descriptors: { unicodeRange: "u+42" }, loaded: false},
+ { family: "a", src: "markC", descriptors: { }, loaded: true}],
+ content: "AAA" },
+ { test: "multiple fonts with overlapping ranges, one with default value in the primary use position, fallback to two",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+41" }, loaded: true},
+ { family: "a", src: "markB", descriptors: { unicodeRange: "u+42" }, loaded: true},
+ { family: "a", src: "markC", descriptors: { }, loaded: true}],
+ content: "ABC" },
+ { test: "multiple fonts with overlapping ranges, one with default value in the primary use position, no fallback",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+41" }, loaded: false},
+ { family: "a", src: "markB", descriptors: { unicodeRange: "u+42" }, loaded: false},
+ { family: "a", src: "markC", descriptors: { }, loaded: true}],
+ content: "CCC" },
+ { test: "metrics only case, ex-sized image, single font with space in range",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+0??" }, loaded: true}],
+ content: "<img style='width: 2ex' src=\"" + redSquDataURL + "\">" },
+ { test: "metrics only case, ex-sized image, single font with space outside range",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+1??" }, loaded: false}],
+ content: "<img style='width: 2ex' src=\"" + redSquDataURL + "\">" },
+ { test: "metrics only case, ch-sized image, single font with space in range",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+0??" }, loaded: true}],
+ content: "<img style='width: 2ch' src=\"" + redSquDataURL + "\">" },
+ { test: "metrics only case, ch-sized image, single font with space outside range",
+ fonts: [{ family: "a", src: "markA", descriptors: { unicodeRange: "u+1??" }, loaded: false}],
+ content: "<img style='width: 2ch' src=\"" + redSquDataURL + "\">" },
+];
+
+// map font loading descriptor names to @font-face rule descriptor names
+var mapDescriptorNames = {
+ style: "font-style",
+ weight: "font-weight",
+ stretch: "font-stretch",
+ unicodeRange: "unicode-range",
+ variant: "font-variant",
+ featureSettings: "font-feature-settings"
+};
+
+var kBaseFontURL;
+if ("SpecialPowers" in window) {
+ kBaseFontURL = "";
+} else {
+ kBaseFontURL = "fonts/";
+}
+
+var mapFontURLs = {
+ markA: "url(" + kBaseFontURL + "markA.woff" + ")",
+ markB: "url(" + kBaseFontURL + "markB.woff" + ")",
+ markC: "url(" + kBaseFontURL + "markC.woff" + ")",
+ markD: "url(" + kBaseFontURL + "markD.woff" + ")",
+
+ /* twourl versions include a bogus url followed by a valid url */
+ markAtwourl: "url(" + kBaseFontURL + "bogus-markA.woff" + "), url(" + kBaseFontURL + "markA.woff" + ")",
+ markBtwourl: "url(" + kBaseFontURL + "bogus-markB.woff" + "), url(" + kBaseFontURL + "markB.woff" + ")",
+ markCtwourl: "url(" + kBaseFontURL + "bogus-markC.woff" + "), url(" + kBaseFontURL + "markC.woff" + ")",
+ markDtwourl: "url(" + kBaseFontURL + "bogus-markD.woff" + "), url(" + kBaseFontURL + "markD.woff" + ")",
+
+ /* localfont versions include a bogus local ref followed by a valid url */
+ markAlocalfirst: "local(bogus-markA), url(" + kBaseFontURL + "markA.woff" + ")",
+ markBlocalfirst: "local(bogus-markB), url(" + kBaseFontURL + "markB.woff" + ")",
+ markClocalfirst: "local(bogus-markC), url(" + kBaseFontURL + "markC.woff" + ")",
+ markDlocalfirst: "local(bogus-markD), url(" + kBaseFontURL + "markD.woff" + ")",
+};
+
+function familyName(name, i) {
+ return "test" + i + "-" + name;
+}
+
+function fontFaceRule(name, fontdata, ft) {
+ var desc = [];
+ desc.push("font-family: " + name);
+ var srckey = fontdata.src + ft;
+ desc.push("src: " + mapFontURLs[srckey]);
+ for (var d in fontdata.descriptors) {
+ desc.push(mapDescriptorNames[d] + ": " + fontdata.descriptors[d]);
+ }
+ return "@font-face { " + desc.join(";") + " }";
+}
+
+function clearRules(sheetIndex) {
+ var sheet = document.styleSheets[sheetIndex];
+ while(sheet.cssRules.length > 0) {
+ sheet.deleteRule(0);
+ }
+}
+
+function clearAllRulesAndFonts() {
+ clearRules(kSheetFonts);
+ clearRules(kSheetStyles);
+ document.fonts.clear();
+}
+
+function addStyleRulesAndText(testdata, i) {
+ // add style rules for testcontent
+ var sheet = document.styleSheets[kSheetStyles];
+ while(sheet.cssRules.length > 0) {
+ sheet.deleteRule(0);
+ }
+ var rule = [];
+ var family = familyName(testdata.fonts[0].family, i);
+ rule.push("#testcontent { font-family: " + family);
+ if ("style" in testdata) {
+ for (s in testdata.style) {
+ rule.push(s + ": " + testdata.style[s]);
+ }
+ }
+ rule.push("}");
+ sheet.insertRule(rule.join("; "), 0);
+
+ var content = document.getElementById("testcontent");
+ content.innerHTML = testdata.content;
+ content.offsetHeight;
+}
+
+// work arounds
+function getFonts() {
+ if ("forEach" in document.fonts) {
+ return document.fonts;
+ }
+ return Array.from(document.fonts);
+}
+
+function getSize() {
+ if ("size" in document.fonts) {
+ return document.fonts.size;
+ }
+ return getFonts().length;
+}
+
+function getReady() {
+ if (typeof(document.fonts.ready) == "function") {
+ return document.fonts.ready();
+ }
+ return document.fonts.ready;
+}
+
+function setTimeoutPromise(aDelay) {
+ return new Promise(function(aResolve, aReject) {
+ setTimeout(aResolve, aDelay);
+ });
+}
+
+function addFontFaceRules(testdata, i, ft) {
+ var sheet = document.styleSheets[kSheetFonts];
+ var createdFonts = [];
+ testdata.fonts.forEach(function(f) {
+ var n = sheet.cssRules.length;
+ var fn = familyName(f.family, i);
+ sheet.insertRule(fontFaceRule(fn, f, ft), n);
+ var newfont;
+ var fonts = getFonts();
+ try {
+ fonts.forEach(function(font) { newfont = font; });
+ createdFonts.push({family: fn, data: f, font: newfont});
+ } catch (e) {
+ console.log(e);
+ }
+ });
+ return createdFonts;
+}
+
+function addDocumentFonts(testdata, i, ft) {
+ var createdFonts = [];
+ testdata.fonts.forEach(function(fd) {
+ var fn = familyName(fd.family, i);
+ var srckey = fd.src + ft;
+ var f = new FontFace(fn, mapFontURLs[srckey], fd.descriptors);
+ document.fonts.add(f);
+ createdFonts.push({family: fn, data: fd, font: f});
+ });
+ return createdFonts;
+}
+
+var q = Promise.resolve();
+
+function runTests() {
+ function setupTests() {
+ setup({explicit_done: true});
+ }
+
+ function checkFontsBeforeLoad(name, testdata, fd) {
+ test(function() {
+ assert_equals(document.fonts.status, "loaded", "before initializing test, no fonts should be loading - found: " + document.fonts.status);
+ var size = getSize();
+ assert_equals(size, testdata.fonts.length,
+ "fonts where not added to the font set object");
+ var i = 0;
+ fonts = getFonts();
+ fonts.forEach(function(ff) {
+ assert_equals(ff.status, "unloaded", "added fonts should be in unloaded state");
+ });
+ }, name + " before load");
+ }
+
+ function checkFontsAfterLoad(name, testdata, fd, afterTimeout) {
+ test(function() {
+ assert_equals(document.fonts.status, "loaded", "after ready promise resolved, no fonts should be loading");
+ var i = 0;
+ fd.forEach(function(f) {
+ assert_true(f.font instanceof FontFace, "font needs to be an instance of FontFace object");
+ if (f.data.loaded) {
+ assert_equals(f.font.status, "loaded", "font not loaded - font " + i + " " + f.data.src + " "
+ + JSON.stringify(f.data.descriptors) + " for content " + testdata.content);
+ } else {
+ assert_equals(f.font.status, "unloaded", "font loaded - font " + i + " " + f.data.src + " "
+ + JSON.stringify(f.data.descriptors) + " for content " + testdata.content);
+ }
+ i++;
+ });
+ }, name + " after load" + (afterTimeout ? " and timeout" : ""));
+ }
+
+ function testFontLoads(testdata, i, name, fd) {
+ checkFontsBeforeLoad(name, testdata, fd);
+ addStyleRulesAndText(testdata, i);
+
+ var ready = getReady();
+ return ready.then(function() {
+ checkFontsAfterLoad(name, testdata, fd, false);
+ }).then(function() {
+ return setTimeoutPromise(0).then(function() {
+ checkFontsAfterLoad(name, testdata, fd, true);
+ });
+ }).then(function() {
+ var ar = getReady();
+ return ar.then(function() {
+ test(function() {
+ assert_equals(document.fonts.status, "loaded", "after ready promise fulfilled once, fontset should not be loading");
+ var fonts = getFonts();
+ fonts.forEach(function(f) {
+ assert_not_equals(f.status, "loading", "after ready promise fulfilled once, no font should be loading");
+ });
+ }, name + " test done check");
+ });
+ }).then(function() {
+ clearAllRulesAndFonts();
+ });
+ }
+
+ function testUnicodeRangeFontFace(testdata, i, ft) {
+ var name = "TEST " + i + " " + testdata.test + " (@font-face rules)" + (ft != "" ? " " + ft : ft);
+
+ var fd = addFontFaceRules(testdata, i, ft);
+ return testFontLoads(testdata, i, name, fd);
+ }
+
+ function testUnicodeRangeDocumentFonts(testdata, i, ft) {
+ var name = "TEST " + i + " " + testdata.test + " (document.fonts)" + (ft != "" ? " " + ft : ft);
+
+ var fd = addDocumentFonts(testdata, i, ft);
+ return testFontLoads(testdata, i, name, fd);
+ }
+
+ q = q.then(function() {
+ setupTests();
+ });
+
+ var fontTypes = ["", "twourl", "localfirst"];
+
+ unicodeRangeTests.forEach(function(testdata, i) {
+ fontTypes.forEach(function(ft) {
+ q = q.then(function() {
+ return testUnicodeRangeFontFace(testdata, i, ft);
+ }).then(function() {
+ return testUnicodeRangeDocumentFonts(testdata, i, ft);
+ });
+ });
+ });
+
+ q = q.then(function() {
+ done();
+ });
+}
+
+if ("fonts" in document) {
+ runTests();
+} else {
+ test(function() {
+ assert_true(true, "CSS Font Loading API is not enabled.");
+ }, "CSS Font Loading API is not enabled");
+}
+</script>
+</body>
+</html>