Bug 1250143. Account for border/padding on outer <svg> elements in GeometryUtils. r=mats draft
authorRobert O'Callahan <robert@ocallahan.org>
Thu, 25 Feb 2016 23:54:09 +1300
changeset 334547 d0ba2e4cd3e45280d8d030517c515caa04cb0b66
parent 334293 b5ec7338bddf9f1147e19c1d4d1b90a0cdb8da9a
child 514926 15a5887790ae08e715f8f101a403bcf88ba14460
push id11565
push userrocallahan@mozilla.com
push dateThu, 25 Feb 2016 10:54:36 +0000
reviewersmats
bugs1250143
milestone47.0a1
Bug 1250143. Account for border/padding on outer <svg> elements in GeometryUtils. r=mats MozReview-Commit-ID: KwEwnukNgeF
layout/base/GeometryUtils.cpp
layout/base/tests/test_getBoxQuads_convertPointRectQuad.html
layout/svg/nsSVGUtils.cpp
--- a/layout/base/GeometryUtils.cpp
+++ b/layout/base/GeometryUtils.cpp
@@ -135,18 +135,18 @@ GetFirstNonAnonymousFrameForNode(nsINode
  * handle SVG, where SVG elements can only compute a rect that's valid with
  * respect to the "outer SVG" frame.
  */
 static nsRect
 GetBoxRectForFrame(nsIFrame** aFrame, CSSBoxType aType)
 {
   nsRect r;
   nsIFrame* f = nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(*aFrame, &r);
-  if (f) {
-    // For SVG, the BoxType is ignored.
+  if (f && f != *aFrame) {
+    // For non-outer SVG frames, the BoxType is ignored.
     *aFrame = f;
     return r;
   }
 
   f = *aFrame;
   switch (aType) {
   case CSSBoxType::Content: r = f->GetContentRectRelativeToSelf(); break;
   case CSSBoxType::Padding: r = f->GetPaddingRectRelativeToSelf(); break;
--- a/layout/base/tests/test_getBoxQuads_convertPointRectQuad.html
+++ b/layout/base/tests/test_getBoxQuads_convertPointRectQuad.html
@@ -331,17 +331,17 @@ TextTextTextTextTextTextTextTextTextText
 
 <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;">
+  <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>
@@ -655,29 +655,36 @@ function runTest() {
   // 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 + 30, svgContainerY + 30, 40, 40);
+                  svgContainerX + 41, svgContainerY + 41, 40, 40);
   // Box types are ignored for SVG elements.
   checkQuadIsRect("circle", {box:"content"},
-                  svgContainerX + 30, svgContainerY + 30, 40, 40);
+                  svgContainerX + 41, svgContainerY + 41, 40, 40);
   checkQuadIsRect("circle", {box:"padding"},
-                  svgContainerX + 30, svgContainerY + 30, 40, 40);
+                  svgContainerX + 41, svgContainerY + 41, 40, 40);
   checkQuadIsRect("circle", {box:"margin"},
-                  svgContainerX + 30, svgContainerY + 30, 40, 40);
+                  svgContainerX + 41, svgContainerY + 41, 40, 40);
   checkQuadIsRect("d", {toStr:"circle"},
-                  dX - (svgContainerX + 30), dY - (svgContainerY + 30), dW, dH);
+                  dX - (svgContainerX + 41), dY - (svgContainerY + 41), dW, dH);
   // Test foreignObject inside an SVG transform.
   checkQuadIsRect("foreign", {},
-                  svgContainerX + 100, svgContainerY + 40, 200, 120);
+                  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("data:text/html,<div id='d'>","");
   } catch (ex) {
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -379,18 +379,20 @@ nsSVGUtils::GetOuterSVGFrameAndCoveredRe
 {
   nsISVGChildFrame* svg = do_QueryFrame(aFrame);
   if (!svg)
     return nullptr;
   nsSVGOuterSVGFrame* outer = GetOuterSVGFrame(aFrame);
   if (outer == svg) {
     return nullptr;
   }
-  *aRect = (aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ?
-             nsRect(0, 0, 0, 0) : svg->GetCoveredRegion();
+  nsMargin bp = outer->GetUsedBorderAndPadding();
+  *aRect = ((aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ?
+             nsRect(0, 0, 0, 0) : svg->GetCoveredRegion()) +
+                 nsPoint(bp.left, bp.top);
   return outer;
 }
 
 gfxMatrix
 nsSVGUtils::GetCanvasTM(nsIFrame *aFrame)
 {
   // XXX yuck, we really need a common interface for GetCanvasTM