Bug 757346 - Change from clipping the mask to drawing it. r=roc
--- 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