From 59423727429d788be9f8aff2b3cb2dae0c20966b Mon Sep 17 00:00:00 2001 From: Timothy Nikkel Date: Wed, 26 Jun 2013 11:43:26 -0500 Subject: [PATCH] Bug 695763. Part 3. Invalidate the background images of buttons, fieldsets, and mathml chars if they are not decoded and we are asked to do a sync decode. r=matt.woodrow --- layout/base/nsCSSRendering.cpp | 18 ++++++++++++++++++ layout/base/nsCSSRendering.h | 6 ++++++ layout/base/nsDisplayList.cpp | 14 ++++++++++++++ layout/base/nsDisplayList.h | 10 ++++++++++ layout/forms/nsButtonFrameRenderer.cpp | 13 +++++++++++++ layout/forms/nsFieldSetFrame.cpp | 13 +++++++++++++ layout/mathml/nsMathMLChar.cpp | 13 +++++++++++++ 7 files changed, 87 insertions(+) diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index a42003e1c38b..5fdd560a5731 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -3036,6 +3036,24 @@ nsCSSRendering::GetBackgroundLayerRect(nsPresContext* aPresContext, return state.mFillArea; } +/* static */ bool +nsCSSRendering::AreAllBackgroundImagesDecodedForFrame(nsIFrame* aFrame) +{ + const nsStyleBackground *bg = aFrame->StyleContext()->StyleBackground(); + NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) { + const nsStyleImage* image = &bg->mLayers[i].mImage; + if (image->GetType() == eStyleImageType_Image) { + nsCOMPtr img; + if (NS_SUCCEEDED(image->GetImageData()->GetImage(getter_AddRefs(img)))) { + if (!img->IsDecoded()) { + return false; + } + } + } + } + return true; +} + static void DrawBorderImage(nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, diff --git a/layout/base/nsCSSRendering.h b/layout/base/nsCSSRendering.h index 2a6b8e625285..9661b75cbe91 100644 --- a/layout/base/nsCSSRendering.h +++ b/layout/base/nsCSSRendering.h @@ -396,6 +396,12 @@ struct nsCSSRendering { const nsStyleBackground::Layer& aLayer, uint32_t aFlags); + /** + * Checks if all images that are part of the background for aFrame are + * currently decoded. + */ + static bool AreAllBackgroundImagesDecodedForFrame(nsIFrame* aFrame); + /** * Called when we start creating a display list. The frame tree will not * change until a matching EndFrameTreeLocked is called. diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index d9459c80ceae..4776ac141ca0 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1468,6 +1468,20 @@ void nsDisplayList::Sort(nsDisplayListBuilder* aBuilder, ::Sort(this, Count(), aCmp, aClosure); } +void +nsDisplayItem::AddInvalidRegionForSyncDecodeBackgroundImages( + nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion* aInvalidRegion) +{ + if (aBuilder->ShouldSyncDecodeImages()) { + if (!nsCSSRendering::AreAllBackgroundImagesDecodedForFrame(mFrame)) { + bool snap; + aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap)); + } + } +} + /* static */ bool nsDisplayItem::ForceActiveLayers() { diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index ac37ad4ccca2..9a3cbb525dcc 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -937,6 +937,16 @@ public: } } + /** + * For display items types that just draw a background we use this function + * to do any invalidation that might be needed if we are asked to sync decode + * images. + */ + void AddInvalidRegionForSyncDecodeBackgroundImages( + nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion* aInvalidRegion); + /** * Called when the area rendered by this display item has changed (been * invalidated or changed geometry) since the last paint. This includes diff --git a/layout/forms/nsButtonFrameRenderer.cpp b/layout/forms/nsButtonFrameRenderer.cpp index a139a4983dc5..8b67110713f8 100644 --- a/layout/forms/nsButtonFrameRenderer.cpp +++ b/layout/forms/nsButtonFrameRenderer.cpp @@ -118,6 +118,9 @@ public: virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx); virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap); + virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion *aInvalidRegion) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("ButtonBorderBackground", TYPE_BUTTON_BORDER_BACKGROUND) private: nsButtonFrameRenderer* mBFR; @@ -150,6 +153,16 @@ private: nsButtonFrameRenderer* mBFR; }; +void +nsDisplayButtonBorderBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion *aInvalidRegion) +{ + AddInvalidRegionForSyncDecodeBackgroundImages(aBuilder, aGeometry, aInvalidRegion); + + nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); +} + void nsDisplayButtonBorderBackground::Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) { diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp index 79e4f9d8d910..a518d317ac12 100644 --- a/layout/forms/nsFieldSetFrame.cpp +++ b/layout/forms/nsFieldSetFrame.cpp @@ -194,6 +194,9 @@ public: HitTestState* aState, nsTArray *aOutFrames); virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx); + virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion *aInvalidRegion) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("FieldSetBorderBackground", TYPE_FIELDSET_BORDER_BACKGROUND) }; @@ -215,6 +218,16 @@ nsDisplayFieldSetBorderBackground::Paint(nsDisplayListBuilder* aBuilder, mVisibleRect, aBuilder->GetBackgroundPaintFlags()); } +void +nsDisplayFieldSetBorderBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion *aInvalidRegion) +{ + AddInvalidRegionForSyncDecodeBackgroundImages(aBuilder, aGeometry, aInvalidRegion); + + nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); +} + void nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, diff --git a/layout/mathml/nsMathMLChar.cpp b/layout/mathml/nsMathMLChar.cpp index 4e62732b46fb..8480483a8136 100644 --- a/layout/mathml/nsMathMLChar.cpp +++ b/layout/mathml/nsMathMLChar.cpp @@ -1644,6 +1644,9 @@ public: } #endif + virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion *aInvalidRegion) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx); NS_DISPLAY_DECL_NAME("MathMLCharBackground", TYPE_MATHML_CHAR_BACKGROUND) @@ -1652,6 +1655,16 @@ private: nsRect mRect; }; +void +nsDisplayMathMLCharBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion *aInvalidRegion) +{ + AddInvalidRegionForSyncDecodeBackgroundImages(aBuilder, aGeometry, aInvalidRegion); + + nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); +} + void nsDisplayMathMLCharBackground::Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) {