tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_getBoxQuads_convertPointRectQuad.html (33586B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4 <meta charset="utf-8">
      5 <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
      7 </head>
      8 <body onload="startTest()">
      9 <p id="display"></p>
     10 <script>
     11 // Global variables we want eval() to be able to reference from anywhere
     12 var f1d;
     13 var text;
     14 var suppressedText;
     15 var suppressedText2;
     16 var comment;
     17 var fragment;
     18 var openedWindow;
     19 var zeroPoint;
     20 var zeroRect;
     21 var zeroQuad;
     22 var notInDocument = document.createElement('div');
     23 
     24 function isEval(expr, b) {
     25  // we ignore an insignificant discrepancy in floating-point values
     26  var exprVal = eval(expr);
     27  if (exprVal != b && Math.abs(exprVal - b) < 0.0001) {
     28    ok(true, expr + " (" + exprVal + " within 0.0001 of " + b + ")");
     29    return;
     30  }
     31  is(exprVal, b, expr);
     32 }
     33 
     34 function isApprox(a, b, msg, options) {
     35  if (a != b && 'tolerance' in options &&
     36      Math.abs(a - b) < options.tolerance) {
     37    ok(true, msg + "(" + a + " within " + options.tolerance + " of " + b + ")");
     38    return;
     39  }
     40  is(a, b, msg);
     41 }
     42 
     43 function makeQuadsExpr(fromStr, options) {
     44  var getBoxQuadsOptionParts = [];
     45  if ('box' in options) {
     46    getBoxQuadsOptionParts.push("box:'" + options.box + "'");
     47  }
     48  if ('toStr' in options) {
     49    getBoxQuadsOptionParts.push("relativeTo:" + options.toStr);
     50  }
     51  return fromStr + ".getBoxQuads({" + getBoxQuadsOptionParts.join(',') + "})";
     52 }
     53 
     54 function makePointExpr(fromStr, options, x, y) {
     55  var convertPointOptionParts = [];
     56  if ('box' in options) {
     57    convertPointOptionParts.push("fromBox:'" + options.box + "'");
     58  }
     59  if ('toBox' in options) {
     60    convertPointOptionParts.push("toBox:'" + options.toBox + "'");
     61  }
     62  return ('toStr' in options ? options.toStr : "document") +
     63    ".convertPointFromNode(new DOMPoint(" + x + "," + y + ")," + fromStr + ",{" +
     64    convertPointOptionParts.join(",") + "})";
     65 }
     66 
     67 function checkConvertPoints(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
     68  var selfQuads = eval(fromStr).getBoxQuads(
     69    {box:options.box == "" ? "border" : options.box,
     70     relativeTo:eval(fromStr)});
     71  var boxWidth = selfQuads[0].getBounds().width;
     72  var boxHeight = selfQuads[0].getBounds().height;
     73 
     74  var convertTopLeftPointExpr = makePointExpr(fromStr, options, 0, 0);
     75  var topLeft = eval(convertTopLeftPointExpr);
     76  isApprox(topLeft.x, x1, convertTopLeftPointExpr + ".x", options);
     77  isApprox(topLeft.y, y1, convertTopLeftPointExpr + ".y", options);
     78 
     79  var convertTopRightPointExpr = makePointExpr(fromStr, options, boxWidth, 0);
     80  var topRight = eval(convertTopRightPointExpr);
     81  isApprox(topRight.x, x2, convertTopRightPointExpr + ".x", options);
     82  isApprox(topRight.y, y2, convertTopRightPointExpr + ".y", options);
     83 
     84  var convertBottomRightPointExpr = makePointExpr(fromStr, options, boxWidth, boxHeight);
     85  var bottomRight = eval(convertBottomRightPointExpr);
     86  isApprox(bottomRight.x, x3, convertBottomRightPointExpr + ".x", options);
     87  isApprox(bottomRight.y, y3, convertBottomRightPointExpr + ".y", options);
     88 
     89  var convertBottomLeftPointExpr = makePointExpr(fromStr, options, 0, boxHeight);
     90  var bottomLeft = eval(convertBottomLeftPointExpr);
     91  isApprox(bottomLeft.x, x4, convertBottomLeftPointExpr + ".x", options);
     92  isApprox(bottomLeft.y, y4, convertBottomLeftPointExpr + ".y", options);
     93 }
     94 
     95 function checkConvertRect(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
     96  var selfQuads = eval(fromStr).getBoxQuads(
     97    {box:options.box == "" ? "border" : options.box,
     98     relativeTo:eval(fromStr)});
     99  var boxWidth = selfQuads[0].getBounds().width;
    100  var boxHeight = selfQuads[0].getBounds().height;
    101 
    102  var convertPointOptionParts = [];
    103  if ('box' in options) {
    104    convertPointOptionParts.push("fromBox:'" + options.box + "'");
    105  }
    106  if ('toBox' in options) {
    107    convertPointOptionParts.push("toBox:'" + options.toBox + "'");
    108  }
    109 
    110  var convertRectExpr = ('toStr' in options ? options.toStr : "document") +
    111    ".convertRectFromNode(new DOMRect(0,0," + boxWidth + "," + boxHeight + ")," +
    112    fromStr + ",{" + convertPointOptionParts.join(",") + "})";
    113  var quad = eval(convertRectExpr);
    114  isApprox(quad.p1.x, x1, convertRectExpr + ".p1.x", options);
    115  isApprox(quad.p1.y, y1, convertRectExpr + ".p1.y", options);
    116  isApprox(quad.p2.x, x2, convertRectExpr + ".p2.x", options);
    117  isApprox(quad.p2.y, y2, convertRectExpr + ".p2.y", options);
    118  isApprox(quad.p3.x, x3, convertRectExpr + ".p3.x", options);
    119  isApprox(quad.p3.y, y3, convertRectExpr + ".p3.y", options);
    120  isApprox(quad.p4.x, x4, convertRectExpr + ".p4.x", options);
    121  isApprox(quad.p4.y, y4, convertRectExpr + ".p4.y", options);
    122 }
    123 
    124 function checkConvertQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
    125  var selfQuads = eval(fromStr).getBoxQuads(
    126    {box:options.box == "" ? "border" : options.box,
    127     relativeTo:eval(fromStr)});
    128  var boxWidth = selfQuads[0].getBounds().width;
    129  var boxHeight = selfQuads[0].getBounds().height;
    130 
    131  var convertPointOptionParts = [];
    132  if ('box' in options) {
    133    convertPointOptionParts.push("fromBox:'" + options.box + "'");
    134  }
    135  if ('toBox' in options) {
    136    convertPointOptionParts.push("toBox:'" + options.toBox + "'");
    137  }
    138 
    139  var convertQuadExpr = ('toStr' in options ? options.toStr : "document") +
    140    ".convertQuadFromNode(new DOMQuad(new DOMRect(0,0," + boxWidth + "," + boxHeight + "))," +
    141    fromStr + ",{" + convertPointOptionParts.join(",") + "})";
    142  var quad = eval(convertQuadExpr);
    143  isApprox(quad.p1.x, x1, convertQuadExpr + ".p1.x", options);
    144  isApprox(quad.p1.y, y1, convertQuadExpr + ".p1.y", options);
    145  isApprox(quad.p2.x, x2, convertQuadExpr + ".p2.x", options);
    146  isApprox(quad.p2.y, y2, convertQuadExpr + ".p2.y", options);
    147  isApprox(quad.p3.x, x3, convertQuadExpr + ".p3.x", options);
    148  isApprox(quad.p3.y, y3, convertQuadExpr + ".p3.y", options);
    149  isApprox(quad.p4.x, x4, convertQuadExpr + ".p4.x", options);
    150  isApprox(quad.p4.y, y4, convertQuadExpr + ".p4.y", options);
    151 }
    152 
    153 function checkQuadIsRect(fromStr, options, x, y, w, h) {
    154  var quadsExpr = makeQuadsExpr(fromStr, options);
    155  var quads = eval(quadsExpr);
    156  is(quads.length, 1, quadsExpr + " checking quad count");
    157  var q = quads[0];
    158  isApprox(q.p1.x, x, quadsExpr + " checking quad.p1.x", options);
    159  isApprox(q.p1.y, y, quadsExpr + " checking quad.p1.y", options);
    160  isApprox(q.p2.x, x + w, quadsExpr + " checking quad.p2.x", options);
    161  isApprox(q.p2.y, y, quadsExpr + " checking quad.p2.y", options);
    162  isApprox(q.p3.x, x + w, quadsExpr + " checking quad.p3.x", options);
    163  isApprox(q.p3.y, y + h, quadsExpr + " checking quad.p3.y", options);
    164  isApprox(q.p4.x, x, quadsExpr + " checking quad.p4.x", options);
    165  isApprox(q.p4.y, y + h, quadsExpr + " checking quad.p4.y", options);
    166 
    167  isApprox(q.getBounds().left, x, quadsExpr + " checking quad.getBounds().left", options);
    168  isApprox(q.getBounds().top, y, quadsExpr + " checking quad.getBounds().top", options);
    169  isApprox(q.getBounds().width, w, quadsExpr + " checking quad.getBounds().width", options);
    170  isApprox(q.getBounds().height, h, quadsExpr + " checking quad.getBounds().height", options);
    171 
    172  checkConvertPoints(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h);
    173  checkConvertRect(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h);
    174  checkConvertQuad(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h);
    175 }
    176 
    177 function checkQuadIsQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
    178  var quadsExpr = makeQuadsExpr(fromStr, options);
    179  var quads = eval(quadsExpr);
    180  is(quads.length, 1, quadsExpr + " checking quad count");
    181  var q = quads[0];
    182  isApprox(q.p1.x, x1, quadsExpr + " checking quad.p1.x", options);
    183  isApprox(q.p1.y, y1, quadsExpr + " checking quad.p1.y", options);
    184  isApprox(q.p2.x, x2, quadsExpr + " checking quad.p2.x", options);
    185  isApprox(q.p2.y, y2, quadsExpr + " checking quad.p2.y", options);
    186  isApprox(q.p3.x, x3, quadsExpr + " checking quad.p3.x", options);
    187  isApprox(q.p3.y, y3, quadsExpr + " checking quad.p3.y", options);
    188  isApprox(q.p4.x, x4, quadsExpr + " checking quad.p4.x", options);
    189  isApprox(q.p4.y, y4, quadsExpr + " checking quad.p4.y", options);
    190 
    191  isApprox(q.getBounds().left, Math.min(x1,x2,x3,x4), quadsExpr + " checking quad.getBounds().left", options);
    192  isApprox(q.getBounds().top, Math.min(y1,y2,y3,y4), quadsExpr + " checking quad.getBounds().top", options);
    193  isApprox(q.getBounds().right, Math.max(x1,x2,x3,x4), quadsExpr + " checking quad.getBounds().right", options);
    194  isApprox(q.getBounds().bottom, Math.max(y1,y2,y3,y4), quadsExpr + " checking quad.getBounds().bottom", options);
    195 
    196  checkConvertPoints(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4);
    197  checkConvertRect(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4);
    198  checkConvertQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4);
    199 }
    200 
    201 function checkException(expr, name) {
    202  try {
    203    eval(expr);
    204    ok(false, "Exception should have been thrown for " + expr);
    205  } catch (ex) {
    206    is(ex.name, name, "Checking exception type for " + expr);
    207  }
    208 }
    209 
    210 function checkNotFound(fromStr, toStr, x1, y1, x2, y2) {
    211  var convertPointExpr = toStr + ".convertPointFromNode(new DOMPoint(" + x1 +
    212    "," + y1 + ")," + fromStr + ")";
    213  checkException(convertPointExpr, "NotFoundError");
    214 
    215  var convertRectExpr = toStr + ".convertRectFromNode(new DOMRect(" + x1 +
    216    "," + y1 + "," + x2 + "," + y2 + ")," + fromStr + ")";
    217  checkException(convertRectExpr, "NotFoundError");
    218 
    219  var convertQuadExpr = toStr + ".convertQuadFromNode(new DOMQuad(new DOMRect(" + x1 +
    220    "," + y1 + "," + x2 + "," + y2 + "))," + fromStr + ")";
    221  checkException(convertQuadExpr, "NotFoundError");
    222 }
    223 </script>
    224 <style>
    225 em {
    226  display:inline-block; height:10px; background:gray;
    227 }
    228 </style>
    229 <div id="dContainer"
    230     style="padding:13px 14px 15px 16px;
    231            border-width:17px 18px 19px 20px; border-style:solid; border-color:yellow;
    232            margin:21px 22px 23px 24px;">
    233  <div id="d"
    234       style="width:120px; height:90px; padding:1px 2px 3px 4px;
    235              border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow;
    236              margin:9px 10px 11px 12px; background:blue;">
    237  </div>
    238 </div>
    239 
    240 <div id="dUnrelated" style="width:50px; height:50px;"></div>
    241 
    242 <iframe id="f1" style="width:50px; height:50px; border:0; background:lime;"
    243        src="file_getBoxQuads_convertPointRectQuad_frame1.html">
    244 </iframe>
    245 <!--
    246 It matters that the first part of this span is on the same line as the above <iframe>!
    247 That ensures the first quad's X position is not equal to the anonymous block's X position.
    248 -->
    249 <span id="ibSplit"
    250  ><em id="ibSplitPart1" style="width:100px;"></em
    251  ><div style="width:110px; height:20px; background:black"></div
    252  ><em style="width:130px;"></em></span>
    253 
    254 <table cellspacing="0" id="table" style="border:0; margin:8px; padding:0; background:orange">
    255  <tbody style="padding:0; margin:0; border:0; background:blue">
    256    <tr style="height:50px; padding:0; margin:0; border:0">
    257      <td style="border:0; margin:0; padding:0">Cell</td>
    258    </tr>
    259  </tbody>
    260  <caption style="height:40px; background:yellow">Caption</caption>
    261 </table>
    262 
    263 <div style="height:80px; column-count:2; column-fill:auto; border:2px solid black;">
    264  <div style="height:20px;"></div>
    265  <div id="colSplit" style="height:80px; background:blue; border:10px solid red; border-bottom-width:15px"></div>
    266 </div>
    267 
    268 <div style="width:200px; border:2px solid black;"
    269  ><em style="width:150px;"></em
    270  ><span id="inlineSplit" style="background:pink; border:10px solid red; border-right-width:15px"
    271    ><em style="width:20px; background:green"></em><em style="width:60px"></em
    272  ></span
    273 ></div>
    274 
    275 <div style="width:200px; border:2px solid black;"
    276  ><em style="width:150px;"></em
    277  ><span id="textContainer">T
    278 TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText</span
    279 ></div>
    280 
    281 <div id="suppressedTextContainer"> </div>
    282 <div id="suppressedTextContainer2"> </div>
    283 
    284 <div id="commentContainer"><!-- COMMENT --></div>
    285 
    286 <div id="displayNone" style="display:none"></div>
    287 
    288 <div id="overflowHidden"
    289     style="overflow:hidden; width:120px; height:90px; padding:1px 2px 3px 4px;
    290            border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow;
    291            margin:9px 10px 11px 12px; background:blue;">
    292  <div style="height:400px; background:lime;"></div>
    293 </div>
    294 
    295 <div id="overflowScroll"
    296     style="overflow:scroll; width:120px; height:90px; padding:1px 2px 3px 4px;
    297            border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow;
    298            margin:9px 10px 11px 12px; background:blue; background-clip:content-box;">
    299  <div id="overflowScrollChild" style="height:400px;"></div>
    300 </div>
    301 
    302 <div id="scaleTransformContainer" style="width:200px; height:200px;">
    303  <div id="scaleTransform"
    304       style="transform:scale(2); transform-origin:top left; width:70px; height:80px; background:yellow"></div>
    305 </div>
    306 
    307 <div id="translateTransformContainer" style="width:200px; height:200px;">
    308  <div id="translateTransform"
    309       style="transform:translate(30px,40px); width:70px; height:80px; background:yellow"></div>
    310 </div>
    311 
    312 <div id="rotateTransformContainer" style="width:200px; height:200px;">
    313  <div id="rotateTransform"
    314       style="transform:rotate(90deg); width:70px; height:80px; background:yellow"></div>
    315 </div>
    316 
    317 <div id="flipTransformContainer" style="width:200px; height:200px;">
    318  <div id="flipTransform"
    319       style="transform:scaleY(-1); width:70px; height:80px; background:yellow"></div>
    320 </div>
    321 
    322 <div id="rot45TransformContainer" style="width:200px; height:200px;">
    323  <div id="rot45Transform"
    324       style="transform:rotate(45deg); width:100px; height:100px; background:yellow"></div>
    325 </div>
    326 
    327 <div id="singularTransform" style="transform:scale(0); width:200px; height:200px;">
    328  <div id="singularTransformChild1" style="height:50px;"></div>
    329  <div id="singularTransformChild2" style="height:50px;"></div>
    330 </div>
    331 
    332 <div id="threeDTransformContainer" style="perspective:600px; width:200px; height:200px">
    333  <div id="threeDTransform" style="transform:rotateY(70deg); background:yellow; height:100px; perspective:600px">
    334    <div id="threeDTransformChild" style="transform:rotateY(-70deg); background:blue; height:50px;"></div>
    335  </div>
    336 </div>
    337 
    338 <div id="preserve3DTransformContainer" style="perspective:600px; width:200px; height:200px">
    339  <div id="preserve3DTransform" style="transform:rotateY(70deg); transform-style:preserve-3d; background:yellow; height:100px;">
    340    <div id="preserve3DTransformChild" style="transform:rotateY(-70deg); background:blue; height:50px;"></div>
    341  </div>
    342 </div>
    343 
    344 <div id="svgContainer">
    345  <svg id="svg" style="width:200px; height:200px; background:lightgray; border:7px solid blue; padding:4px">
    346    <circle id="circle" cx="50" cy="50" r="20" fill="red" style="margin:20px; padding:10px; border:15px solid black"></circle>
    347    <g transform="scale(2)">
    348      <foreignObject x="50" y="20">
    349        <div id="foreign" style="width:100px; height:60px; background:purple"></div>
    350      </foreignObject>
    351    </g>
    352  </svg>
    353 </div>
    354 
    355 <script>
    356 SimpleTest.waitForExplicitFinish();
    357 
    358 window.scrollTo(0,0);
    359 
    360 function startTest() {
    361  SpecialPowers.pushPrefEnv({"set": [["layout.css.getBoxQuads.enabled", true],
    362                                     ["layout.css.convertFromNode.enabled", true]]}, grabFeatures);
    363 }
    364 
    365 // This is a bit of a hack but it works. Our Window object was set up while
    366 // the prefs might have been false so it may not have the features we're
    367 // testing. Create an <iframe> whose Window is initialized while the prefs are
    368 // true, and we can steal the features from that Window.
    369 // When these prefs are enabled on all builds by default, we can skip this step.
    370 function grabFeatures() {
    371  var x = document.createElement('iframe');
    372  x.src = "about:blank";
    373  function setupFeatures(w) {
    374    for (var name of ["getBoxQuads", "convertQuadFromNode", "convertRectFromNode", "convertPointFromNode"]) {
    375      w.Text.prototype[name] = x.contentWindow.Text.prototype[name];
    376      w.Element.prototype[name] = x.contentWindow.Element.prototype[name];
    377      w.Document.prototype[name] = x.contentWindow.Document.prototype[name];
    378    }
    379    for (var name of ["DOMPoint", "DOMQuad"]) {
    380      w[name] = x.contentWindow[name];
    381    }
    382  }
    383  x.onload = function() {
    384    setupFeatures(window);
    385    setupFeatures(f1.contentWindow);
    386    runTest();
    387  };
    388  document.body.appendChild(x);
    389 }
    390 
    391 function runTest() {
    392  zeroPoint = new DOMPoint(0,0);
    393  zeroRect = new DOMRect(0,0,0,0);
    394  zeroQuad = new DOMQuad(zeroRect);
    395 
    396  // Setup globals
    397  f1d = f1.contentWindow.f1d;
    398  text = textContainer.firstChild;
    399  suppressedText = suppressedTextContainer.firstChild;
    400  suppressedText2 = suppressedTextContainer2.firstChild;
    401  comment = commentContainer.firstChild;
    402  fragment = document.createDocumentFragment();
    403 
    404  // Test basic BoxQuadOptions.box.
    405  var dX = d.getBoundingClientRect().left;
    406  var dY = d.getBoundingClientRect().top;
    407  var dW = d.getBoundingClientRect().width;
    408  var dH = d.getBoundingClientRect().height;
    409 
    410  checkQuadIsRect("d", {box:"content"},
    411                  dX + 4 + 8, dY + 1 + 5, 120, 90);
    412  checkQuadIsRect("d", {box:"padding"},
    413                  dX + 8, dY + 5, 120 + 2 + 4, 90 + 1 + 3);
    414  checkQuadIsRect("d", {box:"border"},
    415                  dX, dY, dW, dH);
    416  checkQuadIsRect("d", {},
    417                  dX, dY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
    418  checkQuadIsRect("d", {box:"margin"},
    419                  dX - 12, dY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11);
    420 
    421  // Test basic BoxQuadOptions.relativeTo
    422  checkQuadIsRect("d", {toStr:"dContainer"},
    423                  12 + 16 + 20, 9 + 13 + 17, dW, dH);
    424 
    425  // Test BoxQuadOptions.relativeTo relative to this document          
    426  checkQuadIsRect("d", {toStr:"document"},
    427                  dX, dY, dW, dH);
    428  // Test BoxQuadOptions.relativeTo relative to a non-ancestor.             
    429  var dUnrelatedX = dUnrelated.getBoundingClientRect().left;
    430  var dUnrelatedY = dUnrelated.getBoundingClientRect().top;
    431  checkQuadIsRect("d", {toStr:"dUnrelated"},
    432                  dX - dUnrelatedX, dY - dUnrelatedY, dW, dH);
    433  // Test BoxQuadOptions.relativeTo relative to an element in a different document (and the document)
    434  var f1X = f1.getBoundingClientRect().left;
    435  var f1Y = f1.getBoundingClientRect().top;
    436  checkQuadIsRect("d", {toStr:"f1.contentWindow.f1d"},
    437                  dX - (f1X + 14), dY - (f1Y + 15), dW, dH);
    438  checkQuadIsRect("d", {toStr:"f1.contentDocument"},
    439                  dX - f1X, dY - f1Y, dW, dH);
    440  // Test one document relative to another
    441  checkQuadIsRect("f1.contentDocument", {toStr:"document"},
    442                  f1X, f1Y, 50, 50);
    443  // The box type is irrelevant for a document
    444  checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"content"},
    445                  f1X, f1Y, 50, 50);
    446  checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"margin"},
    447                  f1X, f1Y, 50, 50);
    448  checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"padding"},
    449                  f1X, f1Y, 50, 50);
    450 
    451  // Test that anonymous boxes are correctly ignored when building quads.
    452  var ibSplitPart1X = ibSplitPart1.getBoundingClientRect().left;
    453  var ibSplitY = ibSplit.getBoundingClientRect().top;
    454  isEval("ibSplit.getBoxQuads().length", 3);
    455  isEval("ibSplit.getBoxQuads()[0].getBounds().left", ibSplitPart1X);
    456  isEval("ibSplit.getBoxQuads()[0].getBounds().width", 100);
    457  isEval("ibSplit.getBoxQuads()[1].getBounds().width", 110);
    458  isEval("ibSplit.getBoxQuads()[2].getBounds().width", 130);
    459  isEval("table.getBoxQuads().length", 2);
    460  isEval("table.getBoxQuads()[0].getBounds().height", 50);
    461  isEval("table.getBoxQuads()[1].getBounds().height", 40);
    462 
    463  // Test that we skip anonymous boxes when finding the right box to be relative to.
    464  checkQuadIsRect("d", {toStr:"ibSplit", tolerance:0.0001},
    465                  dX - ibSplitPart1X, dY - ibSplitY, dW, dH);
    466  var tableX = table.getClientRects()[0].left;
    467  var tableY = table.getClientRects()[0].top;
    468  checkQuadIsRect("d", {toStr:"table"},
    469                  dX - tableX, dY - tableY, dW, dH);
    470  isEval("ibSplit.convertPointFromNode(zeroPoint,d).x", dX - ibSplitPart1X);
    471  isEval("table.convertPointFromNode(zeroPoint,d).x", dX - table.getClientRects()[0].left);
    472 
    473  // Test boxes generated by block splitting. Check for borders being placed correctly.
    474  var colSplitY = colSplit.getClientRects()[0].top;
    475  isEval("colSplit.getBoxQuads().length", 2);
    476  isEval("colSplit.getBoxQuads()[0].getBounds().top", colSplitY);
    477  isEval("colSplit.getBoxQuads()[0].getBounds().height", 60);
    478  isEval("colSplit.getBoxQuads()[1].getBounds().top", colSplitY - 20);
    479  isEval("colSplit.getBoxQuads()[1].getBounds().height", 45);
    480  isEval("colSplit.getBoxQuads({box:'content'}).length", 2);
    481  // The first box for the block has the top border; the second box has the bottom border.
    482  isEval("colSplit.getBoxQuads({box:'content'})[0].getBounds().top", colSplitY + 10);
    483  isEval("colSplit.getBoxQuads({box:'content'})[0].getBounds().height", 50);
    484  isEval("colSplit.getBoxQuads({box:'content'})[1].getBounds().top", colSplitY - 20);
    485  isEval("colSplit.getBoxQuads({box:'content'})[1].getBounds().height", 30);
    486 
    487  var inlineSplitX = inlineSplit.getClientRects()[0].left;
    488  isEval("inlineSplit.getBoxQuads().length", 2);
    489  isEval("inlineSplit.getBoxQuads()[0].getBounds().left", inlineSplitX);
    490  isEval("inlineSplit.getBoxQuads()[0].getBounds().width", 30);
    491  isEval("inlineSplit.getBoxQuads()[1].getBounds().left", inlineSplitX - 150);
    492  isEval("inlineSplit.getBoxQuads()[1].getBounds().width", 75);
    493  isEval("inlineSplit.getBoxQuads({box:'content'}).length", 2);
    494  // The first box for the inline has the left border; the second box has the right border.
    495  isEval("inlineSplit.getBoxQuads({box:'content'})[0].getBounds().left", inlineSplitX + 10);
    496  isEval("inlineSplit.getBoxQuads({box:'content'})[0].getBounds().width", 20);
    497  isEval("inlineSplit.getBoxQuads({box:'content'})[1].getBounds().left", inlineSplitX - 150);
    498  isEval("inlineSplit.getBoxQuads({box:'content'})[1].getBounds().width", 60);
    499 
    500  var textX = textContainer.getClientRects()[0].left;
    501  isEval("text.getBoxQuads().length", 2);
    502  isEval("text.getBoxQuads()[0].getBounds().left", textX);
    503  isEval("text.getBoxQuads()[1].getBounds().left", textX - 150);
    504  // Box types are irrelevant for text
    505  isEval("text.getBoxQuads({box:'content'}).length", 2);
    506  isEval("text.getBoxQuads({box:'content'})[0].getBounds().left", textX);
    507  isEval("text.getBoxQuads({box:'content'})[1].getBounds().left", textX - 150);
    508  isEval("text.getBoxQuads({box:'padding'}).length", 2);
    509  isEval("text.getBoxQuads({box:'padding'})[0].getBounds().left", textX);
    510  isEval("text.getBoxQuads({box:'padding'})[1].getBounds().left", textX - 150);
    511  isEval("text.getBoxQuads({box:'margin'}).length", 2);
    512  isEval("text.getBoxQuads({box:'margin'})[0].getBounds().left", textX);
    513  isEval("text.getBoxQuads({box:'margin'})[1].getBounds().left", textX - 150);
    514 
    515  // Test table margins
    516  isEval("table.getBoxQuads({box:'margin'}).length", 1);
    517  isEval("table.getBoxQuads({box:'margin'})[0].getBounds().height", 106);
    518 
    519  // Check that a text node whose layout might have been optimized away gives
    520  // correct results.
    521  var suppressedTextContainerX = suppressedTextContainer.getBoundingClientRect().left;
    522  isEval("suppressedText.getBoxQuads().length", 1);
    523  isEval("suppressedText.getBoxQuads()[0].getBounds().left", suppressedTextContainerX);
    524  isEval("suppressedText.getBoxQuads()[0].getBounds().width", 0);
    525 
    526  var suppressedTextContainer2X = suppressedTextContainer2.getBoundingClientRect().left;
    527  isEval("document.convertPointFromNode(zeroPoint,suppressedText2).x",
    528         suppressedTextContainer2X);
    529 
    530  checkException("comment.getBoxQuads()", "TypeError");
    531  checkException("d.getBoxQuads({relativeTo:comment})", "TypeError");
    532  checkException("comment.convertPointFromNode(zeroPoint,document)", "TypeError");
    533  checkException("document.convertPointFromNode(zeroPoint,comment)", "TypeError");
    534  checkException("comment.convertRectFromNode(zeroRect,document)", "TypeError");
    535  checkException("document.convertRectFromNode(zeroRect,comment)", "TypeError");
    536  checkException("comment.convertQuadFromNode(zeroQuad,document)", "TypeError");
    537  checkException("document.convertQuadFromNode(zeroQuad,comment)", "TypeError");
    538 
    539  checkException("fragment.getBoxQuads()", "TypeError");
    540  checkException("d.getBoxQuads({relativeTo:fragment})", "TypeError");
    541  checkException("fragment.convertPointFromNode(zeroPoint,document)", "TypeError");
    542  checkException("document.convertPointFromNode(zeroPoint,fragment)", "TypeError");
    543  checkException("fragment.convertRectFromNode(zeroRect,document)", "TypeError");
    544  checkException("document.convertRectFromNode(zeroRect,fragment)", "TypeError");
    545  checkException("fragment.convertQuadFromNode(zeroQuad,document)", "TypeError");
    546  checkException("document.convertQuadFromNode(zeroQuad,fragment)", "TypeError");
    547 
    548  isEval("displayNone.getBoxQuads().length", 0);
    549  isEval("notInDocument.getBoxQuads().length", 0);
    550  checkNotFound("displayNone", "document", 1, 2, 3, 4);
    551  checkNotFound("notInDocument", "document", 1, 2, 3, 4);
    552  checkNotFound("document", "displayNone", 1, 2, 3, 4);
    553  checkNotFound("document", "notInDocument", 1, 2, 3, 4);
    554 
    555  // Test an overflow:hidden version of d. overflow:hidden should not affect
    556  // the quads, basically.
    557  var oHX = overflowHidden.getBoundingClientRect().left;
    558  var oHY = overflowHidden.getBoundingClientRect().top;
    559  checkQuadIsRect("overflowHidden", {box:"content"},
    560                  oHX + 4 + 8, oHY + 1 + 5, 120, 90);
    561  checkQuadIsRect("overflowHidden", {box:"padding"},
    562                  oHX + 8, oHY + 5, 120 + 2 + 4, 90 + 1 + 3);
    563  checkQuadIsRect("overflowHidden", {box:"border"},
    564                  oHX, oHY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
    565  checkQuadIsRect("overflowHidden", {},
    566                  oHX, oHY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
    567  checkQuadIsRect("overflowHidden", {box:"margin"},
    568                  oHX - 12, oHY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11);
    569 
    570  // Test an overflow:scroll version of d. I assume that boxes aren't affected
    571  // by the scrollbar although it's not clear that this is correct.
    572  var oSX = overflowScroll.getBoundingClientRect().left;
    573  var oSY = overflowScroll.getBoundingClientRect().top;
    574  checkQuadIsRect("overflowScroll", {box:"content"},
    575                  oSX + 4 + 8, oSY + 1 + 5, 120, 90);
    576  checkQuadIsRect("overflowScroll", {box:"padding"},
    577                  oSX + 8, oSY + 5, 120 + 2 + 4, 90 + 1 + 3);
    578  checkQuadIsRect("overflowScroll", {box:"border"},
    579                  oSX, oSY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
    580  checkQuadIsRect("overflowScroll", {},
    581                  oSX, oSY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
    582  checkQuadIsRect("overflowScroll", {box:"margin"},
    583                  oSX - 12, oSY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11);
    584 
    585  // Test simple 2D transforms.
    586  var stcX = scaleTransformContainer.getBoundingClientRect().left;
    587  var stcY = scaleTransformContainer.getBoundingClientRect().top;
    588  checkQuadIsRect("scaleTransform", {},
    589                  stcX, stcY, 140, 160);
    590  var ttcX = translateTransformContainer.getBoundingClientRect().left;
    591  var ttcY = translateTransformContainer.getBoundingClientRect().top;
    592  checkQuadIsRect("translateTransform", {},
    593                  ttcX + 30, ttcY + 40, 70, 80);
    594  // Test mapping into a transformed element.
    595  checkQuadIsRect("scaleTransform", {toStr:"translateTransform"},
    596                  stcX - (ttcX + 30), stcY - (ttcY + 40), 140, 160);
    597  // Test 90 degree rotation.
    598  var rotatetcX = rotateTransformContainer.getBoundingClientRect().left;
    599  var rotatetcY = rotateTransformContainer.getBoundingClientRect().top;
    600  checkQuadIsQuad("rotateTransform", {},
    601                  rotatetcX + 75, rotatetcY + 5,
    602                  rotatetcX + 75, rotatetcY + 75,
    603                  rotatetcX - 5, rotatetcY + 75,
    604                  rotatetcX - 5, rotatetcY + 5);
    605  // Test vertical flip.
    606  var fliptcX = flipTransformContainer.getBoundingClientRect().left;
    607  var fliptcY = flipTransformContainer.getBoundingClientRect().top;
    608  checkQuadIsQuad("flipTransform", {},
    609                  fliptcX, fliptcY + 80,
    610                  fliptcX + 70, fliptcY + 80,
    611                  fliptcX + 70, fliptcY,
    612                  fliptcX, fliptcY);
    613  // Test non-90deg rotation.
    614  var rot45tcX = rot45TransformContainer.getBoundingClientRect().left;
    615  var rot45tcY = rot45TransformContainer.getBoundingClientRect().top;
    616  var halfDiagonal = 100/Math.sqrt(2);
    617  checkQuadIsQuad("rot45Transform", {tolerance:0.01},
    618                  rot45tcX + 50, rot45tcY + 50 - halfDiagonal,
    619                  rot45tcX + 50 + halfDiagonal, rot45tcY + 50,
    620                  rot45tcX + 50, rot45tcY + 50 + halfDiagonal,
    621                  rot45tcX + 50 - halfDiagonal, rot45tcY + 50);
    622 
    623  // Test singular transforms.
    624  var singularTransformX = singularTransform.getBoundingClientRect().left;
    625  var singularTransformY = singularTransform.getBoundingClientRect().top;
    626  // They map everything to a point.
    627  checkQuadIsRect("singularTransform", {},
    628                  singularTransformX, singularTransformY, 0, 0);
    629  checkQuadIsRect("singularTransformChild2", {},
    630                  singularTransformX, singularTransformY, 0, 0);
    631  // Mapping into an element with a singular transform from outside sets
    632  // everything to zero.
    633  checkQuadIsRect("d", {toStr:"singularTransform"},
    634                  0, 0, 0, 0);
    635  // But mappings within a subtree of an element with a singular transform work.
    636  checkQuadIsRect("singularTransformChild2", {toStr:"singularTransformChild1"},
    637                  0, 50, 200, 50);
    638 
    639  // Test 3D transforms.
    640  var t3tcX = threeDTransformContainer.getBoundingClientRect().left;
    641  var t3tcY = threeDTransformContainer.getBoundingClientRect().top;
    642  checkQuadIsQuad("threeDTransform", {tolerance:0.01},
    643                  t3tcX + 59.446714, t3tcY - 18.569847,
    644                  t3tcX + 129.570778, t3tcY + 13.540874,
    645                  t3tcX + 129.570778, t3tcY + 100,
    646                  t3tcX + 59.446714, t3tcY + 100);
    647  // Test nested 3D transforms (without preserve-3d).
    648  checkQuadIsQuad("threeDTransformChild", {tolerance:0.01},
    649                  t3tcX + 89.395061, t3tcY + 2.243033,
    650                  t3tcX + 113.041727, t3tcY - 2.758530,
    651                  t3tcX + 113.041727, t3tcY + 52.985921,
    652                  t3tcX + 89.395061, t3tcY + 47.571899);
    653  // Test preserve-3D.
    654  var p3dtcX = preserve3DTransformContainer.getBoundingClientRect().left;
    655  var p3dtcY = preserve3DTransformContainer.getBoundingClientRect().top;
    656  checkQuadIsRect("preserve3DTransformChild", {tolerance:0.01},
    657                  p3dtcX, p3dtcY, 200, 50,
    658                  {tolerance:0.0001});
    659  // Test mapping back into preserve-3D.
    660  checkQuadIsRect("d", {toStr:"preserve3DTransformChild",tolerance:0.01},
    661                  dX - p3dtcX, dY - p3dtcY, dW, dH);
    662 
    663  // Test SVG.
    664  var svgContainerX = svgContainer.getBoundingClientRect().left;
    665  var svgContainerY = svgContainer.getBoundingClientRect().top;
    666  checkQuadIsRect("circle", {},
    667                  svgContainerX + 41, svgContainerY + 41, 40, 40);
    668  // Box types are ignored for SVG elements.
    669  checkQuadIsRect("circle", {box:"content"},
    670                  svgContainerX + 41, svgContainerY + 41, 40, 40);
    671  checkQuadIsRect("circle", {box:"padding"},
    672                  svgContainerX + 41, svgContainerY + 41, 40, 40);
    673  checkQuadIsRect("circle", {box:"margin"},
    674                  svgContainerX + 41, svgContainerY + 41, 40, 40);
    675  checkQuadIsRect("d", {toStr:"circle"},
    676                  dX - (svgContainerX + 41), dY - (svgContainerY + 41), dW, dH);
    677  // Test foreignObject inside an SVG transform.
    678  checkQuadIsRect("foreign", {},
    679                  svgContainerX + 111, svgContainerY + 51, 200, 120);
    680  // Outer <svg> elements support padding and content boxes
    681  checkQuadIsRect("svg", {box:"border"},
    682                  svgContainerX, svgContainerY, 222, 222);
    683  checkQuadIsRect("svg", {box:"padding"},
    684                  svgContainerX + 7, svgContainerY + 7, 208, 208);
    685  checkQuadIsRect("svg", {box:"content"},
    686                  svgContainerX + 11, svgContainerY + 11, 200, 200);
    687 
    688  // XXX Test SVG text (probably broken; unclear what the best way is to handle it)
    689 
    690  // Test that converting between nodes in different toplevel browsing contexts
    691  // throws an exception.
    692  try {
    693    openedWindow = window.open("file_getBoxQuads_convertPointRectQuad_frame2.html","");
    694  } catch (ex) {
    695    // in some cases we can't open the window.
    696    openedWindow = null;
    697  }
    698  if (openedWindow) {
    699    openedWindow.addEventListener("load", function() {
    700      checkException("openedWindow.d.getBoxQuads({relativeTo:document})", "NotFoundError");
    701      checkException("document.getBoxQuads({relativeTo:openedWindow.d})", "NotFoundError");
    702      checkException("openedWindow.d.convertPointFromNode(zeroPoint,document)", "NotFoundError");
    703      checkException("document.convertPointFromNode(zeroPoint,openedWindow.d)", "NotFoundError");
    704      checkException("openedWindow.d.convertRectFromNode(zeroRect,document)", "NotFoundError");
    705      checkException("document.convertRectFromNode(zeroRect,openedWindow.d)", "NotFoundError");
    706      checkException("openedWindow.d.convertQuadFromNode(zeroQuad,document)", "NotFoundError");
    707      checkException("document.convertQuadFromNode(zeroQuad,openedWindow.d)", "NotFoundError");
    708      openedWindow.close();
    709      SimpleTest.finish();
    710    });
    711  } else {
    712    SimpleTest.finish();
    713  }
    714 }
    715 </script>
    716 </body>
    717 </html>