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>