layout/base/tests/test_getBoxQuads_convertPointRectQuad.html

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/base/tests/test_getBoxQuads_convertPointRectQuad.html	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,672 @@
     1.4 +<!DOCTYPE HTML>
     1.5 +<html>
     1.6 +<head>
     1.7 +<meta charset="utf-8">
     1.8 +<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
     1.9 +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
    1.10 +</head>
    1.11 +<body onload="startTest()">
    1.12 +<p id="display"></p>
    1.13 +<script>
    1.14 +// Global variables we want eval() to be able to reference from anywhere
    1.15 +var f1d;
    1.16 +var text;
    1.17 +var suppressedText;
    1.18 +var suppressedText2;
    1.19 +var comment;
    1.20 +var fragment;
    1.21 +var openedWindow;
    1.22 +var zeroPoint = new DOMPoint(0,0);
    1.23 +var zeroRect = new DOMRect(0,0,0,0);
    1.24 +var zeroQuad = new DOMQuad(zeroRect);
    1.25 +var notInDocument = document.createElement('div');
    1.26 +
    1.27 +function isEval(expr, b) {
    1.28 +  is(eval(expr), b, expr);
    1.29 +}
    1.30 +
    1.31 +function isApprox(a, b, msg, options) {
    1.32 +  if (a != b && 'tolerance' in options &&
    1.33 +      Math.abs(a - b) < options.tolerance) {
    1.34 +    ok(true, msg + "(" + a + " within " + options.tolerance + " of " + b + ")");
    1.35 +    return;
    1.36 +  }
    1.37 +  is(a, b, msg);
    1.38 +}
    1.39 +
    1.40 +function makeQuadsExpr(fromStr, options) {
    1.41 +  var getBoxQuadsOptionParts = [];
    1.42 +  if ('box' in options) {
    1.43 +    getBoxQuadsOptionParts.push("box:'" + options.box + "'");
    1.44 +  }
    1.45 +  if ('toStr' in options) {
    1.46 +    getBoxQuadsOptionParts.push("relativeTo:" + options.toStr);
    1.47 +  }
    1.48 +  return fromStr + ".getBoxQuads({" + getBoxQuadsOptionParts.join(',') + "})";
    1.49 +}
    1.50 +
    1.51 +function makePointExpr(fromStr, options, x, y) {
    1.52 +  var convertPointOptionParts = [];
    1.53 +  if ('box' in options) {
    1.54 +    convertPointOptionParts.push("fromBox:'" + options.box + "'");
    1.55 +  }
    1.56 +  if ('toBox' in options) {
    1.57 +    convertPointOptionParts.push("toBox:'" + options.toBox + "'");
    1.58 +  }
    1.59 +  return ('toStr' in options ? options.toStr : "document") +
    1.60 +    ".convertPointFromNode(new DOMPoint(" + x + "," + y + ")," + fromStr + ",{" +
    1.61 +    convertPointOptionParts.join(",") + "})";
    1.62 +}
    1.63 +
    1.64 +function checkConvertPoints(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
    1.65 +  var selfQuads = eval(fromStr).getBoxQuads(
    1.66 +    {box:options.box == "" ? "border" : options.box,
    1.67 +     relativeTo:eval(fromStr)});
    1.68 +  var boxWidth = selfQuads[0].bounds.width;
    1.69 +  var boxHeight = selfQuads[0].bounds.height;
    1.70 +
    1.71 +  var convertTopLeftPointExpr = makePointExpr(fromStr, options, 0, 0);
    1.72 +  var topLeft = eval(convertTopLeftPointExpr);
    1.73 +  isApprox(topLeft.x, x1, convertTopLeftPointExpr + ".x", options);
    1.74 +  isApprox(topLeft.y, y1, convertTopLeftPointExpr + ".y", options);
    1.75 +
    1.76 +  var convertTopRightPointExpr = makePointExpr(fromStr, options, boxWidth, 0);
    1.77 +  var topRight = eval(convertTopRightPointExpr);
    1.78 +  isApprox(topRight.x, x2, convertTopRightPointExpr + ".x", options);
    1.79 +  isApprox(topRight.y, y2, convertTopRightPointExpr + ".y", options);
    1.80 +
    1.81 +  var convertBottomRightPointExpr = makePointExpr(fromStr, options, boxWidth, boxHeight);
    1.82 +  var bottomRight = eval(convertBottomRightPointExpr);
    1.83 +  isApprox(bottomRight.x, x3, convertBottomRightPointExpr + ".x", options);
    1.84 +  isApprox(bottomRight.y, y3, convertBottomRightPointExpr + ".y", options);
    1.85 +
    1.86 +  var convertBottomLeftPointExpr = makePointExpr(fromStr, options, 0, boxHeight);
    1.87 +  var bottomLeft = eval(convertBottomLeftPointExpr);
    1.88 +  isApprox(bottomLeft.x, x4, convertBottomLeftPointExpr + ".x", options);
    1.89 +  isApprox(bottomLeft.y, y4, convertBottomLeftPointExpr + ".y", options);
    1.90 +}
    1.91 +
    1.92 +function checkConvertRect(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
    1.93 +  var selfQuads = eval(fromStr).getBoxQuads(
    1.94 +    {box:options.box == "" ? "border" : options.box,
    1.95 +     relativeTo:eval(fromStr)});
    1.96 +  var boxWidth = selfQuads[0].bounds.width;
    1.97 +  var boxHeight = selfQuads[0].bounds.height;
    1.98 +
    1.99 +  var convertPointOptionParts = [];
   1.100 +  if ('box' in options) {
   1.101 +    convertPointOptionParts.push("fromBox:'" + options.box + "'");
   1.102 +  }
   1.103 +  if ('toBox' in options) {
   1.104 +    convertPointOptionParts.push("toBox:'" + options.toBox + "'");
   1.105 +  }
   1.106 +
   1.107 +  var convertRectExpr = ('toStr' in options ? options.toStr : "document") +
   1.108 +    ".convertRectFromNode(new DOMRect(0,0," + boxWidth + "," + boxHeight + ")," +
   1.109 +    fromStr + ",{" + convertPointOptionParts.join(",") + "})";
   1.110 +  var quad = eval(convertRectExpr);
   1.111 +  isApprox(quad.p1.x, x1, convertRectExpr + ".p1.x", options);
   1.112 +  isApprox(quad.p1.y, y1, convertRectExpr + ".p1.y", options);
   1.113 +  isApprox(quad.p2.x, x2, convertRectExpr + ".p2.x", options);
   1.114 +  isApprox(quad.p2.y, y2, convertRectExpr + ".p2.y", options);
   1.115 +  isApprox(quad.p3.x, x3, convertRectExpr + ".p3.x", options);
   1.116 +  isApprox(quad.p3.y, y3, convertRectExpr + ".p3.y", options);
   1.117 +  isApprox(quad.p4.x, x4, convertRectExpr + ".p4.x", options);
   1.118 +  isApprox(quad.p4.y, y4, convertRectExpr + ".p4.y", options);
   1.119 +}
   1.120 +
   1.121 +function checkConvertQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
   1.122 +  var selfQuads = eval(fromStr).getBoxQuads(
   1.123 +    {box:options.box == "" ? "border" : options.box,
   1.124 +     relativeTo:eval(fromStr)});
   1.125 +  var boxWidth = selfQuads[0].bounds.width;
   1.126 +  var boxHeight = selfQuads[0].bounds.height;
   1.127 +
   1.128 +  var convertPointOptionParts = [];
   1.129 +  if ('box' in options) {
   1.130 +    convertPointOptionParts.push("fromBox:'" + options.box + "'");
   1.131 +  }
   1.132 +  if ('toBox' in options) {
   1.133 +    convertPointOptionParts.push("toBox:'" + options.toBox + "'");
   1.134 +  }
   1.135 +
   1.136 +  var convertQuadExpr = ('toStr' in options ? options.toStr : "document") +
   1.137 +    ".convertQuadFromNode(new DOMQuad(new DOMRect(0,0," + boxWidth + "," + boxHeight + "))," +
   1.138 +    fromStr + ",{" + convertPointOptionParts.join(",") + "})";
   1.139 +  var quad = eval(convertQuadExpr);
   1.140 +  isApprox(quad.p1.x, x1, convertQuadExpr + ".p1.x", options);
   1.141 +  isApprox(quad.p1.y, y1, convertQuadExpr + ".p1.y", options);
   1.142 +  isApprox(quad.p2.x, x2, convertQuadExpr + ".p2.x", options);
   1.143 +  isApprox(quad.p2.y, y2, convertQuadExpr + ".p2.y", options);
   1.144 +  isApprox(quad.p3.x, x3, convertQuadExpr + ".p3.x", options);
   1.145 +  isApprox(quad.p3.y, y3, convertQuadExpr + ".p3.y", options);
   1.146 +  isApprox(quad.p4.x, x4, convertQuadExpr + ".p4.x", options);
   1.147 +  isApprox(quad.p4.y, y4, convertQuadExpr + ".p4.y", options);
   1.148 +}
   1.149 +
   1.150 +function checkQuadIsRect(fromStr, options, x, y, w, h) {
   1.151 +  var quadsExpr = makeQuadsExpr(fromStr, options);
   1.152 +  var quads = eval(quadsExpr);
   1.153 +  is(quads.length, 1, quadsExpr + " checking quad count");
   1.154 +  var q = quads[0];
   1.155 +  isApprox(q.p1.x, x, quadsExpr + " checking quad.p1.x", options);
   1.156 +  isApprox(q.p1.y, y, quadsExpr + " checking quad.p1.y", options);
   1.157 +  isApprox(q.p2.x, x + w, quadsExpr + " checking quad.p2.x", options);
   1.158 +  isApprox(q.p2.y, y, quadsExpr + " checking quad.p2.y", options);
   1.159 +  isApprox(q.p3.x, x + w, quadsExpr + " checking quad.p3.x", options);
   1.160 +  isApprox(q.p3.y, y + h, quadsExpr + " checking quad.p3.y", options);
   1.161 +  isApprox(q.p4.x, x, quadsExpr + " checking quad.p4.x", options);
   1.162 +  isApprox(q.p4.y, y + h, quadsExpr + " checking quad.p4.y", options);
   1.163 +
   1.164 +  isApprox(q.bounds.left, x, quadsExpr + " checking quad.bounds.left", options);
   1.165 +  isApprox(q.bounds.top, y, quadsExpr + " checking quad.bounds.top", options);
   1.166 +  isApprox(q.bounds.width, w, quadsExpr + " checking quad.bounds.width", options);
   1.167 +  isApprox(q.bounds.height, h, quadsExpr + " checking quad.bounds.height", options);
   1.168 +
   1.169 +  checkConvertPoints(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h);
   1.170 +  checkConvertRect(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h);
   1.171 +  checkConvertQuad(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h);
   1.172 +}
   1.173 +
   1.174 +function checkQuadIsQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
   1.175 +  var quadsExpr = makeQuadsExpr(fromStr, options);
   1.176 +  var quads = eval(quadsExpr);
   1.177 +  is(quads.length, 1, quadsExpr + " checking quad count");
   1.178 +  var q = quads[0];
   1.179 +  isApprox(q.p1.x, x1, quadsExpr + " checking quad.p1.x", options);
   1.180 +  isApprox(q.p1.y, y1, quadsExpr + " checking quad.p1.y", options);
   1.181 +  isApprox(q.p2.x, x2, quadsExpr + " checking quad.p2.x", options);
   1.182 +  isApprox(q.p2.y, y2, quadsExpr + " checking quad.p2.y", options);
   1.183 +  isApprox(q.p3.x, x3, quadsExpr + " checking quad.p3.x", options);
   1.184 +  isApprox(q.p3.y, y3, quadsExpr + " checking quad.p3.y", options);
   1.185 +  isApprox(q.p4.x, x4, quadsExpr + " checking quad.p4.x", options);
   1.186 +  isApprox(q.p4.y, y4, quadsExpr + " checking quad.p4.y", options);
   1.187 +
   1.188 +  isApprox(q.bounds.left, Math.min(x1,x2,x3,x4), quadsExpr + " checking quad.bounds.left", options);
   1.189 +  isApprox(q.bounds.top, Math.min(y1,y2,y3,y4), quadsExpr + " checking quad.bounds.top", options);
   1.190 +  isApprox(q.bounds.right, Math.max(x1,x2,x3,x4), quadsExpr + " checking quad.bounds.right", options);
   1.191 +  isApprox(q.bounds.bottom, Math.max(y1,y2,y3,y4), quadsExpr + " checking quad.bounds.bottom", options);
   1.192 +
   1.193 +  checkConvertPoints(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4);
   1.194 +  checkConvertRect(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4);
   1.195 +  checkConvertQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4);
   1.196 +}
   1.197 +
   1.198 +function checkException(expr, name) {
   1.199 +  try {
   1.200 +    eval(expr);
   1.201 +    ok(false, "Exception should have been thrown for " + expr);
   1.202 +  } catch (ex) {
   1.203 +    is(ex.name, name, "Checking exception type for " + expr);
   1.204 +  }
   1.205 +}
   1.206 +
   1.207 +function checkNotFound(fromStr, toStr, x1, y1, x2, y2) {
   1.208 +  var convertPointExpr = toStr + ".convertPointFromNode(new DOMPoint(" + x1 +
   1.209 +    "," + y1 + ")," + fromStr + ")";
   1.210 +  checkException(convertPointExpr, "NotFoundError");
   1.211 +
   1.212 +  var convertRectExpr = toStr + ".convertRectFromNode(new DOMRect(" + x1 +
   1.213 +    "," + y1 + "," + x2 + "," + y2 + ")," + fromStr + ")";
   1.214 +  checkException(convertRectExpr, "NotFoundError");
   1.215 +
   1.216 +  var convertQuadExpr = toStr + ".convertQuadFromNode(new DOMQuad(new DOMRect(" + x1 +
   1.217 +    "," + y1 + "," + x2 + "," + y2 + "))," + fromStr + ")";
   1.218 +  checkException(convertQuadExpr, "NotFoundError");
   1.219 +}
   1.220 +</script>
   1.221 +<style>
   1.222 +em {
   1.223 +  display:inline-block; height:10px; background:gray;
   1.224 +}
   1.225 +</style>
   1.226 +<div id="dContainer"
   1.227 +     style="padding:13px 14px 15px 16px;
   1.228 +            border-width:17px 18px 19px 20px; border-style:solid; border-color:yellow;
   1.229 +            margin:21px 22px 23px 24px;">
   1.230 +  <div id="d"
   1.231 +       style="width:120px; height:90px; padding:1px 2px 3px 4px;
   1.232 +              border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow;
   1.233 +              margin:9px 10px 11px 12px; background:blue;">
   1.234 +  </div>
   1.235 +</div>
   1.236 +
   1.237 +<div id="dUnrelated" style="width:50px; height:50px;"></div>
   1.238 +
   1.239 +<iframe id="f1" style="width:50px; height:50px; border:0; background:lime;"
   1.240 +        src="data:text/html,<!DOCTYPE HTML><html style='padding:25px'><div id='f1d' style='position:absolute; left:14px; top:15px; width:16px; height:17px; background:pink'></div>">
   1.241 +</iframe>
   1.242 +<!--
   1.243 +It matters that the first part of this span is on the same line as the above <iframe>!
   1.244 +That ensures the first quad's X position is not equal to the anonymous block's X position.
   1.245 +-->
   1.246 +<span id="ibSplit"
   1.247 +  ><em id="ibSplitPart1" style="width:100px;"></em
   1.248 +  ><div style="width:110px; height:20px; background:black"></div
   1.249 +  ><em style="width:130px;"></em></span>
   1.250 +
   1.251 +<table cellspacing="0" id="table" style="border:0; margin:0; padding:0; background:orange">
   1.252 +  <tbody style="padding:0; margin:0; border:0; background:blue">
   1.253 +    <tr style="height:50px; padding:0; margin:0; border:0">
   1.254 +      <td style="border:0; margin:0; padding:0">Cell</td>
   1.255 +    </tr>
   1.256 +  </tbody>
   1.257 +  <caption style="height:40px; background:yellow">Caption</caption>
   1.258 +</table>
   1.259 +
   1.260 +<div style="height:80px; -moz-column-count:2; -moz-column-fill:auto; border:2px solid black;">
   1.261 +  <div style="height:20px;"></div>
   1.262 +  <div id="colSplit" style="height:80px; background:blue; border:10px solid red; border-bottom-width:15px"></div>
   1.263 +</div>
   1.264 +
   1.265 +<div style="width:200px; border:2px solid black;"
   1.266 +  ><em style="width:150px;"></em
   1.267 +  ><span id="inlineSplit" style="background:pink; border:10px solid red; border-right-width:15px"
   1.268 +    ><em style="width:20px; background:green"></em><em style="width:60px"></em
   1.269 +  ></span
   1.270 +></div>
   1.271 +
   1.272 +<div style="width:200px; border:2px solid black;"
   1.273 +  ><em style="width:150px;"></em
   1.274 +  ><span id="textContainer">T
   1.275 +TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText</span
   1.276 +></div>
   1.277 +
   1.278 +<div id="suppressedTextContainer"> </div>
   1.279 +<div id="suppressedTextContainer2"> </div>
   1.280 +
   1.281 +<div id="commentContainer"><!-- COMMENT --></div>
   1.282 +
   1.283 +<div id="displayNone" style="display:none"></div>
   1.284 +
   1.285 +<div id="overflowHidden"
   1.286 +     style="overflow:hidden; width:120px; height:90px; padding:1px 2px 3px 4px;
   1.287 +            border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow;
   1.288 +            margin:9px 10px 11px 12px; background:blue;">
   1.289 +  <div style="height:400px; background:lime;"></div>
   1.290 +</div>
   1.291 +
   1.292 +<div id="overflowScroll"
   1.293 +     style="overflow:scroll; width:120px; height:90px; padding:1px 2px 3px 4px;
   1.294 +            border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow;
   1.295 +            margin:9px 10px 11px 12px; background:blue; background-clip:content-box;">
   1.296 +  <div id="overflowScrollChild" style="height:400px;"></div>
   1.297 +</div>
   1.298 +
   1.299 +<div id="scaleTransformContainer" style="width:200px; height:200px;">
   1.300 +  <div id="scaleTransform"
   1.301 +       style="transform:scale(2); transform-origin:top left; width:70px; height:80px; background:yellow"></div>
   1.302 +</div>
   1.303 +
   1.304 +<div id="translateTransformContainer" style="width:200px; height:200px;">
   1.305 +  <div id="translateTransform"
   1.306 +       style="transform:translate(30px,40px); width:70px; height:80px; background:yellow"></div>
   1.307 +</div>
   1.308 +
   1.309 +<div id="rotateTransformContainer" style="width:200px; height:200px;">
   1.310 +  <div id="rotateTransform"
   1.311 +       style="transform:rotate(90deg); width:70px; height:80px; background:yellow"></div>
   1.312 +</div>
   1.313 +
   1.314 +<div id="flipTransformContainer" style="width:200px; height:200px;">
   1.315 +  <div id="flipTransform"
   1.316 +       style="transform:scaleY(-1); width:70px; height:80px; background:yellow"></div>
   1.317 +</div>
   1.318 +
   1.319 +<div id="rot45TransformContainer" style="width:200px; height:200px;">
   1.320 +  <div id="rot45Transform"
   1.321 +       style="transform:rotate(45deg); width:100px; height:100px; background:yellow"></div>
   1.322 +</div>
   1.323 +
   1.324 +<div id="singularTransform" style="transform:scale(0); width:200px; height:200px;">
   1.325 +  <div id="singularTransformChild1" style="height:50px;"></div>
   1.326 +  <div id="singularTransformChild2" style="height:50px;"></div>
   1.327 +</div>
   1.328 +
   1.329 +<div id="threeDTransformContainer" style="perspective:600px; width:200px; height:200px">
   1.330 +  <div id="threeDTransform" style="transform:rotateY(70deg); background:yellow; height:100px; perspective:600px">
   1.331 +    <div id="threeDTransformChild" style="transform:rotateY(-70deg); background:blue; height:50px;"></div>
   1.332 +  </div>
   1.333 +</div>
   1.334 +
   1.335 +<div id="preserve3DTransformContainer" style="perspective:600px; width:200px; height:200px">
   1.336 +  <div id="preserve3DTransform" style="transform:rotateY(70deg); transform-style:preserve-3d; background:yellow; height:100px;">
   1.337 +    <div id="preserve3DTransformChild" style="transform:rotateY(-70deg); background:blue; height:50px;"></div>
   1.338 +  </div>
   1.339 +</div>
   1.340 +
   1.341 +<div id="svgContainer">
   1.342 +  <svg id="svg" style="width:200px; height:200px; background:lightgray;">
   1.343 +    <circle id="circle" cx="50" cy="50" r="20" fill="red" style="margin:20px; padding:10px; border:15px solid black"></circle>
   1.344 +    <g transform="scale(2)">
   1.345 +      <foreignObject x="50" y="20">
   1.346 +        <div id="foreign" style="width:100px; height:60px; background:purple"></div>
   1.347 +      </foreignObject>
   1.348 +    </g>
   1.349 +  </svg>
   1.350 +</div>
   1.351 +
   1.352 +<script>
   1.353 +SimpleTest.waitForExplicitFinish();
   1.354 +
   1.355 +window.scrollTo(0,0);
   1.356 +
   1.357 +function startTest() {
   1.358 +  SpecialPowers.pushPrefEnv({"set": [["layout.css.DOMPoint.enabled", true],
   1.359 +                                     ["layout.css.DOMQuad.enabled", true],
   1.360 +                                     ["layout.css.getBoxQuads.enabled", true],
   1.361 +                                     ["layout.css.convertFromNode.enabled", true]]}, runTest);
   1.362 +}
   1.363 +
   1.364 +function runTest() {
   1.365 +  // Setup globals
   1.366 +  f1d = f1.contentWindow.f1d;
   1.367 +  text = textContainer.firstChild;
   1.368 +  suppressedText = suppressedTextContainer.firstChild;
   1.369 +  suppressedText2 = suppressedTextContainer2.firstChild;
   1.370 +  comment = commentContainer.firstChild;
   1.371 +  fragment = document.createDocumentFragment();
   1.372 +
   1.373 +  // Test basic BoxQuadOptions.box.
   1.374 +  var dX = d.getBoundingClientRect().left;
   1.375 +  var dY = d.getBoundingClientRect().top;
   1.376 +  var dW = d.getBoundingClientRect().width;
   1.377 +  var dH = d.getBoundingClientRect().height;
   1.378 +
   1.379 +  checkQuadIsRect("d", {box:"content"},
   1.380 +                  dX + 4 + 8, dY + 1 + 5, 120, 90);
   1.381 +  checkQuadIsRect("d", {box:"padding"},
   1.382 +                  dX + 8, dY + 5, 120 + 2 + 4, 90 + 1 + 3);
   1.383 +  checkQuadIsRect("d", {box:"border"},
   1.384 +                  dX, dY, dW, dH);
   1.385 +  checkQuadIsRect("d", {},
   1.386 +                  dX, dY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
   1.387 +  checkQuadIsRect("d", {box:"margin"},
   1.388 +                  dX - 12, dY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11);
   1.389 +
   1.390 +  // Test basic BoxQuadOptions.relativeTo
   1.391 +  checkQuadIsRect("d", {toStr:"dContainer"},
   1.392 +                  12 + 16 + 20, 9 + 13 + 17, dW, dH);
   1.393 +
   1.394 +  // Test BoxQuadOptions.relativeTo relative to this document          
   1.395 +  checkQuadIsRect("d", {toStr:"document"},
   1.396 +                  dX, dY, dW, dH);
   1.397 +  // Test BoxQuadOptions.relativeTo relative to a non-ancestor.             
   1.398 +  var dUnrelatedX = dUnrelated.getBoundingClientRect().left;
   1.399 +  var dUnrelatedY = dUnrelated.getBoundingClientRect().top;
   1.400 +  checkQuadIsRect("d", {toStr:"dUnrelated"},
   1.401 +                  dX - dUnrelatedX, dY - dUnrelatedY, dW, dH);
   1.402 +  // Test BoxQuadOptions.relativeTo relative to an element in a different document (and the document)
   1.403 +  var f1X = f1.getBoundingClientRect().left;
   1.404 +  var f1Y = f1.getBoundingClientRect().top;
   1.405 +  checkQuadIsRect("d", {toStr:"f1.contentWindow.f1d"},
   1.406 +                  dX - (f1X + 14), dY - (f1Y + 15), dW, dH);
   1.407 +  checkQuadIsRect("d", {toStr:"f1.contentDocument"},
   1.408 +                  dX - f1X, dY - f1Y, dW, dH);
   1.409 +  // Test one document relative to another
   1.410 +  checkQuadIsRect("f1.contentDocument", {toStr:"document"},
   1.411 +                  f1X, f1Y, 50, 50);
   1.412 +  // The box type is irrelevant for a document
   1.413 +  checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"content"},
   1.414 +                  f1X, f1Y, 50, 50);
   1.415 +  checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"margin"},
   1.416 +                  f1X, f1Y, 50, 50);
   1.417 +  checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"padding"},
   1.418 +                  f1X, f1Y, 50, 50);
   1.419 +
   1.420 +  // Test that anonymous boxes are correctly ignored when building quads.
   1.421 +  var ibSplitPart1X = ibSplitPart1.getBoundingClientRect().left;
   1.422 +  var ibSplitY = ibSplit.getBoundingClientRect().top;
   1.423 +  isEval("ibSplit.getBoxQuads().length", 3);
   1.424 +  isEval("ibSplit.getBoxQuads()[0].bounds.left", ibSplitPart1X);
   1.425 +  isEval("ibSplit.getBoxQuads()[0].bounds.width", 100);
   1.426 +  isEval("ibSplit.getBoxQuads()[1].bounds.width", 110);
   1.427 +  isEval("ibSplit.getBoxQuads()[2].bounds.width", 130);
   1.428 +  isEval("table.getBoxQuads().length", 2);
   1.429 +  isEval("table.getBoxQuads()[0].bounds.height", 50);
   1.430 +  isEval("table.getBoxQuads()[1].bounds.height", 40);
   1.431 +
   1.432 +  // Test that we skip anonymous boxes when finding the right box to be relative to.
   1.433 +  checkQuadIsRect("d", {toStr:"ibSplit"},
   1.434 +                  dX - ibSplitPart1X, dY - ibSplitY, dW, dH);
   1.435 +  var tableX = table.getClientRects()[0].left;
   1.436 +  var tableY = table.getClientRects()[0].top;
   1.437 +  checkQuadIsRect("d", {toStr:"table"},
   1.438 +                  dX - tableX, dY - tableY, dW, dH);
   1.439 +  isEval("ibSplit.convertPointFromNode(zeroPoint,d).x", dX - ibSplitPart1X);
   1.440 +  isEval("table.convertPointFromNode(zeroPoint,d).x", dX - table.getClientRects()[0].left);
   1.441 +
   1.442 +  // Test boxes generated by block splitting. Check for borders being placed correctly.
   1.443 +  var colSplitY = colSplit.getClientRects()[0].top;
   1.444 +  isEval("colSplit.getBoxQuads().length", 2);
   1.445 +  isEval("colSplit.getBoxQuads()[0].bounds.top", colSplitY);
   1.446 +  isEval("colSplit.getBoxQuads()[0].bounds.height", 60);
   1.447 +  isEval("colSplit.getBoxQuads()[1].bounds.top", colSplitY - 20);
   1.448 +  isEval("colSplit.getBoxQuads()[1].bounds.height", 45);
   1.449 +  isEval("colSplit.getBoxQuads({box:'content'}).length", 2);
   1.450 +  // The first box for the block has the top border; the second box has the bottom border.
   1.451 +  isEval("colSplit.getBoxQuads({box:'content'})[0].bounds.top", colSplitY + 10);
   1.452 +  isEval("colSplit.getBoxQuads({box:'content'})[0].bounds.height", 50);
   1.453 +  isEval("colSplit.getBoxQuads({box:'content'})[1].bounds.top", colSplitY - 20);
   1.454 +  isEval("colSplit.getBoxQuads({box:'content'})[1].bounds.height", 30);
   1.455 +
   1.456 +  var inlineSplitX = inlineSplit.getClientRects()[0].left;
   1.457 +  isEval("inlineSplit.getBoxQuads().length", 2);
   1.458 +  isEval("inlineSplit.getBoxQuads()[0].bounds.left", inlineSplitX);
   1.459 +  isEval("inlineSplit.getBoxQuads()[0].bounds.width", 30);
   1.460 +  isEval("inlineSplit.getBoxQuads()[1].bounds.left", inlineSplitX - 150);
   1.461 +  isEval("inlineSplit.getBoxQuads()[1].bounds.width", 75);
   1.462 +  isEval("inlineSplit.getBoxQuads({box:'content'}).length", 2);
   1.463 +  // The first box for the inline has the left border; the second box has the right border.
   1.464 +  isEval("inlineSplit.getBoxQuads({box:'content'})[0].bounds.left", inlineSplitX + 10);
   1.465 +  isEval("inlineSplit.getBoxQuads({box:'content'})[0].bounds.width", 20);
   1.466 +  isEval("inlineSplit.getBoxQuads({box:'content'})[1].bounds.left", inlineSplitX - 150);
   1.467 +  isEval("inlineSplit.getBoxQuads({box:'content'})[1].bounds.width", 60);
   1.468 +
   1.469 +  var textX = textContainer.getClientRects()[0].left;
   1.470 +  isEval("text.getBoxQuads().length", 2);
   1.471 +  isEval("text.getBoxQuads()[0].bounds.left", textX);
   1.472 +  isEval("text.getBoxQuads()[1].bounds.left", textX - 150);
   1.473 +  // Box types are irrelevant for text
   1.474 +  isEval("text.getBoxQuads({box:'content'}).length", 2);
   1.475 +  isEval("text.getBoxQuads({box:'content'})[0].bounds.left", textX);
   1.476 +  isEval("text.getBoxQuads({box:'content'})[1].bounds.left", textX - 150);
   1.477 +  isEval("text.getBoxQuads({box:'padding'}).length", 2);
   1.478 +  isEval("text.getBoxQuads({box:'padding'})[0].bounds.left", textX);
   1.479 +  isEval("text.getBoxQuads({box:'padding'})[1].bounds.left", textX - 150);
   1.480 +  isEval("text.getBoxQuads({box:'margin'}).length", 2);
   1.481 +  isEval("text.getBoxQuads({box:'margin'})[0].bounds.left", textX);
   1.482 +  isEval("text.getBoxQuads({box:'margin'})[1].bounds.left", textX - 150);
   1.483 +
   1.484 +  // Check that a text node whose layout might have been optimized away gives
   1.485 +  // correct results.
   1.486 +  var suppressedTextContainerX = suppressedTextContainer.getBoundingClientRect().left;
   1.487 +  isEval("suppressedText.getBoxQuads().length", 1);
   1.488 +  isEval("suppressedText.getBoxQuads()[0].bounds.left", suppressedTextContainerX);
   1.489 +  isEval("suppressedText.getBoxQuads()[0].bounds.width", 0);
   1.490 +
   1.491 +  var suppressedTextContainer2X = suppressedTextContainer2.getBoundingClientRect().left;
   1.492 +  isEval("document.convertPointFromNode(zeroPoint,suppressedText2).x",
   1.493 +         suppressedTextContainer2X);
   1.494 +
   1.495 +  checkException("comment.getBoxQuads()", "TypeError");
   1.496 +  checkException("d.getBoxQuads({relativeTo:comment})", "TypeError");
   1.497 +  checkException("comment.convertPointFromNode(zeroPoint,document)", "TypeError");
   1.498 +  checkException("document.convertPointFromNode(zeroPoint,comment)", "TypeError");
   1.499 +  checkException("comment.convertRectFromNode(zeroRect,document)", "TypeError");
   1.500 +  checkException("document.convertRectFromNode(zeroRect,comment)", "TypeError");
   1.501 +  checkException("comment.convertQuadFromNode(zeroQuad,document)", "TypeError");
   1.502 +  checkException("document.convertQuadFromNode(zeroQuad,comment)", "TypeError");
   1.503 +
   1.504 +  checkException("fragment.getBoxQuads()", "TypeError");
   1.505 +  checkException("d.getBoxQuads({relativeTo:fragment})", "TypeError");
   1.506 +  checkException("fragment.convertPointFromNode(zeroPoint,document)", "TypeError");
   1.507 +  checkException("document.convertPointFromNode(zeroPoint,fragment)", "TypeError");
   1.508 +  checkException("fragment.convertRectFromNode(zeroRect,document)", "TypeError");
   1.509 +  checkException("document.convertRectFromNode(zeroRect,fragment)", "TypeError");
   1.510 +  checkException("fragment.convertQuadFromNode(zeroQuad,document)", "TypeError");
   1.511 +  checkException("document.convertQuadFromNode(zeroQuad,fragment)", "TypeError");
   1.512 +
   1.513 +  isEval("displayNone.getBoxQuads().length", 0);
   1.514 +  isEval("notInDocument.getBoxQuads().length", 0);
   1.515 +  checkNotFound("displayNone", "document", 1, 2, 3, 4);
   1.516 +  checkNotFound("notInDocument", "document", 1, 2, 3, 4);
   1.517 +  checkNotFound("document", "displayNone", 1, 2, 3, 4);
   1.518 +  checkNotFound("document", "notInDocument", 1, 2, 3, 4);
   1.519 +
   1.520 +  // Test an overflow:hidden version of d. overflow:hidden should not affect
   1.521 +  // the quads, basically.
   1.522 +  var oHX = overflowHidden.getBoundingClientRect().left;
   1.523 +  var oHY = overflowHidden.getBoundingClientRect().top;
   1.524 +  checkQuadIsRect("overflowHidden", {box:"content"},
   1.525 +                  oHX + 4 + 8, oHY + 1 + 5, 120, 90);
   1.526 +  checkQuadIsRect("overflowHidden", {box:"padding"},
   1.527 +                  oHX + 8, oHY + 5, 120 + 2 + 4, 90 + 1 + 3);
   1.528 +  checkQuadIsRect("overflowHidden", {box:"border"},
   1.529 +                  oHX, oHY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
   1.530 +  checkQuadIsRect("overflowHidden", {},
   1.531 +                  oHX, oHY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
   1.532 +  checkQuadIsRect("overflowHidden", {box:"margin"},
   1.533 +                  oHX - 12, oHY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11);
   1.534 +
   1.535 +  // Test an overflow:scroll version of d. I assume that boxes aren't affected
   1.536 +  // by the scrollbar although it's not clear that this is correct.
   1.537 +  var oSX = overflowScroll.getBoundingClientRect().left;
   1.538 +  var oSY = overflowScroll.getBoundingClientRect().top;
   1.539 +  checkQuadIsRect("overflowScroll", {box:"content"},
   1.540 +                  oSX + 4 + 8, oSY + 1 + 5, 120, 90);
   1.541 +  checkQuadIsRect("overflowScroll", {box:"padding"},
   1.542 +                  oSX + 8, oSY + 5, 120 + 2 + 4, 90 + 1 + 3);
   1.543 +  checkQuadIsRect("overflowScroll", {box:"border"},
   1.544 +                  oSX, oSY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
   1.545 +  checkQuadIsRect("overflowScroll", {},
   1.546 +                  oSX, oSY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
   1.547 +  checkQuadIsRect("overflowScroll", {box:"margin"},
   1.548 +                  oSX - 12, oSY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11);
   1.549 +
   1.550 +  // Test simple 2D transforms.
   1.551 +  var stcX = scaleTransformContainer.getBoundingClientRect().left;
   1.552 +  var stcY = scaleTransformContainer.getBoundingClientRect().top;
   1.553 +  checkQuadIsRect("scaleTransform", {},
   1.554 +                  stcX, stcY, 140, 160);
   1.555 +  var ttcX = translateTransformContainer.getBoundingClientRect().left;
   1.556 +  var ttcY = translateTransformContainer.getBoundingClientRect().top;
   1.557 +  checkQuadIsRect("translateTransform", {},
   1.558 +                  ttcX + 30, ttcY + 40, 70, 80);
   1.559 +  // Test mapping into a transformed element.
   1.560 +  checkQuadIsRect("scaleTransform", {toStr:"translateTransform"},
   1.561 +                  stcX - (ttcX + 30), stcY - (ttcY + 40), 140, 160);
   1.562 +  // Test 90 degree rotation.
   1.563 +  var rotatetcX = rotateTransformContainer.getBoundingClientRect().left;
   1.564 +  var rotatetcY = rotateTransformContainer.getBoundingClientRect().top;
   1.565 +  checkQuadIsQuad("rotateTransform", {},
   1.566 +                  rotatetcX + 75, rotatetcY + 5,
   1.567 +                  rotatetcX + 75, rotatetcY + 75,
   1.568 +                  rotatetcX - 5, rotatetcY + 75,
   1.569 +                  rotatetcX - 5, rotatetcY + 5);
   1.570 +  // Test vertical flip.
   1.571 +  var fliptcX = flipTransformContainer.getBoundingClientRect().left;
   1.572 +  var fliptcY = flipTransformContainer.getBoundingClientRect().top;
   1.573 +  checkQuadIsQuad("flipTransform", {},
   1.574 +                  fliptcX, fliptcY + 80,
   1.575 +                  fliptcX + 70, fliptcY + 80,
   1.576 +                  fliptcX + 70, fliptcY,
   1.577 +                  fliptcX, fliptcY);
   1.578 +  // Test non-90deg rotation.
   1.579 +  var rot45tcX = rot45TransformContainer.getBoundingClientRect().left;
   1.580 +  var rot45tcY = rot45TransformContainer.getBoundingClientRect().top;
   1.581 +  var halfDiagonal = 100/Math.sqrt(2);
   1.582 +  checkQuadIsQuad("rot45Transform", {tolerance:0.01},
   1.583 +                  rot45tcX + 50, rot45tcY + 50 - halfDiagonal,
   1.584 +                  rot45tcX + 50 + halfDiagonal, rot45tcY + 50,
   1.585 +                  rot45tcX + 50, rot45tcY + 50 + halfDiagonal,
   1.586 +                  rot45tcX + 50 - halfDiagonal, rot45tcY + 50);
   1.587 +
   1.588 +  // Test singular transforms.
   1.589 +  var singularTransformX = singularTransform.getBoundingClientRect().left;
   1.590 +  var singularTransformY = singularTransform.getBoundingClientRect().top;
   1.591 +  // They map everything to a point.
   1.592 +  checkQuadIsRect("singularTransform", {},
   1.593 +                  singularTransformX, singularTransformY, 0, 0);
   1.594 +  checkQuadIsRect("singularTransformChild2", {},
   1.595 +                  singularTransformX, singularTransformY, 0, 0);
   1.596 +  // Mapping into an element with a singular transform from outside sets
   1.597 +  // everything to zero.
   1.598 +  checkQuadIsRect("d", {toStr:"singularTransform"},
   1.599 +                  0, 0, 0, 0);
   1.600 +  // But mappings within a subtree of an element with a singular transform work.
   1.601 +  checkQuadIsRect("singularTransformChild2", {toStr:"singularTransformChild1"},
   1.602 +                  0, 50, 200, 50);
   1.603 +
   1.604 +  // Test 3D transforms.
   1.605 +  var t3tcX = threeDTransformContainer.getBoundingClientRect().left;
   1.606 +  var t3tcY = threeDTransformContainer.getBoundingClientRect().top;
   1.607 +  checkQuadIsQuad("threeDTransform", {tolerance:0.01},
   1.608 +                  t3tcX + 59.446714, t3tcY - 18.569847,
   1.609 +                  t3tcX + 129.570778, t3tcY + 13.540874,
   1.610 +                  t3tcX + 129.570778, t3tcY + 100,
   1.611 +                  t3tcX + 59.446714, t3tcY + 100);
   1.612 +  // Test nested 3D transforms (without preserve-3d).
   1.613 +  checkQuadIsQuad("threeDTransformChild", {tolerance:0.01},
   1.614 +                  t3tcX + 89.395061, t3tcY + 2.243033,
   1.615 +                  t3tcX + 113.041727, t3tcY - 2.758530,
   1.616 +                  t3tcX + 113.041727, t3tcY + 52.985921,
   1.617 +                  t3tcX + 89.395061, t3tcY + 47.571899);
   1.618 +  // Test preserve-3D.
   1.619 +  var p3dtcX = preserve3DTransformContainer.getBoundingClientRect().left;
   1.620 +  var p3dtcY = preserve3DTransformContainer.getBoundingClientRect().top;
   1.621 +  checkQuadIsRect("preserve3DTransformChild", {tolerance:0.01},
   1.622 +                  p3dtcX, p3dtcY, 200, 50,
   1.623 +                  {tolerance:0.0001});
   1.624 +  // Test mapping back into preserve-3D.
   1.625 +  checkQuadIsRect("d", {toStr:"preserve3DTransformChild",tolerance:0.01},
   1.626 +                  dX - p3dtcX, dY - p3dtcY, dW, dH);
   1.627 +
   1.628 +  // Test SVG.
   1.629 +  var svgContainerX = svgContainer.getBoundingClientRect().left;
   1.630 +  var svgContainerY = svgContainer.getBoundingClientRect().top;
   1.631 +  checkQuadIsRect("circle", {},
   1.632 +                  svgContainerX + 30, svgContainerY + 30, 40, 40);
   1.633 +  // Box types are ignored for SVG elements.
   1.634 +  checkQuadIsRect("circle", {box:"content"},
   1.635 +                  svgContainerX + 30, svgContainerY + 30, 40, 40);
   1.636 +  checkQuadIsRect("circle", {box:"padding"},
   1.637 +                  svgContainerX + 30, svgContainerY + 30, 40, 40);
   1.638 +  checkQuadIsRect("circle", {box:"margin"},
   1.639 +                  svgContainerX + 30, svgContainerY + 30, 40, 40);
   1.640 +  checkQuadIsRect("d", {toStr:"circle"},
   1.641 +                  dX - (svgContainerX + 30), dY - (svgContainerY + 30), dW, dH);
   1.642 +  // Test foreignObject inside an SVG transform.
   1.643 +  checkQuadIsRect("foreign", {},
   1.644 +                  svgContainerX + 100, svgContainerY + 40, 200, 120);
   1.645 +
   1.646 +  // XXX Test SVG text (probably broken; unclear what the best way is to handle it)
   1.647 +
   1.648 +  // Test that converting between nodes in different toplevel browsing contexts
   1.649 +  // throws an exception.
   1.650 +  try {
   1.651 +    openedWindow = window.open("data:text/html,<div id='d'>","");
   1.652 +  } catch (ex) {
   1.653 +    // in some cases we can't open the window.
   1.654 +    openedWindow = null;
   1.655 +  }
   1.656 +  if (openedWindow) {
   1.657 +    openedWindow.addEventListener("load", function() {
   1.658 +      checkException("openedWindow.d.getBoxQuads({relativeTo:document})", "NotFoundError");
   1.659 +      checkException("document.getBoxQuads({relativeTo:openedWindow.d})", "NotFoundError");
   1.660 +      checkException("openedWindow.d.convertPointFromNode(zeroPoint,document)", "NotFoundError");
   1.661 +      checkException("document.convertPointFromNode(zeroPoint,openedWindow.d)", "NotFoundError");
   1.662 +      checkException("openedWindow.d.convertRectFromNode(zeroRect,document)", "NotFoundError");
   1.663 +      checkException("document.convertRectFromNode(zeroRect,openedWindow.d)", "NotFoundError");
   1.664 +      checkException("openedWindow.d.convertQuadFromNode(zeroQuad,document)", "NotFoundError");
   1.665 +      checkException("document.convertQuadFromNode(zeroQuad,openedWindow.d)", "NotFoundError");
   1.666 +      openedWindow.close();
   1.667 +      SimpleTest.finish();
   1.668 +    });
   1.669 +  } else {
   1.670 +    SimpleTest.finish();
   1.671 +  }
   1.672 +}
   1.673 +</script>
   1.674 +</body>
   1.675 +</html>

mercurial