Bug 1344971 - Part 3: Don't compute a region for nsDisplayBorder when we only want a rect. r=mstange
authorMatt Woodrow <mwoodrow@mozilla.com>
Tue, 07 Mar 2017 14:07:33 +1300
changeset 449071 5895e9f4bc68e23cff73d4356a64631c1c99784e
parent 449070 6805a1db0a08ac2fd820bfca43391718abf42f50
child 449072 699c28d527aa4ec926e63df4b8ee1aa6663cbbb9
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1344971
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1344971 - Part 3: Don't compute a region for nsDisplayBorder when we only want a rect. r=mstange
gfx/2d/BaseRect.h
layout/mathml/nsMathMLmtableFrame.cpp
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/gfx/2d/BaseRect.h
+++ b/gfx/2d/BaseRect.h
@@ -177,16 +177,21 @@ struct BaseRect {
   // If both rectangles are empty, sets 'this' to aRect2.
   //
   // 'this' can be the same object as either aRect1 or aRect2
   void UnionRect(const Sub& aRect1, const Sub& aRect2)
   {
     *static_cast<Sub*>(this) = aRect1.Union(aRect2);
   }
 
+  void OrWith(const Sub& aRect1)
+  {
+    UnionRect(*static_cast<Sub*>(this), aRect1);
+  }
+
   // Computes the smallest rectangle that contains both the points (including
   // edges) of both aRect1 and aRect2.
   // Thus, empty input rectangles are allowed to affect the result.
   //
   // 'this' can be the same object as either aRect1 or aRect2
   void UnionRectEdges(const Sub& aRect1, const Sub& aRect2)
   {
     *static_cast<Sub*>(this) = aRect1.UnionEdges(aRect2);
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -295,17 +295,17 @@ public:
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
                            bool* aSnap) const override
   {
     *aSnap = true;
     nsStyleBorder styleBorder = *mFrame->StyleBorder();
     nsMathMLmtdFrame* frame = static_cast<nsMathMLmtdFrame*>(mFrame);
     ApplyBorderToStyle(frame, styleBorder);
-    nsRect bounds = CalculateBounds(styleBorder).GetBounds();
+    nsRect bounds = CalculateBounds<nsRect>(styleBorder);
     nsMargin overflow = ComputeBorderOverflow(frame, styleBorder);
     bounds.Inflate(overflow);
     return bounds;
   }
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override
   {
     nsStyleBorder styleBorder = *mFrame->StyleBorder();
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -5366,17 +5366,17 @@ nsDisplayCaret::BuildLayer(nsDisplayList
 }
 
 nsDisplayBorder::nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
   : nsDisplayItem(aBuilder, aFrame)
   , mBorderIsEmpty(false)
 {
   MOZ_COUNT_CTOR(nsDisplayBorder);
 
-  mBounds = CalculateBounds(*mFrame->StyleBorder()).GetBounds();
+  mBounds = CalculateBounds<nsRect>(*mFrame->StyleBorder());
 }
 
 bool
 nsDisplayBorder::IsInvisibleInRect(const nsRect& aRect) const
 {
   nsRect paddingRect = mFrame->GetPaddingRect() - mFrame->GetPosition() +
     ToReferenceFrame();
   const nsStyleBorder *styleBorder;
@@ -5681,63 +5681,16 @@ nsDisplayBorder::Paint(nsDisplayListBuil
 nsRect
 nsDisplayBorder::GetBounds(nsDisplayListBuilder* aBuilder,
                            bool* aSnap) const
 {
   *aSnap = true;
   return mBounds;
 }
 
-nsRegion
-nsDisplayBorder::CalculateBounds(const nsStyleBorder& aStyleBorder) const
-{
-  nsRect borderBounds(ToReferenceFrame(), mFrame->GetSize());
-  if (aStyleBorder.IsBorderImageLoaded()) {
-    borderBounds.Inflate(aStyleBorder.GetImageOutset());
-    return borderBounds;
-  } else {
-    nsMargin border = aStyleBorder.GetComputedBorder();
-    nsRegion result;
-    if (border.top > 0) {
-      result = nsRect(borderBounds.X(), borderBounds.Y(), borderBounds.Width(), border.top);
-    }
-    if (border.right > 0) {
-      result.OrWith(nsRect(borderBounds.XMost() - border.right, borderBounds.Y(), border.right, borderBounds.Height()));
-    }
-    if (border.bottom > 0) {
-      result.OrWith(nsRect(borderBounds.X(), borderBounds.YMost() - border.bottom, borderBounds.Width(), border.bottom));
-    }
-    if (border.left > 0) {
-      result.OrWith(nsRect(borderBounds.X(), borderBounds.Y(), border.left, borderBounds.Height()));
-    }
-
-    nscoord radii[8];
-    if (mFrame->GetBorderRadii(radii)) {
-      if (border.left > 0 || border.top > 0) {
-        nsSize cornerSize(radii[eCornerTopLeftX], radii[eCornerTopLeftY]);
-        result.OrWith(nsRect(borderBounds.TopLeft(), cornerSize));
-      }
-      if (border.top > 0 || border.right > 0) {
-        nsSize cornerSize(radii[eCornerTopRightX], radii[eCornerTopRightY]);
-        result.OrWith(nsRect(borderBounds.TopRight() - nsPoint(cornerSize.width, 0), cornerSize));
-      }
-      if (border.right > 0 || border.bottom > 0) {
-        nsSize cornerSize(radii[eCornerBottomRightX], radii[eCornerBottomRightY]);
-        result.OrWith(nsRect(borderBounds.BottomRight() - nsPoint(cornerSize.width, cornerSize.height), cornerSize));
-      }
-      if (border.bottom > 0 || border.left > 0) {
-        nsSize cornerSize(radii[eCornerBottomLeftX], radii[eCornerBottomLeftY]);
-        result.OrWith(nsRect(borderBounds.BottomLeft() - nsPoint(0, cornerSize.height), cornerSize));
-      }
-    }
-
-    return result;
-  }
-}
-
 // Given a region, compute a conservative approximation to it as a list
 // of rectangles that aren't vertically adjacent (i.e., vertically
 // adjacent or overlapping rectangles are combined).
 // Right now this is only approximate, some vertically overlapping rectangles
 // aren't guaranteed to be combined.
 static void
 ComputeDisjointRectangles(const nsRegion& aRegion,
                           nsTArray<nsRect>* aRects) {
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -3454,26 +3454,70 @@ public:
   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                          const nsDisplayItemGeometry* aGeometry,
                                          nsRegion* aInvalidRegion) const override;
 
   virtual nsRegion GetTightBounds(nsDisplayListBuilder* aBuilder,
                                   bool* aSnap) const override
   {
     *aSnap = true;
-    return CalculateBounds(*mFrame->StyleBorder());
+    return CalculateBounds<nsRegion>(*mFrame->StyleBorder());
   }
 
 protected:
   void CreateBorderImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                           mozilla::wr::IpcResourceUpdateQueue& aResource,
                                           const StackingContextHelper& aSc,
                                           mozilla::layers::WebRenderLayerManager* aManager,
                                           nsDisplayListBuilder* aDisplayListBuilder);
-  nsRegion CalculateBounds(const nsStyleBorder& aStyleBorder) const;
+  template<typename T>
+  T CalculateBounds(const nsStyleBorder& aStyleBorder) const
+  {
+    nsRect borderBounds(ToReferenceFrame(), mFrame->GetSize());
+    if (aStyleBorder.IsBorderImageLoaded()) {
+      borderBounds.Inflate(aStyleBorder.GetImageOutset());
+      return borderBounds;
+    } else {
+      nsMargin border = aStyleBorder.GetComputedBorder();
+      T result;
+      if (border.top > 0) {
+        result = nsRect(borderBounds.X(), borderBounds.Y(), borderBounds.Width(), border.top);
+      }
+      if (border.right > 0) {
+        result.OrWith(nsRect(borderBounds.XMost() - border.right, borderBounds.Y(), border.right, borderBounds.Height()));
+      }
+      if (border.bottom > 0) {
+        result.OrWith(nsRect(borderBounds.X(), borderBounds.YMost() - border.bottom, borderBounds.Width(), border.bottom));
+      }
+      if (border.left > 0) {
+        result.OrWith(nsRect(borderBounds.X(), borderBounds.Y(), border.left, borderBounds.Height()));
+      }
+
+      nscoord radii[8];
+      if (mFrame->GetBorderRadii(radii)) {
+        if (border.left > 0 || border.top > 0) {
+          nsSize cornerSize(radii[mozilla::eCornerTopLeftX], radii[mozilla::eCornerTopLeftY]);
+          result.OrWith(nsRect(borderBounds.TopLeft(), cornerSize));
+        }
+        if (border.top > 0 || border.right > 0) {
+          nsSize cornerSize(radii[mozilla::eCornerTopRightX], radii[mozilla::eCornerTopRightY]);
+          result.OrWith(nsRect(borderBounds.TopRight() - nsPoint(cornerSize.width, 0), cornerSize));
+        }
+        if (border.right > 0 || border.bottom > 0) {
+          nsSize cornerSize(radii[mozilla::eCornerBottomRightX], radii[mozilla::eCornerBottomRightY]);
+          result.OrWith(nsRect(borderBounds.BottomRight() - nsPoint(cornerSize.width, cornerSize.height), cornerSize));
+        }
+        if (border.bottom > 0 || border.left > 0) {
+          nsSize cornerSize(radii[mozilla::eCornerBottomLeftX], radii[mozilla::eCornerBottomLeftY]);
+          result.OrWith(nsRect(borderBounds.BottomLeft() - nsPoint(0, cornerSize.height), cornerSize));
+        }
+      }
+      return result;
+    }
+  }
 
   mozilla::Array<mozilla::gfx::Color, 4> mColors;
   mozilla::Array<mozilla::LayerCoord, 4> mWidths;
   mozilla::Array<mozilla::LayerSize, 4> mCorners;
   mozilla::Array<uint8_t, 4> mBorderStyles;
   mozilla::LayerRect mRect;
 
   mozilla::Maybe<nsCSSBorderRenderer> mBorderRenderer;