Index: LayoutTests/css3/fonts/resources/style-matching-test.js |
diff --git a/LayoutTests/css3/fonts/resources/style-matching-test.js b/LayoutTests/css3/fonts/resources/style-matching-test.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d7ebe5fc4aea0de96ed16fd61f66bd9fa46b3f48 |
--- /dev/null |
+++ b/LayoutTests/css3/fonts/resources/style-matching-test.js |
@@ -0,0 +1,259 @@ |
+function emptyFontFaceDeclarations() |
+{ |
+ var stylesheet = document.styleSheets[0]; |
+ var rules = stylesheet.cssRules; |
+ var rulesLengthSnapshot = stylesheet.cssRules.length; |
+ if (!rulesLengthSnapshot) |
+ return; |
+ for (var i = 0; i < rulesLengthSnapshot; i++) { |
+ stylesheet.deleteRule(0); |
+ } |
+} |
+ |
+function makeFontFaceDeclaration(stretch, style, weight) |
+{ |
+ var fontFaceDeclaration = '@font-face { font-family: "CSSMatchingtest"; ' + |
+ "font-stretch: " + stretch + ";" + |
+ "font-style: " + style + ";" + |
+ "font-weight: " + weight + ";" + |
+ 'src: url("' + |
+ "resources/fonts/CSSMatchingTest_" + |
+ stretch + "_" + style + "_" + weight + '.ttf");'; |
+ return fontFaceDeclaration; |
+} |
+ |
+function notifyInspectorFontsReady() { |
+ var cssRules = document.styleSheets[0].cssRules; |
+ var fontsAvailable = []; |
+ for (var i = 0; i < cssRules.length; i++) { |
+ urlmatch = /url\(.*fonts\/CSSMatchingTest_(.*).ttf\)/.exec( |
+ cssRules[i].cssText); |
+ fontsAvailable.push(urlmatch[1]); |
+ } |
+ evaluateInFrontend('window.onFontsLoaded(' + |
+ JSON.stringify(fontsAvailable) + ");"); |
+} |
+ |
+function updateAvailableFontFaceDeclarations(available) |
+{ |
+ emptyFontFaceDeclarations(); |
+ for (stretch of available.stretches) |
+ for (style of available.styles) |
+ for (weight of available.weights) { |
+ document.styleSheets[0].addRule( |
+ makeFontFaceDeclaration(stretch, style, weight)); |
+ } |
+ |
+ document.fonts.ready.then(window.notifyInspectorFontsReady); |
+} |
+ |
+function test() |
+{ |
+ var documentNodeId; |
+ var documentNodeSelector; |
+ var allTestSelectors = []; |
+ var testSelectors = []; |
+ |
+ var stretches = [ 'condensed', 'expanded' ]; |
+ var styles = [ 'normal', 'italic' ]; |
+ var weights = [ '100', '900' ]; |
+ |
+ var weightsHumanReadable = [ "Thin", "Black" ]; |
+ |
+ var fontSetVariations = []; |
+ var currentFontSetVariation = {}; |
+ |
+ makeFontSetVariations(); |
+ |
+ function makeFontSetVariations() { |
+ // For each of the three properties we have three choices: |
+ // Restrict to the first value, to the second, or |
+ // allow both. So we're iterating over those options |
+ // for each dimension to generate the set of allowed |
+ // options for each property. The fonts in the test |
+ // page will later be generated from these possible |
+ // choices / restrictions. |
+ function choices(property) { |
+ return [ property, [ property[0] ], [ property[1] ] ]; |
+ } |
+ |
+ for (stretchChoice of choices(stretches)) { |
+ for (styleChoice of choices(styles)) { |
+ for (weightChoice of choices(weights)) { |
+ var available = {}; |
+ available.stretches = stretchChoice; |
+ available.styles = styleChoice; |
+ available.weights = weightChoice; |
+ fontSetVariations.push(available); |
+ } |
+ } |
+ } |
+ } |
+ |
+ InspectorTest.requestDocumentNodeId(onDocumentNodeId); |
+ |
+ function onDocumentNodeId(nodeId) |
+ { |
+ documentNodeId = nodeId; |
+ |
+ InspectorTest.evaluateInInspectedPage( |
+ 'JSON.stringify(' + |
+ 'Array.prototype.map.call(' + |
+ 'document.querySelectorAll(".test *"),' + |
+ 'function(element) { return element.id } ));', |
+ startTestingPage); |
+ } |
+ |
+ function startTestingPage(result) |
+ { |
+ allTestSelectors = JSON.parse(result.result.result.value); |
+ nextTest(); |
+ } |
+ |
+ function nextTest() { |
+ if (testSelectors.length) { |
+ testNextPageElement(); |
+ } else { |
+ currentFontSetVariation = fontSetVariations.shift(); |
+ if (currentFontSetVariation) { |
+ testSelectors = allTestSelectors.slice(); |
+ updateFontDeclarationsInPageForVariation( |
+ currentFontSetVariation); |
+ } else { |
+ InspectorTest.completeTest(); |
+ } |
+ } |
+ } |
+ |
+ function updateFontDeclarationsInPageForVariation(fontSetVariation) |
+ { |
+ window.testPageFontsReady = false; |
+ InspectorTest.evaluateInInspectedPage( |
+ 'updateAvailableFontFaceDeclarations(' + |
+ JSON.stringify(fontSetVariation) + |
+ ');'); |
+ // nextTest() is called once we receive the onFontsLoaded |
+ // notification from the page. |
+ } |
+ |
+ // Explicitly make this available on window scope so that testing |
+ // can resume through a signal from the page once the fonts.ready |
+ // promise resolves. |
+ window.onFontsLoaded = function(loadedFonts) { |
+ InspectorTest.log("Available fonts updated: " + |
+ JSON.stringify(loadedFonts) + "\n"); |
+ // fonts.ready event fires too early, used fonts for rendering |
Kunihiko Sakamoto
2015/08/05 10:36:36
Hmm, fonts.ready resolves before the style change
|
+ // have not been updated yet. Remove this wehn crbug.com/516680 |
+ // is fixed. |
+ // https://drafts.csswg.org/css-font-loading/#font-face-set-ready |
+ setTimeout(nextTest, 100); |
+ } |
+ |
+ function testNextPageElement(result) |
+ { |
+ var nextSelector = testSelectors.shift() |
+ if (nextSelector) { |
+ documentNodeSelector = "#" + nextSelector; |
+ platformFontsForElementWithSelector(documentNodeSelector); |
+ } |
+ } |
+ |
+ function platformFontsForElementWithSelector(selector) |
+ { |
+ InspectorTest.requestNodeId(documentNodeId, selector, onNodeId); |
+ |
+ function onNodeId(nodeId) |
+ { |
+ InspectorTest.sendCommandOrDie("CSS.getPlatformFontsForNode", |
+ { nodeId: nodeId }, |
+ onGotComputedFonts); |
+ } |
+ |
+ function onGotComputedFonts(response) |
+ { |
+ logResults(response); |
+ nextTest(); |
+ } |
+ } |
+ |
+ function logResults(response) |
+ { |
+ InspectorTest.log(documentNodeSelector); |
+ logPassFailResult( |
+ documentNodeSelector, |
+ response.fonts[0].familyName); |
+ } |
+ |
+ function cssStyleMatchingExpectationForSelector(selector) { |
+ var selectorStretchStyleWeight = selector.substr(1).split("_"); |
+ var selectorStretch = selectorStretchStyleWeight[0].toLowerCase(); |
+ var selectorStyle = selectorStretchStyleWeight[1].toLowerCase(); |
+ var selectorWeight = selectorStretchStyleWeight[2]; |
+ |
+ var expectedProperties = {}; |
+ if (currentFontSetVariation.stretches.indexOf(selectorStretch) > 0) { |
+ expectedProperties.stretch = selectorStretch; |
+ } else { |
+ // If the requested property value is not availabe in the |
+ // current font set, then it's restricted to only one value, |
+ // which is the nearest match, and at index 0. |
+ expectedProperties.stretch = currentFontSetVariation.stretches[0]; |
+ } |
+ |
+ if (currentFontSetVariation.styles.indexOf(selectorStyle) > 0) { |
+ expectedProperties.style = selectorStyle; |
+ } else { |
+ expectedProperties.style = currentFontSetVariation.styles[0]; |
+ } |
+ |
+ if (currentFontSetVariation.weights.indexOf(selectorWeight) > 0) { |
+ expectedProperties.weight = selectorWeight; |
+ } else { |
+ expectedProperties.weight = currentFontSetVariation.weights[0]; |
+ } |
+ |
+ return expectedProperties; |
+ } |
+ |
+ function logPassFailResult(selector, usedFontName) |
+ { |
+ var actualStretchStyleWeight = |
+ /CSSMatchingTest (\w*) (\w*) (.*)/.exec(usedFontName); |
+ var actualStretch, actualStyle, actualWeight; |
+ if (actualStretchStyleWeight && actualStretchStyleWeight.length > 3) { |
+ actualStretch = actualStretchStyleWeight[1].toLowerCase(); |
+ actualStyle = actualStretchStyleWeight[2].toLowerCase(); |
+ // Font names have human readable weight description, |
+ // we need to convert. |
+ actualWeight = weights [ |
+ weightsHumanReadable.indexOf(actualStretchStyleWeight[3]) ]; |
+ } else { |
+ actualStretch = usedFontName; |
+ actualStyle = ""; |
+ actualWeight = ""; |
+ } |
+ |
+ var expectedProperties = cssStyleMatchingExpectationForSelector( |
+ selector); |
+ |
+ InspectorTest.log("Expected: " + |
+ expectedProperties.stretch + " " + |
+ expectedProperties.style + " " + |
+ expectedProperties.weight); |
+ InspectorTest.log("Actual: " + actualStretch + " " + |
+ actualStyle + " " + |
+ actualWeight); |
+ |
+ if (actualStretch != expectedProperties.stretch || |
+ actualStyle != expectedProperties.style || |
+ actualWeight != expectedProperties.weight) { |
+ InspectorTest.log("FAIL\n"); |
+ } else { |
+ InspectorTest.log("PASS\n"); |
+ } |
+ } |
+}; |
+ |
+window.addEventListener("DOMContentLoaded", function () { |
+ runTest(); |
+}, false); |