# HG changeset patch # Parent 0625c68c0abcfe4d10880d15d8fe7d06df3369c9 Bug 1211264. Fallback to rendering dest rect with rotated box shadows. r=mstange diff --git a/gfx/thebes/gfxBlur.cpp b/gfx/thebes/gfxBlur.cpp --- a/gfx/thebes/gfxBlur.cpp +++ b/gfx/thebes/gfxBlur.cpp @@ -444,28 +444,25 @@ CacheBlur(DrawTarget& aDT, BlurCacheData* data = new BlurCacheData(aBoxShadow, aExtendDest, key); if (!gBlurCache->RegisterEntry(data)) { delete data; } } // Blurs a small surface and creates the mask. static already_AddRefed -CreateBlurMask(const IntSize& aRectSize, +CreateBlurMask(const IntSize& aMinSize, RectCornerRadii* aCornerRadii, IntSize aBlurRadius, IntMargin& aExtendDestBy, IntMargin& aSliceBorder, DrawTarget& aDestDrawTarget) { - IntMargin slice; gfxAlphaBoxBlur blur; - IntSize minSize = - ComputeMinSizeForShadowShape(aCornerRadii, aBlurRadius, slice, aRectSize); - IntRect minRect(IntPoint(), minSize); + IntRect minRect(IntPoint(), aMinSize); gfxContext* blurCtx = blur.Init(ThebesRect(Rect(minRect)), IntSize(), aBlurRadius, nullptr, nullptr); if (!blurCtx) { return nullptr; } @@ -483,17 +480,17 @@ CreateBlurMask(const IntSize& aRectSize, IntPoint topLeft; RefPtr result = blur.DoBlur(&aDestDrawTarget, &topLeft); if (!result) { return nullptr; } IntRect expandedMinRect(topLeft, result->GetSize()); aExtendDestBy = expandedMinRect - minRect; - aSliceBorder = slice + aExtendDestBy; + aSliceBorder += aExtendDestBy; MOZ_ASSERT(aSliceBorder.LeftRight() <= expandedMinRect.width); MOZ_ASSERT(aSliceBorder.TopBottom() <= expandedMinRect.height); return result.forget(); } static already_AddRefed @@ -508,56 +505,71 @@ CreateBoxShadow(SourceSurface* aBlurMask return nullptr; } ColorPattern shadowColor(ToDeviceColor(aShadowColor)); boxShadowDT->MaskSurface(shadowColor, aBlurMask, Point(0, 0)); return boxShadowDT->Snapshot(); } -static SourceSurface* +static already_AddRefed GetBlur(DrawTarget& aDT, const IntSize& aRectSize, const IntSize& aBlurRadius, RectCornerRadii* aCornerRadii, const Color& aShadowColor, IntMargin& aExtendDestBy, - IntMargin& aSlice) + IntMargin& aSlice, + gfxContext* aDestinationCtx) { if (!gBlurCache) { gBlurCache = new BlurCache(); } IntSize minSize = ComputeMinSizeForShadowShape(aCornerRadii, aBlurRadius, aSlice, aRectSize); + // We can get seams using the min size rect when drawing to the destination rect + // If we have a rotation on the destination context. In those cases, + // just draw the rotated blur. + bool useDestRect = aDestinationCtx->CurrentMatrix().HasNonTranslationOrFlip(); + if (useDestRect) { + minSize = aRectSize; + } + BlurCacheData* cached = gBlurCache->Lookup(minSize, aBlurRadius, aCornerRadii, aShadowColor, aDT.GetBackendType()); - if (cached) { + if (cached && !useDestRect) { // See CreateBlurMask() for these values aExtendDestBy = cached->mExtendDest; aSlice = aSlice + aExtendDestBy; - return cached->mBlur; + RefPtr blur = cached->mBlur; + return blur.forget(); } RefPtr blurMask = - CreateBlurMask(aRectSize, aCornerRadii, aBlurRadius, aExtendDestBy, aSlice, aDT); + CreateBlurMask(minSize, aCornerRadii, aBlurRadius, aExtendDestBy, aSlice, aDT); if (!blurMask) { return nullptr; } RefPtr boxShadow = CreateBoxShadow(blurMask, aShadowColor); if (!boxShadow) { return nullptr; } - CacheBlur(aDT, minSize, aBlurRadius, aCornerRadii, aShadowColor, aExtendDestBy, boxShadow); - return boxShadow; + if (useDestRect) { + // Since we're just going to paint the actual rect to the destination + aSlice.SizeTo(0, 0, 0, 0); + } else { + CacheBlur(aDT, minSize, aBlurRadius, aCornerRadii, aShadowColor, aExtendDestBy, boxShadow); + } + return boxShadow.forget(); } void gfxAlphaBoxBlur::ShutdownBlurCache() { delete gBlurCache; gBlurCache = nullptr; } @@ -693,17 +705,18 @@ gfxAlphaBoxBlur::BlurRectangle(gfxContex IntRect rect = RoundedToInt(ToRect(aRect)); IntMargin extendDestBy; IntMargin slice; RefPtr boxShadow = GetBlur(destDrawTarget, rect.Size(), blurRadius, aCornerRadii, aShadowColor, - extendDestBy, slice); + extendDestBy, slice, + aDestinationCtx); if (!boxShadow) { return; } destDrawTarget.PushClipRect(ToRect(aDirtyRect)); // Copy the right parts from boxShadow into destDrawTarget. The middle parts // will be stretched, border-image style. diff --git a/layout/reftests/box-shadow/boxshadow-rotated-ref.html b/layout/reftests/box-shadow/boxshadow-rotated-ref.html new file mode 100644 --- /dev/null +++ b/layout/reftests/box-shadow/boxshadow-rotated-ref.html @@ -0,0 +1,15 @@ + + + + + +
+ + diff --git a/layout/reftests/box-shadow/boxshadow-rotated.html b/layout/reftests/box-shadow/boxshadow-rotated.html new file mode 100644 --- /dev/null +++ b/layout/reftests/box-shadow/boxshadow-rotated.html @@ -0,0 +1,16 @@ + + + + + +
+ + diff --git a/layout/reftests/box-shadow/reftest.list b/layout/reftests/box-shadow/reftest.list --- a/layout/reftests/box-shadow/reftest.list +++ b/layout/reftests/box-shadow/reftest.list @@ -19,16 +19,17 @@ random-if(d2d) == boxshadow-onecorner.ht random-if(d2d) == boxshadow-twocorners.html boxshadow-twocorners-ref.html random-if(d2d) == boxshadow-threecorners.html boxshadow-threecorners-ref.html == boxshadow-skiprect.html boxshadow-skiprect-ref.html == boxshadow-opacity.html boxshadow-opacity-ref.html == boxshadow-color-rounding.html boxshadow-color-rounding-ref.html == boxshadow-color-rounding-middle.html boxshadow-color-rounding-middle-ref.html fuzzy-if(OSX==1010,1,24) == boxshadow-large-border-radius.html boxshadow-large-border-radius-ref.html # Bug 1209649 == boxshadow-border-radius-int.html boxshadow-border-radius-int-ref.html +fuzzy(24,3072) == boxshadow-rotated.html boxshadow-rotated-ref.html # Bug 1211264 == overflow-not-scrollable-1.html overflow-not-scrollable-1-ref.html == overflow-not-scrollable-1.html overflow-not-scrollable-1-ref2.html == overflow-not-scrollable-2.html overflow-not-scrollable-2-ref.html fails-if(B2G||Mulet) == 611574-1.html 611574-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop fails-if(B2G||Mulet) == 611574-2.html 611574-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop fuzzy-if(winWidget,5,30) == fieldset.html fieldset-ref.html # minor anti-aliasing problem on Windows fuzzy-if(winWidget,5,30) == fieldset-inset.html fieldset-inset-ref.html # minor anti-aliasing problem on Windows