Bug 1476843 - Use FillRoundedRect instead of creating a path when possible. r?Bas draft
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 19 Jul 2018 14:54:50 +1200
changeset 820179 fa10cee049d6c9aec11d3c01ef680b0710c5d459
parent 819595 f75d65d2a63ad19f26df88af9ea8693b0441c26c
push id116741
push usermwoodrow@mozilla.com
push dateThu, 19 Jul 2018 02:55:28 +0000
reviewersBas
bugs1476843
milestone63.0a1
Bug 1476843 - Use FillRoundedRect instead of creating a path when possible. r?Bas MozReview-Commit-ID: 4H9DF57fEvg
gfx/thebes/gfxBlur.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsImageFrame.cpp
layout/painting/DisplayItemClip.cpp
layout/painting/DisplayItemClip.h
layout/painting/nsCSSRendering.cpp
layout/painting/nsDisplayList.cpp
--- a/gfx/thebes/gfxBlur.cpp
+++ b/gfx/thebes/gfxBlur.cpp
@@ -536,19 +536,18 @@ CreateBoxShadow(DrawTarget* aDestDrawTar
     blur.InitDrawTarget(aDestDrawTarget, blurRect, zeroSpread, aBlurRadius);
   if (!blurDT) {
     return nullptr;
   }
 
   ColorPattern black(Color(0.f, 0.f, 0.f, 1.f));
 
   if (aCornerRadii) {
-    RefPtr<Path> roundedRect =
-      MakePathForRoundedRect(*blurDT, minRect, *aCornerRadii);
-    blurDT->Fill(roundedRect, black);
+    RoundedRect roundedRect(minRect, *aCornerRadii);
+    blurDT->FillRoundedRect(roundedRect, black);
   } else {
     blurDT->FillRect(minRect, black);
   }
 
   IntPoint topLeft;
   RefPtr<SourceSurface> result = blur.DoBlur(&aShadowColor, &topLeft);
   if (!result) {
     return nullptr;
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -382,16 +382,24 @@ BulletRenderer::Paint(gfxContext& aRende
                                           mDest, aDirtyRect,
                                           /* no SVGImageContext */ Nothing(),
                                           aFlags);
   }
 
   if (IsPathType()) {
     DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
 
+    if (mListStyleType == NS_STYLE_LIST_STYLE_DISC) {
+      Size halfDim = mPathRect.Size().ToUnknownSize() / 2.f;
+      RoundedRect rect(mPathRect.ToUnknownRect(),
+                       RectCornerRadii(halfDim.width, halfDim.height));
+      drawTarget->FillRoundedRect(rect, ColorPattern(ToDeviceColor(mColor)));
+      return ImgDrawResult::SUCCESS;
+    }
+
     if (!mPath) {
       RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder();
       switch (mListStyleType) {
       case NS_STYLE_LIST_STYLE_CIRCLE:
       case NS_STYLE_LIST_STYLE_DISC:
         AppendEllipseToPath(builder, mPathRect.Center().ToUnknownPoint(), mPathRect.Size().ToUnknownSize());
         break;
       case NS_STYLE_LIST_STYLE_SQUARE:
@@ -411,19 +419,17 @@ BulletRenderer::Paint(gfxContext& aRende
     case NS_STYLE_LIST_STYLE_SQUARE:
     case NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED:
     case NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN:
       drawTarget->Fill(mPath, ColorPattern(ToDeviceColor(mColor)));
       break;
     default:
       MOZ_CRASH("unreachable");
     }
-  }
-
-  if (IsTextType()) {
+  } else if (IsTextType()) {
     PaintTextToContext(aFrame, &aRenderingContext, aDisableSubpixelAA);
   }
 
   return ImgDrawResult::SUCCESS;
 }
 
 void
 BulletRenderer::PaintTextToContext(nsIFrame* aFrame,
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1551,20 +1551,19 @@ nsImageFrame::DisplayAltFeedback(gfxCont
       drawTarget->StrokeRect(devPxRect, color);
 
       // filled circle in bottom right quadrant of stroked rect:
       nscoord twoPX = nsPresContext::CSSPixelsToAppUnits(2);
       rect = nsRect(iconXPos + size/2, inner.y + size/2,
                     size/2 - twoPX, size/2 - twoPX);
       devPxRect =
         ToRect(nsLayoutUtils::RectToGfxRect(rect, PresContext()->AppUnitsPerDevPixel()));
-      RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder();
-      AppendEllipseToPath(builder, devPxRect.Center(), devPxRect.Size());
-      RefPtr<Path> ellipse = builder->Finish();
-      drawTarget->Fill(ellipse, color);
+      RoundedRect roundedRect(devPxRect, RectCornerRadii(devPxRect.width / 2.f,
+                                                         devPxRect.height / 2.f));
+      drawTarget->FillRoundedRect(roundedRect, color);
     }
 
     // Reduce the inner rect by the width of the icon, and leave an
     // additional ICON_PADDING pixels for padding
     int32_t paddedIconSize =
       nsPresContext::CSSPixelsToAppUnits(ICON_SIZE + ICON_PADDING);
     if (wm.IsVertical()) {
       inner.y += paddedIconSize;
--- a/layout/painting/DisplayItemClip.cpp
+++ b/layout/painting/DisplayItemClip.cpp
@@ -133,21 +133,18 @@ DisplayItemClip::FillIntersectionOfRound
   if (!end) {
     return;
   }
 
   // Push clips for any rects that come BEFORE the rect at |aEnd - 1|, if any:
   ApplyRoundedRectClipsTo(aContext, aAppUnitsPerDevPixel, 0, end - 1);
 
   // Now fill the rect at |aEnd - 1|:
-  RefPtr<Path> roundedRect = MakeRoundedRectPath(aDrawTarget,
-                                                 aAppUnitsPerDevPixel,
-                                                 mRoundedClipRects[end - 1]);
   ColorPattern color(ToDeviceColor(aColor));
-  aDrawTarget.Fill(roundedRect, color);
+  FillRoundedRectPath(aDrawTarget, aAppUnitsPerDevPixel, mRoundedClipRects[end - 1], color);
 
   // Finally, pop any clips that we may have pushed:
   for (uint32_t i = 0; i < end - 1; ++i) {
     aContext->PopClip();
   }
 }
 
 already_AddRefed<Path>
@@ -158,16 +155,30 @@ DisplayItemClip::MakeRoundedRectPath(Dra
   RectCornerRadii pixelRadii;
   nsCSSRendering::ComputePixelRadii(aRoundRect.mRadii, A2D, &pixelRadii);
 
   Rect rect = NSRectToSnappedRect(aRoundRect.mRect, A2D, aDrawTarget);
 
   return MakePathForRoundedRect(aDrawTarget, rect, pixelRadii);
 }
 
+void
+DisplayItemClip::FillRoundedRectPath(DrawTarget& aDrawTarget,
+                                     int32_t A2D,
+                                     const RoundedRect &aRoundRect,
+                                     const Pattern& aFill) const
+{
+  RectCornerRadii pixelRadii;
+  nsCSSRendering::ComputePixelRadii(aRoundRect.mRadii, A2D, &pixelRadii);
+
+  gfx::RoundedRect rect(NSRectToSnappedRect(aRoundRect.mRect, A2D, aDrawTarget),
+                        pixelRadii);
+  aDrawTarget.FillRoundedRect(rect, aFill);
+}
+
 nsRect
 DisplayItemClip::ApproximateIntersectInward(const nsRect& aRect) const
 {
   nsRect r = aRect;
   if (mHaveClipRect) {
     r.IntersectRect(r, mClipRect);
   }
   for (uint32_t i = 0, iEnd = mRoundedClipRects.Length();
--- a/layout/painting/DisplayItemClip.h
+++ b/layout/painting/DisplayItemClip.h
@@ -93,16 +93,20 @@ public:
   // Draw (fill) the rounded rects in this clip to aContext
   void FillIntersectionOfRoundedRectClips(gfxContext* aContext,
                                           const Color& aColor,
                                           int32_t aAppUnitsPerDevPixel) const;
   // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext
   already_AddRefed<Path> MakeRoundedRectPath(DrawTarget& aDrawTarget,
                                                   int32_t A2D,
                                                   const RoundedRect &aRoundRect) const;
+  void FillRoundedRectPath(DrawTarget& aDrawTarget,
+                           int32_t A2D,
+                           const RoundedRect &aRoundRect,
+                           const gfx::Pattern& aFill) const;
 
   // Returns true if the intersection of aRect and this clip region is
   // non-empty. This is precise for DisplayItemClips with at most one
   // rounded rectangle. When multiple rounded rectangles are present, we just
   // check that the rectangle intersects all of them (but possibly in different
   // places). So it may return true when the correct answer is false.
   bool MayIntersect(const nsRect& aRect) const;
 
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -2470,17 +2470,18 @@ SetupImageLayerClip(nsCSSRendering::Imag
       MakePathForRoundedRect(*aCtx->GetDrawTarget(), bgAreaGfx,
                              aClipState.mClippedRadii);
     aCtx->Clip(roundedRect);
   }
 }
 
 static void
 DrawBackgroundColor(nsCSSRendering::ImageLayerClipState& aClipState,
-                    gfxContext *aCtx, nscoord aAppUnitsPerPixel)
+                    gfxContext *aCtx, nscoord aAppUnitsPerPixel,
+                    const Color& aColor)
 {
   if (aClipState.mDirtyRectInDevPx.IsEmpty()) {
     // Our caller won't draw anything under this condition, so no need
     // to set more up.
     return;
   }
 
   DrawTarget* drawTarget = aCtx->GetDrawTarget();
@@ -2518,20 +2519,20 @@ DrawBackgroundColor(nsCSSRendering::Imag
       aClipState.mAdditionalBGClipArea, aAppUnitsPerPixel);
     bgAdditionalAreaGfx.Round();
     gfxUtils::ConditionRect(bgAdditionalAreaGfx);
     aCtx->NewPath();
     aCtx->Rectangle(bgAdditionalAreaGfx, true);
     aCtx->Clip();
   }
 
-  RefPtr<Path> roundedRect =
-    MakePathForRoundedRect(*drawTarget, bgAreaGfx, aClipState.mClippedRadii);
-  aCtx->SetPath(roundedRect);
-  aCtx->Fill();
+
+  RoundedRect roundedRect(bgAreaGfx, aClipState.mClippedRadii);
+  drawTarget->FillRoundedRect(roundedRect, ColorPattern(aColor),
+                              DrawOptions(1.0f, CompositionOp::OP_OVER, aCtx->CurrentAntialiasMode()));
   aCtx->Restore();
 }
 
 nscolor
 nsCSSRendering::DetermineBackgroundColor(nsPresContext* aPresContext,
                                          ComputedStyle* aComputedStyle,
                                          nsIFrame* aFrame,
                                          bool& aDrawBackgroundImage,
@@ -2709,17 +2710,17 @@ nsCSSRendering::PaintStyleImageLayerWith
     aRenderingCtx.SetColor(Color::FromABGR(bgColor));
   }
 
   // If there is no background image, draw a color.  (If there is
   // neither a background image nor a color, we wouldn't have gotten
   // this far.)
   if (!drawBackgroundImage) {
     if (!isCanvasFrame) {
-      DrawBackgroundColor(clipState, &aRenderingCtx, appUnitsPerPixel);
+      DrawBackgroundColor(clipState, &aRenderingCtx, appUnitsPerPixel, Color::FromABGR(bgColor));
     }
     return ImgDrawResult::SUCCESS;
   }
 
   if (layers.mImageCount < 1) {
     // Return if there are no background layers, all work from this point
     // onwards happens iteratively on these.
     return ImgDrawResult::SUCCESS;
@@ -2741,17 +2742,17 @@ nsCSSRendering::PaintStyleImageLayerWith
       aParams.frame->AssociateImage(layers.mLayers[i].mImage,
                                     &aParams.presCtx, 0);
     }
   }
 
   // The background color is rendered over the entire dirty area,
   // even if the image isn't.
   if (drawBackgroundColor && !isCanvasFrame) {
-    DrawBackgroundColor(clipState, &aRenderingCtx, appUnitsPerPixel);
+    DrawBackgroundColor(clipState, &aRenderingCtx, appUnitsPerPixel, Color::FromABGR(bgColor));
   }
 
   // Compute the outermost boundary of the area that might be painted.
   // Same coordinate space as aParams.borderArea & aParams.bgClipRect.
   Sides skipSides = aParams.frame->GetSkipSides();
   nsRect paintBorderArea =
     BoxDecorationRectForBackground(aParams.frame, aParams.borderArea,
                                      skipSides, &aBorder);
@@ -4567,20 +4568,18 @@ nsContextBoxBlur::BlurRectangle(gfxConte
     return;
   }
 
   Rect shadowGfxRect = NSRectToRect(aRect, aAppUnitsPerDevPixel);
 
   if (aBlurRadius <= 0) {
     ColorPattern color(ToDeviceColor(aShadowColor));
     if (aCornerRadii) {
-      RefPtr<Path> roundedRect = MakePathForRoundedRect(aDestDrawTarget,
-                                                        shadowGfxRect,
-                                                        *aCornerRadii);
-      aDestDrawTarget.Fill(roundedRect, color);
+      RoundedRect roundedRect(shadowGfxRect, *aCornerRadii);
+      aDestDrawTarget.FillRoundedRect(roundedRect, color);
     } else {
       aDestDrawTarget.FillRect(shadowGfxRect, color);
     }
     return;
   }
 
   gfxFloat scaleX = 1;
   gfxFloat scaleY = 1;
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -4794,20 +4794,18 @@ nsDisplayBackgroundColor::PaintWithClip(
     aClip.AppendRoundedRects(&roundedRect);
 
     bool pushedClip = false;
     if (!fillRect.Contains(roundedRect[0].mRect)) {
       dt->PushClipRect(bounds);
       pushedClip = true;
     }
 
-    RefPtr<Path> path = aClip.MakeRoundedRectPath(*aCtx->GetDrawTarget(),
-                                                  A2D,
-                                                  roundedRect[0]);
-    dt->Fill(path, fill);
+    aClip.FillRoundedRectPath(*aCtx->GetDrawTarget(),
+                              A2D, roundedRect[0], fill);
     if (pushedClip) {
       dt->PopClip();
     }
   } else {
     dt->FillRect(bounds, fill);
   }
 }