1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/reftests/svg/as-image/svg-image-util.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,173 @@ 1.4 +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +// Standard values to use for <img>/<embed> height & width, if requested. 1.10 +var HOST_NODE_HEIGHT = "20"; 1.11 +var HOST_NODE_WIDTH = "30"; 1.12 + 1.13 +// All the possible values of "align" 1.14 +const ALIGN_VALS = ["none", 1.15 + "xMinYMin", "xMinYMid", "xMinYMax", 1.16 + "xMidYMin", "xMidYMid", "xMidYMax", 1.17 + "xMaxYMin", "xMaxYMid", "xMaxYMax"]; 1.18 + 1.19 +// All the possible values of "meetOrSlice" 1.20 +const MEETORSLICE_VALS = [ "meet", "slice" ]; 1.21 + 1.22 +/** 1.23 + * Generates full data URI for an SVG document, with the given parameters 1.24 + * on the SVG element. 1.25 + * 1.26 + * @param aViewboxArr An array of four numbers, representing the 1.27 + * viewBox attribute, or null for no viewBox. 1.28 + * @param aWidth The width attribute, or null for no width. 1.29 + * @param aHeight The height attribute, or null for no height. 1.30 + * @param aAlign The 'align' component of the 1.31 + * preserveAspectRatio attribute, or null for none. 1.32 + * @param aMeetOrSlice The 'meetOrSlice' component of the 1.33 + * preserveAspectRatio attribute, or null for 1.34 + * none. (If non-null, implies non-null value for 1.35 + * aAlign.) 1.36 + * @param aViewParams Parameters to use for the view element. 1.37 + * @param aFragmentIdentifier The SVG fragment identifier. 1.38 + */ 1.39 +function generateSVGDataURI(aViewboxArr, aWidth, aHeight, 1.40 + aAlign, aMeetOrSlice, 1.41 + aViewParams, aFragmentIdentifier) { 1.42 + // prefix 1.43 + var datauri = "data:image/svg+xml," 1.44 + // Begin the SVG tag 1.45 + datauri += "%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20shape-rendering%3D%22crispEdges%22"; 1.46 + 1.47 + // Append the custom chunk from our params 1.48 + // If we're working with views, the align customisation is applied there instead 1.49 + datauri += generateSVGAttrsForParams(aViewboxArr, aWidth, aHeight, 1.50 + aViewParams ? null : aAlign, 1.51 + aMeetOrSlice); 1.52 + 1.53 + // Add 'font-size' just in case the client wants to use ems 1.54 + datauri += "%20font-size%3D%22" + "10px" + "%22"; 1.55 + 1.56 + // Put closing right bracket on SVG tag 1.57 + datauri += "%3E"; 1.58 + 1.59 + if (aViewParams) { 1.60 + // Give the view the id of the fragment identifier 1.61 + datauri += "%3Cview%20id%3D%22" + aFragmentIdentifier + "%22"; 1.62 + 1.63 + // Append the custom chunk from our view params 1.64 + datauri += generateSVGAttrsForParams(aViewParams.viewBox, null, null, 1.65 + aAlign, aViewParams.meetOrSlice); 1.66 + 1.67 + datauri += "%2F%3E"; 1.68 + } 1.69 + 1.70 + // Add the rest of the SVG document 1.71 + datauri += "%3Crect%20x%3D%221%22%20y%3D%221%22%20height%3D%2218%22%20width%3D%2218%22%20stroke-width%3D%222%22%20stroke%3D%22black%22%20fill%3D%22yellow%22%2F%3E%3Ccircle%20cx%3D%2210%22%20cy%3D%2210%22%20r%3D%228%22%20style%3D%22fill%3A%20blue%22%2F%3E%3C%2Fsvg%3E"; 1.72 + 1.73 + return datauri; 1.74 +} 1.75 + 1.76 +// Generates just the chunk of a data URI that's relevant to 1.77 +// the given params. 1.78 +function generateSVGAttrsForParams(aViewboxArr, aWidth, aHeight, 1.79 + aAlign, aMeetOrSlice) { 1.80 + var str = ""; 1.81 + if (aViewboxArr) { 1.82 + str += "%20viewBox%3D%22"; 1.83 + for (var i in aViewboxArr) { 1.84 + str += aViewboxArr[i]; 1.85 + if (i != aViewboxArr.length - 1) { 1.86 + str += "%20"; 1.87 + } 1.88 + } 1.89 + str += "%22"; 1.90 + } 1.91 + if (aWidth) { 1.92 + str += "%20width%3D%22" + aWidth + "%22"; 1.93 + } 1.94 + if (aHeight) { 1.95 + str += "%20height%3D%22" + aHeight + "%22"; 1.96 + } 1.97 + if (aAlign) { 1.98 + str += "%20preserveAspectRatio%3D%22" + aAlign; 1.99 + if (aMeetOrSlice) { 1.100 + str += "%20" + aMeetOrSlice; 1.101 + } 1.102 + str += "%22"; 1.103 + } 1.104 + 1.105 + return str; 1.106 +} 1.107 + 1.108 +// Returns a newly-generated element with the given tagname, the given URI 1.109 +// for its |src| attribute, and the given width & height values. 1.110 +function generateHostNode(aHostNodeTagName, aUri, 1.111 + aHostNodeWidth, aHostNodeHeight) { 1.112 + var elem = document.createElement(aHostNodeTagName); 1.113 + elem.setAttribute("src", aUri); 1.114 + 1.115 + if (aHostNodeWidth) { 1.116 + elem.setAttribute("width", aHostNodeWidth); 1.117 + } 1.118 + if (aHostNodeHeight) { 1.119 + elem.setAttribute("height", aHostNodeHeight); 1.120 + } 1.121 + 1.122 + return elem; 1.123 +} 1.124 + 1.125 +// THIS IS THE CHIEF HELPER FUNCTION TO BE CALLED BY CLIENTS 1.126 +function appendSVGArrayWithParams(aSVGParams, aHostNodeTagName) { 1.127 + // These are width & height vals that will be used for the *host node*. 1.128 + // (i.e. the <img> or <embed> node -- not the <svg> node) 1.129 + var hostNodeWidthVals = [ null, HOST_NODE_WIDTH ]; 1.130 + var hostNodeHeightVals = [ null, HOST_NODE_HEIGHT ]; 1.131 + 1.132 + for (var i = 0; i < hostNodeWidthVals.length; i++) { 1.133 + var hostNodeWidth = hostNodeWidthVals[i]; 1.134 + for (var j = 0; j < hostNodeHeightVals.length; j++) { 1.135 + var hostNodeHeight = hostNodeHeightVals[j]; 1.136 + appendSVGSubArrayWithParams(aSVGParams, aHostNodeTagName, 1.137 + hostNodeWidth, hostNodeHeight); 1.138 + } 1.139 + } 1.140 +} 1.141 + 1.142 +// Helper function for above, for a fixed [host-node-width][host-node-height] 1.143 +function appendSVGSubArrayWithParams(aSVGParams, aHostNodeTagName, 1.144 + aHostNodeWidth, aHostNodeHeight) { 1.145 + var rootNode = document.getElementsByTagName("body")[0]; 1.146 + for (var k = 0; k < ALIGN_VALS.length; k++) { 1.147 + var alignVal = ALIGN_VALS[k]; 1.148 + if (!aSVGParams.meetOrSlice) { 1.149 + alignVal = "none"; 1.150 + } 1.151 + 1.152 + // Generate the Data URI 1.153 + var uri = generateSVGDataURI(aSVGParams.viewBox, 1.154 + aSVGParams.width, aSVGParams.height, 1.155 + alignVal, 1.156 + aSVGParams.meetOrSlice, 1.157 + aSVGParams.view, 1.158 + aSVGParams.fragmentIdentifier); 1.159 + 1.160 + if (aSVGParams.fragmentIdentifier) { 1.161 + uri += "#" + aSVGParams.fragmentIdentifier; 1.162 + } 1.163 + 1.164 + // Generate & append the host node element 1.165 + var hostNode = generateHostNode(aHostNodeTagName, uri, 1.166 + aHostNodeWidth, aHostNodeHeight); 1.167 + rootNode.appendChild(hostNode); 1.168 + 1.169 + // Cosmetic: Add a newline when we get halfway through the ALIGN_VALS 1.170 + // and then again when we reach the end 1.171 + if (k + 1 == ALIGN_VALS.length / 2 || 1.172 + k + 1 == ALIGN_VALS.length) { 1.173 + rootNode.appendChild(document.createElement("br")); 1.174 + } 1.175 + } 1.176 +}