layout/base/tests/test_getBoxQuads_convertPointRectQuad.html

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial