Bug 1289011 - Part 3. Handle view-box. draft
authorcku <cku@mozilla.com>
Tue, 30 Aug 2016 10:27:30 +0800
changeset 409566 a8746ff8fd3131262f61f75dad7fcbd84df8c92d
parent 409565 61a9d55466d22b85c21a3c104b5b2280a83a2acf
child 409567 b3dc077939a4e3f200b9da57603f8878305339eb
push id28492
push userbmo:cku@mozilla.com
push dateSat, 03 Sep 2016 18:05:10 +0000
bugs1289011
milestone51.0a1
Bug 1289011 - Part 3. Handle view-box. MozReview-Commit-ID: 3GsivsTYPYK
dom/svg/SVGSVGElement.cpp
dom/svg/SVGSVGElement.h
layout/svg/nsCSSClipPathInstance.cpp
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -1017,17 +1017,17 @@ SVGSVGElement::GetLengthInfo()
 
 nsSVGElement::EnumAttributesInfo
 SVGSVGElement::GetEnumInfo()
 {
   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
                             ArrayLength(sEnumInfo));
 }
 
-nsSVGViewBox *
+nsSVGViewBox*
 SVGSVGElement::GetViewBox()
 {
   return &mViewBox;
 }
 
 SVGAnimatedPreserveAspectRatio *
 SVGSVGElement::GetPreserveAspectRatio()
 {
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -283,16 +283,17 @@ public:
   already_AddRefed<SVGIRect> CreateSVGRect();
   already_AddRefed<SVGTransform> CreateSVGTransform();
   already_AddRefed<SVGTransform> CreateSVGTransformFromMatrix(SVGMatrix& matrix);
   using nsINode::GetElementById; // This does what we want
   already_AddRefed<SVGAnimatedRect> ViewBox();
   already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
   uint16_t ZoomAndPan();
   void SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv);
+  virtual nsSVGViewBox* GetViewBox() override;
 
 private:
   // nsSVGElement overrides
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
@@ -373,17 +374,16 @@ private:
 
   virtual EnumAttributesInfo GetEnumInfo() override;
 
   enum { ZOOMANDPAN };
   nsSVGEnum mEnumAttributes[1];
   static nsSVGEnumMapping sZoomAndPanMap[];
   static EnumInfo sEnumInfo[1];
 
-  virtual nsSVGViewBox *GetViewBox() override;
   virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio() override;
 
   nsSVGViewBox                   mViewBox;
   SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
 
   // mCurrentViewID and mSVGView are mutually exclusive; we can have
   // at most one non-null.
   nsAutoPtr<nsString>            mCurrentViewID;
--- a/layout/svg/nsCSSClipPathInstance.cpp
+++ b/layout/svg/nsCSSClipPathInstance.cpp
@@ -60,22 +60,52 @@ nsCSSClipPathInstance::HitTestBasicShape
   float pixelRatio = float(nsPresContext::AppUnitsPerCSSPixel()) /
                      aFrame->PresContext()->AppUnitsPerDevPixel();
   return path->ContainsPoint(ToPoint(aPoint) * pixelRatio, Matrix());
 }
 
 nsRect
 nsCSSClipPathInstance::ComputeSVGReferenceRect()
 {
+  MOZ_ASSERT(mTargetFrame->GetContent()->IsSVGElement());
   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::View: {
+      nsIContent* content = mTargetFrame->GetContent();
+      nsSVGElement* element = static_cast<nsSVGElement*>(content);
+      SVGSVGElement* svgElement = element->GetCtx();
+      MOZ_ASSERT(svgElement);
 
+      if (svgElement && svgElement->HasViewBoxRect()) {
+        // If a ‘viewBox‘ attribute is specified for the SVG viewport creating
+        // element:
+        // 1. The reference box is positioned at the origin of the coordinate
+        //    system established by the ‘viewBox‘ attribute.
+        // 2. The dimension of the reference box is set to the width and height
+        //    values of the ‘viewBox‘ attribute.
+        nsSVGViewBox* viewBox = svgElement->GetViewBox();
+        const nsSVGViewBoxRect& value = viewBox->GetAnimValue();
+        r = nsRect(nsPresContext::CSSPixelsToAppUnits(value.x),
+                   nsPresContext::CSSPixelsToAppUnits(value.y),
+                   nsPresContext::CSSPixelsToAppUnits(value.width),
+                   nsPresContext::CSSPixelsToAppUnits(value.height));
+      } else {
+        // No viewBox is specified, uses the nearest SVG viewport as reference
+        // box.
+        svgFloatSize viewportSize = svgElement->GetViewportSize();
+        r = nsRect(0, 0,
+                   nsPresContext::CSSPixelsToAppUnits(viewportSize.width),
+                   nsPresContext::CSSPixelsToAppUnits(viewportSize.height));
+      }
+
+      break;
+    }
     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);