diff options
Diffstat (limited to 'layout/style/test/test_unicode_range_loading.html')
-rw-r--r-- | layout/style/test/test_unicode_range_loading.html | 366 |
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> |