Bug 757346 - Change from clipping the mask to drawing it. r=roc
authorNicholas Cameron <ncameron@mozilla.com>
Sun, 27 May 2012 16:55:22 -0400
changeset 95064 602c1435026d796555e6307116030a8f8c18ff3b
parent 95063 e1a1d40f2246333ba95fc705d938007d00a07b90
child 95065 4c3f2ddd82e8c35cbababbbb2004571aea077be4
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersroc
bugs757346
milestone15.0a1
Bug 757346 - Change from clipping the mask to drawing it. r=roc
layout/base/FrameLayerBuilder.cpp
layout/base/FrameLayerBuilder.h
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -2633,32 +2633,55 @@ FrameLayerBuilder::Clip::ApplyRectTo(gfx
 void
 FrameLayerBuilder::Clip::ApplyRoundedRectsTo(gfxContext* aContext,
                                              PRInt32 A2D,
                                              PRUint32 aBegin, PRUint32 aEnd) const
 {
   aEnd = NS_MIN<PRUint32>(aEnd, mRoundedClipRects.Length());
 
   for (PRUint32 i = aBegin; i < aEnd; ++i) {
-    const Clip::RoundedRect &rr = mRoundedClipRects[i];
-
-    gfxCornerSizes pixelRadii;
-    nsCSSRendering::ComputePixelRadii(rr.mRadii, A2D, &pixelRadii);
-
-    gfxRect clip = nsLayoutUtils::RectToGfxRect(rr.mRect, A2D);
-    clip.Round();
-    clip.Condition();
-    // REVIEW: This might make clip empty.  Is that OK?
-
-    aContext->NewPath();
-    aContext->RoundedRectangle(clip, pixelRadii);
+    AddRoundedRectPathTo(aContext, A2D, mRoundedClipRects[i]);
     aContext->Clip();
   }
 }
 
+void
+FrameLayerBuilder::Clip::DrawRoundedRectsTo(gfxContext* aContext,
+                                            PRInt32 A2D,
+                                            PRUint32 aBegin, PRUint32 aEnd) const
+{
+  aEnd = NS_MIN<PRUint32>(aEnd, mRoundedClipRects.Length());
+
+  if (aEnd - aBegin == 0)
+    return;
+
+  // If there is just one rounded rect we can just fill it, if there are more then we
+  // must clip the rest to get the intersection of clips
+  ApplyRoundedRectsTo(aContext, A2D, aBegin, aEnd - 1);
+  AddRoundedRectPathTo(aContext, A2D, mRoundedClipRects[aEnd - 1]);
+  aContext->Fill();
+}
+
+void
+FrameLayerBuilder::Clip::AddRoundedRectPathTo(gfxContext* aContext,
+                                              PRInt32 A2D,
+                                              const RoundedRect &aRoundRect) const
+{
+  gfxCornerSizes pixelRadii;
+  nsCSSRendering::ComputePixelRadii(aRoundRect.mRadii, A2D, &pixelRadii);
+
+  gfxRect clip = nsLayoutUtils::RectToGfxRect(aRoundRect.mRect, A2D);
+  clip.Round();
+  clip.Condition();
+  // REVIEW: This might make clip empty.  Is that OK?
+
+  aContext->NewPath();
+  aContext->RoundedRectangle(clip, pixelRadii);
+}
+
 nsRect
 FrameLayerBuilder::Clip::ApproximateIntersect(const nsRect& aRect) const
 {
   nsRect r = aRect;
   if (mHaveClipRect) {
     r.IntersectRect(r, mClipRect);
   }
   for (PRUint32 i = 0, iEnd = mRoundedClipRects.Length();
@@ -2852,22 +2875,19 @@ ContainerState::SetupMaskLayer(Layer *aL
   gfxMatrix scale;
   scale.Scale(mParameters.mXScale, mParameters.mYScale);
   context->Multiply(scale);
 
   // useful for debugging, make masked areas semi-opaque
   //context->SetColor(gfxRGBA(0, 0, 0, 0.3));
   //context->Paint();
 
-  PRInt32 A2D = mContainerFrame->PresContext()->AppUnitsPerDevPixel();
-  aClip.ApplyRoundedRectsTo(context, A2D, 0, aRoundedRectClipCount);
-
-  // paint through the clipping rects with alpha to create the mask
-  context->SetColor(gfxRGBA(0, 0, 0, 1));
-  context->Paint();
+  // paint the clipping rects with alpha to create the mask
+  context->SetColor(gfxRGBA(0, 0, 0, 1));  PRInt32 A2D = mContainerFrame->PresContext()->AppUnitsPerDevPixel();
+  aClip.DrawRoundedRectsTo(context, A2D, 0, aRoundedRectClipCount);
 
   // build the image and container
   nsRefPtr<ImageContainer> container = aLayer->Manager()->CreateImageContainer();
   NS_ASSERTION(container, "Could not create image container for mask layer.");
   static const Image::Format format = Image::CAIRO_SURFACE;
   nsRefPtr<Image> image = container->CreateImage(&format, 1);
   NS_ASSERTION(image, "Could not create image container for mask layer.");
   CairoImage::Data data;
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -368,16 +368,23 @@ public:
 
     void ApplyRectTo(gfxContext* aContext, PRInt32 A2D) const;
     // Applies the rounded rects in this Clip to aContext
     // Will only apply rounded rects from aBegin (inclusive) to aEnd
     // (exclusive) or the number of rounded rects, whichever is smaller.
     void ApplyRoundedRectsTo(gfxContext* aContext, PRInt32 A2DPRInt32,
                              PRUint32 aBegin, PRUint32 aEnd) const;
 
+    // Draw (fill) the rounded rects in this clip to aContext
+    void DrawRoundedRectsTo(gfxContext* aContext, PRInt32 A2D,
+                            PRUint32 aBegin, PRUint32 aEnd) const;
+    // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext
+    void AddRoundedRectPathTo(gfxContext* aContext, PRInt32 A2D,
+                              const RoundedRect &aRoundRect) const;
+
     // Return a rectangle contained in the intersection of aRect with this
     // clip region. Tries to return the largest possible rectangle, but may
     // not succeed.
     nsRect ApproximateIntersect(const nsRect& aRect) const;
 
     // Returns false if aRect is definitely not clipped by a rounded corner in
     // this clip. Returns true if aRect is clipped by a rounded corner in this
     // clip or it can not be quickly determined that it is not clipped by a