// Simple implementation of SVG sizing setup({explicit_done: true}); var SVGSizing = (function() { function parseLength(l) { var match = /^([-+]?[0-9]+|[-+]?[0-9]*\.[0-9]+)(px|%)?$/.exec(l); if (!match) return null; return new Length(Number(match[1]), match[2] ? match[2] : "px"); } function parseViewBox(input) { if (!input) return null; var arr = input.split(' '); return arr.map(function(a) { return parseInt(a); }); } // Only px and % are used function convertToPx(input, percentRef) { if (input == null) return null; var length = parseLength(input); if (length.amount == 0) return 0; if (!length.unit) length.unit = "px"; if (length.unit == "%" && percentRef === undefined) return null; return length.amount * { px: 1, "%": percentRef/100}[length.unit]; } function Length(amount, unit) { this.amount = amount; this.unit = unit; } function describe(data) { function dumpObject(obj) { var r = ""; for (var property in obj) { if (obj.hasOwnProperty(property)) { var value = obj[property]; if (typeof value == 'string') value = "'" + value + "'"; else if (value == null) value = "null"; else if (typeof value == 'object') { if (value instanceof Array) value = "[" + value + "]"; else value = "{" + dumpObject(value) + "}"; } if (value != "null") r += property + ": " + value + ", "; } } return r; } var result = dumpObject(data); if (result == "") return "(initial values)"; return result; } function mapPresentationalHintLength(testData, cssProperty, attr) { if (attr) { var l = parseLength(attr); if (l) testData.style[cssProperty] = l.amount + l.unit; } } function computedWidthIsAuto(testData) { return !testData.style["width"] || testData.style["width"] == 'auto'; } function computedHeightIsAuto(testData) { return !testData.style["height"] || testData.style["height"] == 'auto' || (parseLength(testData.style["height"]).unit == '%' && containerComputedHeightIsAuto(testData)); } function containerComputedWidthIsAuto(testData) { return !testData.config.containerWidthStyle || testData.config.containerWidthStyle == 'auto'; } function containerComputedHeightIsAuto(testData) { return !testData.config.containerHeightStyle || testData.config.containerHeightStyle == 'auto'; } function intrinsicInformation(testData) { if (testData.config.placeholder == 'iframe') return {}; var w = convertToPx(testData.config.svgWidthAttr) || 0; var h = convertToPx(testData.config.svgHeightAttr) || 0; var r = 0; if (w && h) { r = w / h; } else { var vb = parseViewBox(testData.config.svgViewBoxAttr); if (vb) { r = vb[2] / vb[3]; } if (r) { if (!w && h) w = h * r; else if (!h && w) h = w / r; } } return { width: w, height: h, ratio: r }; }; function contentAttributeForPlaceholder(testData) { if (testData.config.placeholder == 'object') return "data"; else return "src"; } function TestData(config) { this.config = config; this.name = describe(config); this.style = {}; if (config.placeholder) { mapPresentationalHintLength(this, "width", config.placeholderWidthAttr); mapPresentationalHintLength(this, "height", config.placeholderHeightAttr); } else { if (config.svgWidthStyle) this.style["width"] = config.svgWidthStyle; else mapPresentationalHintLength(this, "width", config.svgWidthAttr); if (config.svgHeightStyle) this.style["height"] = config.svgHeightStyle; else mapPresentationalHintLength(this, "height", config.svgHeightAttr); } } TestData.prototype.computeInlineReplacedSize = function(outerWidth, outerHeight) { var intrinsic = intrinsicInformation(this); var self = this; // http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height function calculateUsedHeight() { if (computedHeightIsAuto(self)) { if (computedWidthIsAuto(self) && intrinsic.height) return intrinsic.height; if (intrinsic.ratio) return calculateUsedWidth() / intrinsic.ratio; if (intrinsic.height) return intrinsic.height; return 150; } return convertToPx(self.style["height"], convertToPx(self.config.containerHeightStyle, outerHeight)); } // http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width function calculateUsedWidth() { if (computedWidthIsAuto(self)) { if (computedHeightIsAuto(self) && intrinsic.width) return intrinsic.width; if (!computedHeightIsAuto(self) && intrinsic.ratio) return calculateUsedHeight() * intrinsic.ratio; if (computedHeightIsAuto(self) && intrinsic.ratio) { if (containerComputedWidthIsAuto(self)) { // Note: While this is actually undefined in CSS // 2.1, use the suggested value by examining the // ancestor widths. return outerWidth; } else { return convertToPx(self.config.containerWidthStyle, outerWidth); } } if (intrinsic.width) return intrinsic.width; return 300; } if (containerComputedWidthIsAuto(self)) return convertToPx(self.style["width"], outerWidth); else return convertToPx(self.style["width"], convertToPx(self.config.containerWidthStyle, outerWidth)); } return { width: calculateUsedWidth(), height: calculateUsedHeight() }; }; TestData.prototype.buildContainer = function (placeholder, options) { options = options || {}; var container = document.createElement("div"); container.id = "container"; if (this.config.containerWidthStyle) container.style.width = this.config.containerWidthStyle; if (this.config.containerHeightStyle) container.style.height = this.config.containerHeightStyle; if (options.pretty) container.appendChild(document.createTextNode("\n\t\t")); container.appendChild(placeholder); if (options.pretty) container.appendChild(document.createTextNode("\n\t")); return container; }; TestData.prototype.buildSVGOrPlaceholder = function (options) { options = options || {}; var self = this; if (this.config.placeholder) { var generateSVGURI = function(testData, encoder) { var res = '' + (passed ? 'Pass' : 'Fail') + '');\n" + "};\n"; root.appendChild(script); root.appendChild(document.createTextNode("\n")); var expectedElement = document.createElement("div"); expectedElement.id = "expected"; root.appendChild(expectedElement); root.appendChild(document.createTextNode("\n")); var testContainer = document.createElement("div"); testContainer.id = "testContainer"; testContainer.appendChild(document.createTextNode("\n\t")); testContainer.appendChild(container); testContainer.appendChild(document.createTextNode("\n")); root.appendChild(testContainer); root.appendChild(document.createTextNode("\n")); return "\n" + root.outerHTML; } function pad(n, width, z) { z = z || '0'; n = n + ''; return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; } function heightToDescription(height) { if (!height || height == "auto") return "auto"; if (parseLength(height).unit == '%') return "percentage"; return "fixed"; } var demoRoot = document.querySelector('#demo'); if (demoRoot) { var demo = buildDemoSerialization(); var iframe = document.createElement('iframe'); iframe.style.width = (Math.max(900, expectedRect.width)) + "px"; iframe.style.height = (Math.max(400, expectedRect.height)) + "px"; iframe.src = "data:text/html;charset=utf-8," + encodeURIComponent(demo); demoRoot.appendChild(iframe); demoRoot.insertAdjacentHTML( 'beforeEnd', '

Download

'); } }; return { TestData: TestData, doCombinationTest: function(values, func, testSingleId) { function computeConfig(id) { id--; var multiplier = 1; var config = {}; for (var i=0; i= multiplier) return null; return config; } function cont(id) { var config = computeConfig(id); if (config && (!testSingleId || testSingleId == id)) { var next = function() {func(config, id, cont)}; // Make sure we don't blow the stack, without too much slowness if (id % 20 === 0) { step_timeout(next, 0); } else { next(); } } else { done(); } }; if (testSingleId) cont(testSingleId); else cont(1); } }; })();