layout/reftests/svg/as-image/svg-image-util.js

changeset 0
6474c204b198
     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 +}

mercurial