Bug 1289011 - Part 2. Implement ComputeSVGReferenceRect. draft
authorcku <cku@mozilla.com>
Sun, 28 Aug 2016 02:06:04 +0800
changeset 409565 61a9d55466d22b85c21a3c104b5b2280a83a2acf
parent 409564 b87c65af72ef26f638b016eb71ca03e96ef2aae9
child 409566 a8746ff8fd3131262f61f75dad7fcbd84df8c92d
push id28492
push userbmo:cku@mozilla.com
push dateSat, 03 Sep 2016 18:05:10 +0000
bugs1289011
milestone51.0a1
Bug 1289011 - Part 2. Implement ComputeSVGReferenceRect. MozReview-Commit-ID: G98lmo59AuB
layout/svg/nsCSSClipPathInstance.cpp
layout/svg/nsCSSClipPathInstance.h
--- a/layout/svg/nsCSSClipPathInstance.cpp
+++ b/layout/svg/nsCSSClipPathInstance.cpp
@@ -57,44 +57,92 @@ nsCSSClipPathInstance::HitTestBasicShape
   RefPtr<DrawTarget> drawTarget =
     gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
   RefPtr<Path> path = instance.CreateClipPath(drawTarget);
   float pixelRatio = float(nsPresContext::AppUnitsPerCSSPixel()) /
                      aFrame->PresContext()->AppUnitsPerDevPixel();
   return path->ContainsPoint(ToPoint(aPoint) * pixelRatio, Matrix());
 }
 
+nsRect
+nsCSSClipPathInstance::ComputeSVGReferenceRect()
+{
+  nsRect r;
+
+  // For SVG elements without associated CSS layout box, the used value for
+  // content-box, padding-box, border-box and margin-box is fill-box.
+  switch (mClipPathStyle.GetReferenceBox()) {
+
+    case StyleClipPathGeometryBox::NoBox:
+    case StyleClipPathGeometryBox::Border:
+    case StyleClipPathGeometryBox::Content:
+    case StyleClipPathGeometryBox::Padding:
+    case StyleClipPathGeometryBox::Margin:
+    case StyleClipPathGeometryBox::Fill: {
+      gfxRect bbox = nsSVGUtils::GetBBox(mTargetFrame,
+                                         nsSVGUtils::eBBoxIncludeFill);
+      r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
+                                         nsPresContext::AppUnitsPerCSSPixel());
+      break;
+    }
+    default:{
+      MOZ_ASSERT_UNREACHABLE("unknown StyleClipPathGeometryBox type");
+      gfxRect bbox = nsSVGUtils::GetBBox(mTargetFrame,
+                                         nsSVGUtils::eBBoxIncludeFill);
+      r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
+                                         nsPresContext::AppUnitsPerCSSPixel());
+      break;
+    }
+  }
+
+  return r;
+}
 
 nsRect
 nsCSSClipPathInstance::ComputeHTMLReferenceRect()
 {
   nsRect r;
-  // XXXkrit SVG needs to use different boxes.
+
+  // For elements with associated CSS layout box, the used value for fill-box,
+  // stroke-box and view-box is border-box.
   switch (mClipPathStyle.GetReferenceBox()) {
     case StyleClipPathGeometryBox::Content:
       r = mTargetFrame->GetContentRectRelativeToSelf();
       break;
     case StyleClipPathGeometryBox::Padding:
       r = mTargetFrame->GetPaddingRectRelativeToSelf();
       break;
     case StyleClipPathGeometryBox::Margin:
       r = mTargetFrame->GetMarginRectRelativeToSelf();
       break;
-    default: // Use the border box
+    case StyleClipPathGeometryBox::NoBox:
+    case StyleClipPathGeometryBox::Border:
+    case StyleClipPathGeometryBox::Fill:
+    case StyleClipPathGeometryBox::Stroke:
+    case StyleClipPathGeometryBox::View:
+      r = mTargetFrame->GetRectRelativeToSelf();
+      break;
+    default:
+      MOZ_ASSERT_UNREACHABLE("unknown StyleClipPathGeometryBox type");
       r = mTargetFrame->GetRectRelativeToSelf();
       break;
   }
 
   return r;
 }
 
 already_AddRefed<Path>
 nsCSSClipPathInstance::CreateClipPath(DrawTarget* aDrawTarget)
 {
-  nsRect r = ComputeHTMLReferenceRect();
+  // We use ComputeSVGReferenceRect for all SVG elements, except <svg>
+  // element, which does have an associated CSS layout box. In this case we
+  // should still use ComputeHTMLReferenceRect for region computing.
+  nsRect r = mTargetFrame->IsFrameOfType(nsIFrame::eSVG) &&
+             (mTargetFrame->GetType() != nsGkAtoms::svgOuterSVGFrame)
+             ? ComputeSVGReferenceRect() : ComputeHTMLReferenceRect();
 
   if (mClipPathStyle.GetType() != StyleShapeSourceType::Shape) {
     // TODO Clip to border-radius/reference box if no shape
     // was specified.
     RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
     return builder->Finish();
   }
 
--- a/layout/svg/nsCSSClipPathInstance.h
+++ b/layout/svg/nsCSSClipPathInstance.h
@@ -45,16 +45,17 @@ private:
   already_AddRefed<Path> CreateClipPathPolygon(DrawTarget* aDrawTarget,
                                                const nsRect& aRefBox);
 
   already_AddRefed<Path> CreateClipPathInset(DrawTarget* aDrawTarget,
                                              const nsRect& aRefBox);
 
 
   nsRect ComputeHTMLReferenceRect();
+  nsRect ComputeSVGReferenceRect();
 
   /**
    * The frame for the element that is currently being clipped.
    */
   nsIFrame* mTargetFrame;
   StyleClipPath mClipPathStyle;
 };