diff options
Diffstat (limited to '')
-rw-r--r-- | layout/base/tests/test_getBoxQuads_convertPointRectQuad.html | 717 |
1 files changed, 717 insertions, 0 deletions
diff --git a/layout/base/tests/test_getBoxQuads_convertPointRectQuad.html b/layout/base/tests/test_getBoxQuads_convertPointRectQuad.html new file mode 100644 index 0000000000..3b0431f458 --- /dev/null +++ b/layout/base/tests/test_getBoxQuads_convertPointRectQuad.html @@ -0,0 +1,717 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta charset="utf-8"> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body onload="startTest()"> +<p id="display"></p> +<script> +// Global variables we want eval() to be able to reference from anywhere +var f1d; +var text; +var suppressedText; +var suppressedText2; +var comment; +var fragment; +var openedWindow; +var zeroPoint; +var zeroRect; +var zeroQuad; +var notInDocument = document.createElement('div'); + +function isEval(expr, b) { + // we ignore an insignificant discrepancy in floating-point values + var exprVal = eval(expr); + if (exprVal != b && Math.abs(exprVal - b) < 0.0001) { + ok(true, expr + " (" + exprVal + " within 0.0001 of " + b + ")"); + return; + } + is(exprVal, b, expr); +} + +function isApprox(a, b, msg, options) { + if (a != b && 'tolerance' in options && + Math.abs(a - b) < options.tolerance) { + ok(true, msg + "(" + a + " within " + options.tolerance + " of " + b + ")"); + return; + } + is(a, b, msg); +} + +function makeQuadsExpr(fromStr, options) { + var getBoxQuadsOptionParts = []; + if ('box' in options) { + getBoxQuadsOptionParts.push("box:'" + options.box + "'"); + } + if ('toStr' in options) { + getBoxQuadsOptionParts.push("relativeTo:" + options.toStr); + } + return fromStr + ".getBoxQuads({" + getBoxQuadsOptionParts.join(',') + "})"; +} + +function makePointExpr(fromStr, options, x, y) { + var convertPointOptionParts = []; + if ('box' in options) { + convertPointOptionParts.push("fromBox:'" + options.box + "'"); + } + if ('toBox' in options) { + convertPointOptionParts.push("toBox:'" + options.toBox + "'"); + } + return ('toStr' in options ? options.toStr : "document") + + ".convertPointFromNode(new DOMPoint(" + x + "," + y + ")," + fromStr + ",{" + + convertPointOptionParts.join(",") + "})"; +} + +function checkConvertPoints(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) { + var selfQuads = eval(fromStr).getBoxQuads( + {box:options.box == "" ? "border" : options.box, + relativeTo:eval(fromStr)}); + var boxWidth = selfQuads[0].getBounds().width; + var boxHeight = selfQuads[0].getBounds().height; + + var convertTopLeftPointExpr = makePointExpr(fromStr, options, 0, 0); + var topLeft = eval(convertTopLeftPointExpr); + isApprox(topLeft.x, x1, convertTopLeftPointExpr + ".x", options); + isApprox(topLeft.y, y1, convertTopLeftPointExpr + ".y", options); + + var convertTopRightPointExpr = makePointExpr(fromStr, options, boxWidth, 0); + var topRight = eval(convertTopRightPointExpr); + isApprox(topRight.x, x2, convertTopRightPointExpr + ".x", options); + isApprox(topRight.y, y2, convertTopRightPointExpr + ".y", options); + + var convertBottomRightPointExpr = makePointExpr(fromStr, options, boxWidth, boxHeight); + var bottomRight = eval(convertBottomRightPointExpr); + isApprox(bottomRight.x, x3, convertBottomRightPointExpr + ".x", options); + isApprox(bottomRight.y, y3, convertBottomRightPointExpr + ".y", options); + + var convertBottomLeftPointExpr = makePointExpr(fromStr, options, 0, boxHeight); + var bottomLeft = eval(convertBottomLeftPointExpr); + isApprox(bottomLeft.x, x4, convertBottomLeftPointExpr + ".x", options); + isApprox(bottomLeft.y, y4, convertBottomLeftPointExpr + ".y", options); +} + +function checkConvertRect(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) { + var selfQuads = eval(fromStr).getBoxQuads( + {box:options.box == "" ? "border" : options.box, + relativeTo:eval(fromStr)}); + var boxWidth = selfQuads[0].getBounds().width; + var boxHeight = selfQuads[0].getBounds().height; + + var convertPointOptionParts = []; + if ('box' in options) { + convertPointOptionParts.push("fromBox:'" + options.box + "'"); + } + if ('toBox' in options) { + convertPointOptionParts.push("toBox:'" + options.toBox + "'"); + } + + var convertRectExpr = ('toStr' in options ? options.toStr : "document") + + ".convertRectFromNode(new DOMRect(0,0," + boxWidth + "," + boxHeight + ")," + + fromStr + ",{" + convertPointOptionParts.join(",") + "})"; + var quad = eval(convertRectExpr); + isApprox(quad.p1.x, x1, convertRectExpr + ".p1.x", options); + isApprox(quad.p1.y, y1, convertRectExpr + ".p1.y", options); + isApprox(quad.p2.x, x2, convertRectExpr + ".p2.x", options); + isApprox(quad.p2.y, y2, convertRectExpr + ".p2.y", options); + isApprox(quad.p3.x, x3, convertRectExpr + ".p3.x", options); + isApprox(quad.p3.y, y3, convertRectExpr + ".p3.y", options); + isApprox(quad.p4.x, x4, convertRectExpr + ".p4.x", options); + isApprox(quad.p4.y, y4, convertRectExpr + ".p4.y", options); +} + +function checkConvertQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) { + var selfQuads = eval(fromStr).getBoxQuads( + {box:options.box == "" ? "border" : options.box, + relativeTo:eval(fromStr)}); + var boxWidth = selfQuads[0].getBounds().width; + var boxHeight = selfQuads[0].getBounds().height; + + var convertPointOptionParts = []; + if ('box' in options) { + convertPointOptionParts.push("fromBox:'" + options.box + "'"); + } + if ('toBox' in options) { + convertPointOptionParts.push("toBox:'" + options.toBox + "'"); + } + + var convertQuadExpr = ('toStr' in options ? options.toStr : "document") + + ".convertQuadFromNode(new DOMQuad(new DOMRect(0,0," + boxWidth + "," + boxHeight + "))," + + fromStr + ",{" + convertPointOptionParts.join(",") + "})"; + var quad = eval(convertQuadExpr); + isApprox(quad.p1.x, x1, convertQuadExpr + ".p1.x", options); + isApprox(quad.p1.y, y1, convertQuadExpr + ".p1.y", options); + isApprox(quad.p2.x, x2, convertQuadExpr + ".p2.x", options); + isApprox(quad.p2.y, y2, convertQuadExpr + ".p2.y", options); + isApprox(quad.p3.x, x3, convertQuadExpr + ".p3.x", options); + isApprox(quad.p3.y, y3, convertQuadExpr + ".p3.y", options); + isApprox(quad.p4.x, x4, convertQuadExpr + ".p4.x", options); + isApprox(quad.p4.y, y4, convertQuadExpr + ".p4.y", options); +} + +function checkQuadIsRect(fromStr, options, x, y, w, h) { + var quadsExpr = makeQuadsExpr(fromStr, options); + var quads = eval(quadsExpr); + is(quads.length, 1, quadsExpr + " checking quad count"); + var q = quads[0]; + isApprox(q.p1.x, x, quadsExpr + " checking quad.p1.x", options); + isApprox(q.p1.y, y, quadsExpr + " checking quad.p1.y", options); + isApprox(q.p2.x, x + w, quadsExpr + " checking quad.p2.x", options); + isApprox(q.p2.y, y, quadsExpr + " checking quad.p2.y", options); + isApprox(q.p3.x, x + w, quadsExpr + " checking quad.p3.x", options); + isApprox(q.p3.y, y + h, quadsExpr + " checking quad.p3.y", options); + isApprox(q.p4.x, x, quadsExpr + " checking quad.p4.x", options); + isApprox(q.p4.y, y + h, quadsExpr + " checking quad.p4.y", options); + + isApprox(q.getBounds().left, x, quadsExpr + " checking quad.getBounds().left", options); + isApprox(q.getBounds().top, y, quadsExpr + " checking quad.getBounds().top", options); + isApprox(q.getBounds().width, w, quadsExpr + " checking quad.getBounds().width", options); + isApprox(q.getBounds().height, h, quadsExpr + " checking quad.getBounds().height", options); + + checkConvertPoints(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h); + checkConvertRect(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h); + checkConvertQuad(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h); +} + +function checkQuadIsQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) { + var quadsExpr = makeQuadsExpr(fromStr, options); + var quads = eval(quadsExpr); + is(quads.length, 1, quadsExpr + " checking quad count"); + var q = quads[0]; + isApprox(q.p1.x, x1, quadsExpr + " checking quad.p1.x", options); + isApprox(q.p1.y, y1, quadsExpr + " checking quad.p1.y", options); + isApprox(q.p2.x, x2, quadsExpr + " checking quad.p2.x", options); + isApprox(q.p2.y, y2, quadsExpr + " checking quad.p2.y", options); + isApprox(q.p3.x, x3, quadsExpr + " checking quad.p3.x", options); + isApprox(q.p3.y, y3, quadsExpr + " checking quad.p3.y", options); + isApprox(q.p4.x, x4, quadsExpr + " checking quad.p4.x", options); + isApprox(q.p4.y, y4, quadsExpr + " checking quad.p4.y", options); + + isApprox(q.getBounds().left, Math.min(x1,x2,x3,x4), quadsExpr + " checking quad.getBounds().left", options); + isApprox(q.getBounds().top, Math.min(y1,y2,y3,y4), quadsExpr + " checking quad.getBounds().top", options); + isApprox(q.getBounds().right, Math.max(x1,x2,x3,x4), quadsExpr + " checking quad.getBounds().right", options); + isApprox(q.getBounds().bottom, Math.max(y1,y2,y3,y4), quadsExpr + " checking quad.getBounds().bottom", options); + + checkConvertPoints(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4); + checkConvertRect(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4); + checkConvertQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4); +} + +function checkException(expr, name) { + try { + eval(expr); + ok(false, "Exception should have been thrown for " + expr); + } catch (ex) { + is(ex.name, name, "Checking exception type for " + expr); + } +} + +function checkNotFound(fromStr, toStr, x1, y1, x2, y2) { + var convertPointExpr = toStr + ".convertPointFromNode(new DOMPoint(" + x1 + + "," + y1 + ")," + fromStr + ")"; + checkException(convertPointExpr, "NotFoundError"); + + var convertRectExpr = toStr + ".convertRectFromNode(new DOMRect(" + x1 + + "," + y1 + "," + x2 + "," + y2 + ")," + fromStr + ")"; + checkException(convertRectExpr, "NotFoundError"); + + var convertQuadExpr = toStr + ".convertQuadFromNode(new DOMQuad(new DOMRect(" + x1 + + "," + y1 + "," + x2 + "," + y2 + "))," + fromStr + ")"; + checkException(convertQuadExpr, "NotFoundError"); +} +</script> +<style> +em { + display:inline-block; height:10px; background:gray; +} +</style> +<div id="dContainer" + style="padding:13px 14px 15px 16px; + border-width:17px 18px 19px 20px; border-style:solid; border-color:yellow; + margin:21px 22px 23px 24px;"> + <div id="d" + style="width:120px; height:90px; padding:1px 2px 3px 4px; + border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow; + margin:9px 10px 11px 12px; background:blue;"> + </div> +</div> + +<div id="dUnrelated" style="width:50px; height:50px;"></div> + +<iframe id="f1" style="width:50px; height:50px; border:0; background:lime;" + src="file_getBoxQuads_convertPointRectQuad_frame1.html"> +</iframe> +<!-- +It matters that the first part of this span is on the same line as the above <iframe>! +That ensures the first quad's X position is not equal to the anonymous block's X position. +--> +<span id="ibSplit" + ><em id="ibSplitPart1" style="width:100px;"></em + ><div style="width:110px; height:20px; background:black"></div + ><em style="width:130px;"></em></span> + +<table cellspacing="0" id="table" style="border:0; margin:8px; padding:0; background:orange"> + <tbody style="padding:0; margin:0; border:0; background:blue"> + <tr style="height:50px; padding:0; margin:0; border:0"> + <td style="border:0; margin:0; padding:0">Cell</td> + </tr> + </tbody> + <caption style="height:40px; background:yellow">Caption</caption> +</table> + +<div style="height:80px; column-count:2; column-fill:auto; border:2px solid black;"> + <div style="height:20px;"></div> + <div id="colSplit" style="height:80px; background:blue; border:10px solid red; border-bottom-width:15px"></div> +</div> + +<div style="width:200px; border:2px solid black;" + ><em style="width:150px;"></em + ><span id="inlineSplit" style="background:pink; border:10px solid red; border-right-width:15px" + ><em style="width:20px; background:green"></em><em style="width:60px"></em + ></span +></div> + +<div style="width:200px; border:2px solid black;" + ><em style="width:150px;"></em + ><span id="textContainer">T +TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText</span +></div> + +<div id="suppressedTextContainer"> </div> +<div id="suppressedTextContainer2"> </div> + +<div id="commentContainer"><!-- COMMENT --></div> + +<div id="displayNone" style="display:none"></div> + +<div id="overflowHidden" + style="overflow:hidden; width:120px; height:90px; padding:1px 2px 3px 4px; + border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow; + margin:9px 10px 11px 12px; background:blue;"> + <div style="height:400px; background:lime;"></div> +</div> + +<div id="overflowScroll" + style="overflow:scroll; width:120px; height:90px; padding:1px 2px 3px 4px; + border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow; + margin:9px 10px 11px 12px; background:blue; background-clip:content-box;"> + <div id="overflowScrollChild" style="height:400px;"></div> +</div> + +<div id="scaleTransformContainer" style="width:200px; height:200px;"> + <div id="scaleTransform" + style="transform:scale(2); transform-origin:top left; width:70px; height:80px; background:yellow"></div> +</div> + +<div id="translateTransformContainer" style="width:200px; height:200px;"> + <div id="translateTransform" + style="transform:translate(30px,40px); width:70px; height:80px; background:yellow"></div> +</div> + +<div id="rotateTransformContainer" style="width:200px; height:200px;"> + <div id="rotateTransform" + style="transform:rotate(90deg); width:70px; height:80px; background:yellow"></div> +</div> + +<div id="flipTransformContainer" style="width:200px; height:200px;"> + <div id="flipTransform" + style="transform:scaleY(-1); width:70px; height:80px; background:yellow"></div> +</div> + +<div id="rot45TransformContainer" style="width:200px; height:200px;"> + <div id="rot45Transform" + style="transform:rotate(45deg); width:100px; height:100px; background:yellow"></div> +</div> + +<div id="singularTransform" style="transform:scale(0); width:200px; height:200px;"> + <div id="singularTransformChild1" style="height:50px;"></div> + <div id="singularTransformChild2" style="height:50px;"></div> +</div> + +<div id="threeDTransformContainer" style="perspective:600px; width:200px; height:200px"> + <div id="threeDTransform" style="transform:rotateY(70deg); background:yellow; height:100px; perspective:600px"> + <div id="threeDTransformChild" style="transform:rotateY(-70deg); background:blue; height:50px;"></div> + </div> +</div> + +<div id="preserve3DTransformContainer" style="perspective:600px; width:200px; height:200px"> + <div id="preserve3DTransform" style="transform:rotateY(70deg); transform-style:preserve-3d; background:yellow; height:100px;"> + <div id="preserve3DTransformChild" style="transform:rotateY(-70deg); background:blue; height:50px;"></div> + </div> +</div> + +<div id="svgContainer"> + <svg id="svg" style="width:200px; height:200px; background:lightgray; border:7px solid blue; padding:4px"> + <circle id="circle" cx="50" cy="50" r="20" fill="red" style="margin:20px; padding:10px; border:15px solid black"></circle> + <g transform="scale(2)"> + <foreignObject x="50" y="20"> + <div id="foreign" style="width:100px; height:60px; background:purple"></div> + </foreignObject> + </g> + </svg> +</div> + +<script> +SimpleTest.waitForExplicitFinish(); + +window.scrollTo(0,0); + +function startTest() { + SpecialPowers.pushPrefEnv({"set": [["layout.css.getBoxQuads.enabled", true], + ["layout.css.convertFromNode.enabled", true]]}, grabFeatures); +} + +// This is a bit of a hack but it works. Our Window object was set up while +// the prefs might have been false so it may not have the features we're +// testing. Create an <iframe> whose Window is initialized while the prefs are +// true, and we can steal the features from that Window. +// When these prefs are enabled on all builds by default, we can skip this step. +function grabFeatures() { + var x = document.createElement('iframe'); + x.src = "about:blank"; + document.body.appendChild(x); + function setupFeatures(w) { + for (var name of ["getBoxQuads", "convertQuadFromNode", "convertRectFromNode", "convertPointFromNode"]) { + w.Text.prototype[name] = x.contentWindow.Text.prototype[name]; + w.Element.prototype[name] = x.contentWindow.Element.prototype[name]; + w.Document.prototype[name] = x.contentWindow.Document.prototype[name]; + } + for (var name of ["DOMPoint", "DOMQuad"]) { + w[name] = x.contentWindow[name]; + } + } + x.onload = function() { + setupFeatures(window); + setupFeatures(f1.contentWindow); + runTest(); + }; +} + +function runTest() { + zeroPoint = new DOMPoint(0,0); + zeroRect = new DOMRect(0,0,0,0); + zeroQuad = new DOMQuad(zeroRect); + + // Setup globals + f1d = f1.contentWindow.f1d; + text = textContainer.firstChild; + suppressedText = suppressedTextContainer.firstChild; + suppressedText2 = suppressedTextContainer2.firstChild; + comment = commentContainer.firstChild; + fragment = document.createDocumentFragment(); + + // Test basic BoxQuadOptions.box. + var dX = d.getBoundingClientRect().left; + var dY = d.getBoundingClientRect().top; + var dW = d.getBoundingClientRect().width; + var dH = d.getBoundingClientRect().height; + + checkQuadIsRect("d", {box:"content"}, + dX + 4 + 8, dY + 1 + 5, 120, 90); + checkQuadIsRect("d", {box:"padding"}, + dX + 8, dY + 5, 120 + 2 + 4, 90 + 1 + 3); + checkQuadIsRect("d", {box:"border"}, + dX, dY, dW, dH); + checkQuadIsRect("d", {}, + dX, dY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7); + checkQuadIsRect("d", {box:"margin"}, + dX - 12, dY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11); + + // Test basic BoxQuadOptions.relativeTo + checkQuadIsRect("d", {toStr:"dContainer"}, + 12 + 16 + 20, 9 + 13 + 17, dW, dH); + + // Test BoxQuadOptions.relativeTo relative to this document + checkQuadIsRect("d", {toStr:"document"}, + dX, dY, dW, dH); + // Test BoxQuadOptions.relativeTo relative to a non-ancestor. + var dUnrelatedX = dUnrelated.getBoundingClientRect().left; + var dUnrelatedY = dUnrelated.getBoundingClientRect().top; + checkQuadIsRect("d", {toStr:"dUnrelated"}, + dX - dUnrelatedX, dY - dUnrelatedY, dW, dH); + // Test BoxQuadOptions.relativeTo relative to an element in a different document (and the document) + var f1X = f1.getBoundingClientRect().left; + var f1Y = f1.getBoundingClientRect().top; + checkQuadIsRect("d", {toStr:"f1.contentWindow.f1d"}, + dX - (f1X + 14), dY - (f1Y + 15), dW, dH); + checkQuadIsRect("d", {toStr:"f1.contentDocument"}, + dX - f1X, dY - f1Y, dW, dH); + // Test one document relative to another + checkQuadIsRect("f1.contentDocument", {toStr:"document"}, + f1X, f1Y, 50, 50); + // The box type is irrelevant for a document + checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"content"}, + f1X, f1Y, 50, 50); + checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"margin"}, + f1X, f1Y, 50, 50); + checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"padding"}, + f1X, f1Y, 50, 50); + + // Test that anonymous boxes are correctly ignored when building quads. + var ibSplitPart1X = ibSplitPart1.getBoundingClientRect().left; + var ibSplitY = ibSplit.getBoundingClientRect().top; + isEval("ibSplit.getBoxQuads().length", 3); + isEval("ibSplit.getBoxQuads()[0].getBounds().left", ibSplitPart1X); + isEval("ibSplit.getBoxQuads()[0].getBounds().width", 100); + isEval("ibSplit.getBoxQuads()[1].getBounds().width", 110); + isEval("ibSplit.getBoxQuads()[2].getBounds().width", 130); + isEval("table.getBoxQuads().length", 2); + isEval("table.getBoxQuads()[0].getBounds().height", 50); + isEval("table.getBoxQuads()[1].getBounds().height", 40); + + // Test that we skip anonymous boxes when finding the right box to be relative to. + checkQuadIsRect("d", {toStr:"ibSplit", tolerance:0.0001}, + dX - ibSplitPart1X, dY - ibSplitY, dW, dH); + var tableX = table.getClientRects()[0].left; + var tableY = table.getClientRects()[0].top; + checkQuadIsRect("d", {toStr:"table"}, + dX - tableX, dY - tableY, dW, dH); + isEval("ibSplit.convertPointFromNode(zeroPoint,d).x", dX - ibSplitPart1X); + isEval("table.convertPointFromNode(zeroPoint,d).x", dX - table.getClientRects()[0].left); + + // Test boxes generated by block splitting. Check for borders being placed correctly. + var colSplitY = colSplit.getClientRects()[0].top; + isEval("colSplit.getBoxQuads().length", 2); + isEval("colSplit.getBoxQuads()[0].getBounds().top", colSplitY); + isEval("colSplit.getBoxQuads()[0].getBounds().height", 60); + isEval("colSplit.getBoxQuads()[1].getBounds().top", colSplitY - 20); + isEval("colSplit.getBoxQuads()[1].getBounds().height", 45); + isEval("colSplit.getBoxQuads({box:'content'}).length", 2); + // The first box for the block has the top border; the second box has the bottom border. + isEval("colSplit.getBoxQuads({box:'content'})[0].getBounds().top", colSplitY + 10); + isEval("colSplit.getBoxQuads({box:'content'})[0].getBounds().height", 50); + isEval("colSplit.getBoxQuads({box:'content'})[1].getBounds().top", colSplitY - 20); + isEval("colSplit.getBoxQuads({box:'content'})[1].getBounds().height", 30); + + var inlineSplitX = inlineSplit.getClientRects()[0].left; + isEval("inlineSplit.getBoxQuads().length", 2); + isEval("inlineSplit.getBoxQuads()[0].getBounds().left", inlineSplitX); + isEval("inlineSplit.getBoxQuads()[0].getBounds().width", 30); + isEval("inlineSplit.getBoxQuads()[1].getBounds().left", inlineSplitX - 150); + isEval("inlineSplit.getBoxQuads()[1].getBounds().width", 75); + isEval("inlineSplit.getBoxQuads({box:'content'}).length", 2); + // The first box for the inline has the left border; the second box has the right border. + isEval("inlineSplit.getBoxQuads({box:'content'})[0].getBounds().left", inlineSplitX + 10); + isEval("inlineSplit.getBoxQuads({box:'content'})[0].getBounds().width", 20); + isEval("inlineSplit.getBoxQuads({box:'content'})[1].getBounds().left", inlineSplitX - 150); + isEval("inlineSplit.getBoxQuads({box:'content'})[1].getBounds().width", 60); + + var textX = textContainer.getClientRects()[0].left; + isEval("text.getBoxQuads().length", 2); + isEval("text.getBoxQuads()[0].getBounds().left", textX); + isEval("text.getBoxQuads()[1].getBounds().left", textX - 150); + // Box types are irrelevant for text + isEval("text.getBoxQuads({box:'content'}).length", 2); + isEval("text.getBoxQuads({box:'content'})[0].getBounds().left", textX); + isEval("text.getBoxQuads({box:'content'})[1].getBounds().left", textX - 150); + isEval("text.getBoxQuads({box:'padding'}).length", 2); + isEval("text.getBoxQuads({box:'padding'})[0].getBounds().left", textX); + isEval("text.getBoxQuads({box:'padding'})[1].getBounds().left", textX - 150); + isEval("text.getBoxQuads({box:'margin'}).length", 2); + isEval("text.getBoxQuads({box:'margin'})[0].getBounds().left", textX); + isEval("text.getBoxQuads({box:'margin'})[1].getBounds().left", textX - 150); + + // Test table margins + isEval("table.getBoxQuads({box:'margin'}).length", 1); + isEval("table.getBoxQuads({box:'margin'})[0].getBounds().height", 106); + + // Check that a text node whose layout might have been optimized away gives + // correct results. + var suppressedTextContainerX = suppressedTextContainer.getBoundingClientRect().left; + isEval("suppressedText.getBoxQuads().length", 1); + isEval("suppressedText.getBoxQuads()[0].getBounds().left", suppressedTextContainerX); + isEval("suppressedText.getBoxQuads()[0].getBounds().width", 0); + + var suppressedTextContainer2X = suppressedTextContainer2.getBoundingClientRect().left; + isEval("document.convertPointFromNode(zeroPoint,suppressedText2).x", + suppressedTextContainer2X); + + checkException("comment.getBoxQuads()", "TypeError"); + checkException("d.getBoxQuads({relativeTo:comment})", "TypeError"); + checkException("comment.convertPointFromNode(zeroPoint,document)", "TypeError"); + checkException("document.convertPointFromNode(zeroPoint,comment)", "TypeError"); + checkException("comment.convertRectFromNode(zeroRect,document)", "TypeError"); + checkException("document.convertRectFromNode(zeroRect,comment)", "TypeError"); + checkException("comment.convertQuadFromNode(zeroQuad,document)", "TypeError"); + checkException("document.convertQuadFromNode(zeroQuad,comment)", "TypeError"); + + checkException("fragment.getBoxQuads()", "TypeError"); + checkException("d.getBoxQuads({relativeTo:fragment})", "TypeError"); + checkException("fragment.convertPointFromNode(zeroPoint,document)", "TypeError"); + checkException("document.convertPointFromNode(zeroPoint,fragment)", "TypeError"); + checkException("fragment.convertRectFromNode(zeroRect,document)", "TypeError"); + checkException("document.convertRectFromNode(zeroRect,fragment)", "TypeError"); + checkException("fragment.convertQuadFromNode(zeroQuad,document)", "TypeError"); + checkException("document.convertQuadFromNode(zeroQuad,fragment)", "TypeError"); + + isEval("displayNone.getBoxQuads().length", 0); + isEval("notInDocument.getBoxQuads().length", 0); + checkNotFound("displayNone", "document", 1, 2, 3, 4); + checkNotFound("notInDocument", "document", 1, 2, 3, 4); + checkNotFound("document", "displayNone", 1, 2, 3, 4); + checkNotFound("document", "notInDocument", 1, 2, 3, 4); + + // Test an overflow:hidden version of d. overflow:hidden should not affect + // the quads, basically. + var oHX = overflowHidden.getBoundingClientRect().left; + var oHY = overflowHidden.getBoundingClientRect().top; + checkQuadIsRect("overflowHidden", {box:"content"}, + oHX + 4 + 8, oHY + 1 + 5, 120, 90); + checkQuadIsRect("overflowHidden", {box:"padding"}, + oHX + 8, oHY + 5, 120 + 2 + 4, 90 + 1 + 3); + checkQuadIsRect("overflowHidden", {box:"border"}, + oHX, oHY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7); + checkQuadIsRect("overflowHidden", {}, + oHX, oHY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7); + checkQuadIsRect("overflowHidden", {box:"margin"}, + oHX - 12, oHY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11); + + // Test an overflow:scroll version of d. I assume that boxes aren't affected + // by the scrollbar although it's not clear that this is correct. + var oSX = overflowScroll.getBoundingClientRect().left; + var oSY = overflowScroll.getBoundingClientRect().top; + checkQuadIsRect("overflowScroll", {box:"content"}, + oSX + 4 + 8, oSY + 1 + 5, 120, 90); + checkQuadIsRect("overflowScroll", {box:"padding"}, + oSX + 8, oSY + 5, 120 + 2 + 4, 90 + 1 + 3); + checkQuadIsRect("overflowScroll", {box:"border"}, + oSX, oSY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7); + checkQuadIsRect("overflowScroll", {}, + oSX, oSY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7); + checkQuadIsRect("overflowScroll", {box:"margin"}, + oSX - 12, oSY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11); + + // Test simple 2D transforms. + var stcX = scaleTransformContainer.getBoundingClientRect().left; + var stcY = scaleTransformContainer.getBoundingClientRect().top; + checkQuadIsRect("scaleTransform", {}, + stcX, stcY, 140, 160); + var ttcX = translateTransformContainer.getBoundingClientRect().left; + var ttcY = translateTransformContainer.getBoundingClientRect().top; + checkQuadIsRect("translateTransform", {}, + ttcX + 30, ttcY + 40, 70, 80); + // Test mapping into a transformed element. + checkQuadIsRect("scaleTransform", {toStr:"translateTransform"}, + stcX - (ttcX + 30), stcY - (ttcY + 40), 140, 160); + // Test 90 degree rotation. + var rotatetcX = rotateTransformContainer.getBoundingClientRect().left; + var rotatetcY = rotateTransformContainer.getBoundingClientRect().top; + checkQuadIsQuad("rotateTransform", {}, + rotatetcX + 75, rotatetcY + 5, + rotatetcX + 75, rotatetcY + 75, + rotatetcX - 5, rotatetcY + 75, + rotatetcX - 5, rotatetcY + 5); + // Test vertical flip. + var fliptcX = flipTransformContainer.getBoundingClientRect().left; + var fliptcY = flipTransformContainer.getBoundingClientRect().top; + checkQuadIsQuad("flipTransform", {}, + fliptcX, fliptcY + 80, + fliptcX + 70, fliptcY + 80, + fliptcX + 70, fliptcY, + fliptcX, fliptcY); + // Test non-90deg rotation. + var rot45tcX = rot45TransformContainer.getBoundingClientRect().left; + var rot45tcY = rot45TransformContainer.getBoundingClientRect().top; + var halfDiagonal = 100/Math.sqrt(2); + checkQuadIsQuad("rot45Transform", {tolerance:0.01}, + rot45tcX + 50, rot45tcY + 50 - halfDiagonal, + rot45tcX + 50 + halfDiagonal, rot45tcY + 50, + rot45tcX + 50, rot45tcY + 50 + halfDiagonal, + rot45tcX + 50 - halfDiagonal, rot45tcY + 50); + + // Test singular transforms. + var singularTransformX = singularTransform.getBoundingClientRect().left; + var singularTransformY = singularTransform.getBoundingClientRect().top; + // They map everything to a point. + checkQuadIsRect("singularTransform", {}, + singularTransformX, singularTransformY, 0, 0); + checkQuadIsRect("singularTransformChild2", {}, + singularTransformX, singularTransformY, 0, 0); + // Mapping into an element with a singular transform from outside sets + // everything to zero. + checkQuadIsRect("d", {toStr:"singularTransform"}, + 0, 0, 0, 0); + // But mappings within a subtree of an element with a singular transform work. + checkQuadIsRect("singularTransformChild2", {toStr:"singularTransformChild1"}, + 0, 50, 200, 50); + + // Test 3D transforms. + var t3tcX = threeDTransformContainer.getBoundingClientRect().left; + var t3tcY = threeDTransformContainer.getBoundingClientRect().top; + checkQuadIsQuad("threeDTransform", {tolerance:0.01}, + t3tcX + 59.446714, t3tcY - 18.569847, + t3tcX + 129.570778, t3tcY + 13.540874, + t3tcX + 129.570778, t3tcY + 100, + t3tcX + 59.446714, t3tcY + 100); + // Test nested 3D transforms (without preserve-3d). + checkQuadIsQuad("threeDTransformChild", {tolerance:0.01}, + t3tcX + 89.395061, t3tcY + 2.243033, + t3tcX + 113.041727, t3tcY - 2.758530, + t3tcX + 113.041727, t3tcY + 52.985921, + t3tcX + 89.395061, t3tcY + 47.571899); + // Test preserve-3D. + var p3dtcX = preserve3DTransformContainer.getBoundingClientRect().left; + var p3dtcY = preserve3DTransformContainer.getBoundingClientRect().top; + checkQuadIsRect("preserve3DTransformChild", {tolerance:0.01}, + p3dtcX, p3dtcY, 200, 50, + {tolerance:0.0001}); + // Test mapping back into preserve-3D. + checkQuadIsRect("d", {toStr:"preserve3DTransformChild",tolerance:0.01}, + dX - p3dtcX, dY - p3dtcY, dW, dH); + + // Test SVG. + var svgContainerX = svgContainer.getBoundingClientRect().left; + var svgContainerY = svgContainer.getBoundingClientRect().top; + checkQuadIsRect("circle", {}, + svgContainerX + 41, svgContainerY + 41, 40, 40); + // Box types are ignored for SVG elements. + checkQuadIsRect("circle", {box:"content"}, + svgContainerX + 41, svgContainerY + 41, 40, 40); + checkQuadIsRect("circle", {box:"padding"}, + svgContainerX + 41, svgContainerY + 41, 40, 40); + checkQuadIsRect("circle", {box:"margin"}, + svgContainerX + 41, svgContainerY + 41, 40, 40); + checkQuadIsRect("d", {toStr:"circle"}, + dX - (svgContainerX + 41), dY - (svgContainerY + 41), dW, dH); + // Test foreignObject inside an SVG transform. + checkQuadIsRect("foreign", {}, + svgContainerX + 111, svgContainerY + 51, 200, 120); + // Outer <svg> elements support padding and content boxes + checkQuadIsRect("svg", {box:"border"}, + svgContainerX, svgContainerY, 222, 222); + checkQuadIsRect("svg", {box:"padding"}, + svgContainerX + 7, svgContainerY + 7, 208, 208); + checkQuadIsRect("svg", {box:"content"}, + svgContainerX + 11, svgContainerY + 11, 200, 200); + + // XXX Test SVG text (probably broken; unclear what the best way is to handle it) + + // Test that converting between nodes in different toplevel browsing contexts + // throws an exception. + try { + openedWindow = window.open("file_getBoxQuads_convertPointRectQuad_frame2.html",""); + } catch (ex) { + // in some cases we can't open the window. + openedWindow = null; + } + if (openedWindow) { + openedWindow.addEventListener("load", function() { + checkException("openedWindow.d.getBoxQuads({relativeTo:document})", "NotFoundError"); + checkException("document.getBoxQuads({relativeTo:openedWindow.d})", "NotFoundError"); + checkException("openedWindow.d.convertPointFromNode(zeroPoint,document)", "NotFoundError"); + checkException("document.convertPointFromNode(zeroPoint,openedWindow.d)", "NotFoundError"); + checkException("openedWindow.d.convertRectFromNode(zeroRect,document)", "NotFoundError"); + checkException("document.convertRectFromNode(zeroRect,openedWindow.d)", "NotFoundError"); + checkException("openedWindow.d.convertQuadFromNode(zeroQuad,document)", "NotFoundError"); + checkException("document.convertQuadFromNode(zeroQuad,openedWindow.d)", "NotFoundError"); + openedWindow.close(); + SimpleTest.finish(); + }); + } else { + SimpleTest.finish(); + } +} +</script> +</body> +</html> |