Bug 820246 - Split nsDisplayCanvasBackground into separate color and image items. r=roc

This commit is contained in:
Matt Woodrow 2012-12-13 14:15:55 +13:00
parent b604f8c8d2
commit 012ebe70a2
7 changed files with 87 additions and 58 deletions

View File

@ -9,7 +9,8 @@ DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BORDER_BACKGROUND)
DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BOX_SHADOW_OUTER)
DECLARE_DISPLAY_ITEM_TYPE(BUTTON_FOREGROUND)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGROUND)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGROUND_COLOR)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGROUND_IMAGE)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS_FOCUS)
DECLARE_DISPLAY_ITEM_TYPE(CARET)
DECLARE_DISPLAY_ITEM_TYPE(CHECKED_CHECKBOX)

View File

@ -49,6 +49,7 @@
#include "nsIViewManager.h"
#include "ImageLayers.h"
#include "ImageContainer.h"
#include "nsCanvasFrame.h"
#include "mozilla/StandardInteger.h"
@ -2083,14 +2084,22 @@ static void CheckForBorderItem(nsDisplayItem *aItem, uint32_t& aFlags)
void
nsDisplayBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) {
PaintInternal(aBuilder, aCtx, mVisibleRect, nullptr);
}
void
nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx, const nsRect& aBounds,
nsRect* aClipRect) {
nsPoint offset = ToReferenceFrame();
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
CheckForBorderItem(this, flags);
nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
mVisibleRect,
aBounds,
nsRect(offset, mFrame->GetSize()),
flags, nullptr, mLayer);
flags, aClipRect, mLayer);
}
void nsDisplayBackgroundImage::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
@ -2149,6 +2158,10 @@ nsDisplayBackgroundImage::GetBoundsInternal() {
}
nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
if (mFrame->GetType() == nsGkAtoms::canvasFrame) {
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
borderBox = frame->CanvasArea() + ToReferenceFrame();
}
const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer];
return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
borderBox, *mBackgroundStyle, layer);

View File

@ -1913,6 +1913,9 @@ protected:
gfxRect* aDestRect);
nsRect GetBoundsInternal();
void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
const nsRect& aBounds, nsRect* aClipRect);
// Cache the result of nsCSSRendering::FindBackground. Always null if
// mIsThemed is true or if FindBackground returned false.
const nsStyleBackground* mBackgroundStyle;

View File

@ -4831,8 +4831,8 @@ AddCanvasBackgroundColor(const nsDisplayList& aList, nsIFrame* aCanvasFrame,
{
for (nsDisplayItem* i = aList.GetBottom(); i; i = i->GetAbove()) {
if (i->GetUnderlyingFrame() == aCanvasFrame &&
i->GetType() == nsDisplayItem::TYPE_CANVAS_BACKGROUND) {
nsDisplayCanvasBackground* bg = static_cast<nsDisplayCanvasBackground*>(i);
i->GetType() == nsDisplayItem::TYPE_CANVAS_BACKGROUND_COLOR) {
nsDisplayCanvasBackgroundColor* bg = static_cast<nsDisplayCanvasBackgroundColor*>(i);
bg->SetExtraBackgroundColor(aColor);
return true;
}

View File

@ -178,6 +178,19 @@ nsRect nsCanvasFrame::CanvasArea() const
return result;
}
void
nsDisplayCanvasBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
nsPoint offset = ToReferenceFrame();
nsRect bgClipRect = frame->CanvasArea() + offset;
if (NS_GET_A(mColor) > 0) {
aCtx->SetColor(mColor);
aCtx->FillRect(bgClipRect);
}
}
static void BlitSurface(gfxContext* aDest, const gfxRect& aRect, gfxASurface* aSource)
{
aDest->Translate(gfxPoint(aRect.x, aRect.y));
@ -189,19 +202,13 @@ static void BlitSurface(gfxContext* aDest, const gfxRect& aRect, gfxASurface* aS
}
void
nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
nsPoint offset = ToReferenceFrame();
nsRect bgClipRect = frame->CanvasArea() + offset;
if (mIsBottommostLayer && NS_GET_A(mExtraBackgroundColor) > 0) {
aCtx->SetColor(mExtraBackgroundColor);
aCtx->FillRect(bgClipRect);
}
bool snap;
nsRect bounds = GetBounds(aBuilder, &snap);
nsRenderingContext context;
nsRefPtr<gfxContext> dest = aCtx->ThebesContext();
nsRefPtr<gfxASurface> surf;
@ -230,15 +237,14 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
}
#endif
nsCSSRendering::PaintBackground(mFrame->PresContext(), surf ? context : *aCtx, mFrame,
surf ? bounds : mVisibleRect,
nsRect(offset, mFrame->GetSize()),
aBuilder->GetBackgroundPaintFlags(),
&bgClipRect, mLayer);
PaintInternal(aBuilder,
surf ? &context : aCtx,
surf ? bgClipRect: mVisibleRect,
&bgClipRect);
if (surf) {
BlitSurface(dest, destRect, surf);
GetUnderlyingFrame()->Properties().Set(nsIFrame::CachedBackgroundImage(), surf.forget().get());
frame->Properties().Set(nsIFrame::CachedBackgroundImage(), surf.forget().get());
}
}
@ -302,11 +308,14 @@ nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsCSSRendering::FindBackground(PresContext(), this, &bgSC)) {
bg = bgSC->GetStyleBackground();
}
aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayCanvasBackgroundColor(aBuilder, this));
// Create separate items for each background layer.
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
rv = aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayCanvasBackground(aBuilder, this, i,
isThemed, bg));
new (aBuilder) nsDisplayCanvasBackgroundImage(aBuilder, this, i,
isThemed, bg));
NS_ENSURE_SUCCESS(rv, rv);
}
}

View File

@ -122,13 +122,11 @@ protected:
* We can also paint an "extra background color" behind the normal
* background.
*/
class nsDisplayCanvasBackground : public nsDisplayBackgroundImage {
class nsDisplayCanvasBackgroundColor : public nsDisplayItem {
public:
nsDisplayCanvasBackground(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
uint32_t aLayer, bool aIsThemed,
const nsStyleBackground* aBackgroundStyle)
: nsDisplayBackgroundImage(aBuilder, aFrame, aLayer, aIsThemed, aBackgroundStyle),
mExtraBackgroundColor(NS_RGBA(0,0,0,0))
nsDisplayCanvasBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame)
: nsDisplayItem(aBuilder, aFrame)
, mColor(NS_RGBA(0,0,0,0))
{
}
@ -136,27 +134,19 @@ public:
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE
{
return NS_GET_A(mExtraBackgroundColor) > 0 ||
nsDisplayBackgroundImage::ComputeVisibility(aBuilder, aVisibleRegion,
aAllowVisibleRegionExpansion);
return NS_GET_A(mColor) > 0;
}
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) MOZ_OVERRIDE
{
if (NS_GET_A(mExtraBackgroundColor) == 255) {
if (NS_GET_A(mColor) == 255) {
return nsRegion(GetBounds(aBuilder, aSnap));
}
return nsDisplayBackgroundImage::GetOpaqueRegion(aBuilder, aSnap);
return nsRegion();
}
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE
{
nscolor background;
if (!nsDisplayBackgroundImage::IsUniform(aBuilder, &background))
return false;
NS_ASSERTION(background == NS_RGBA(0,0,0,0),
"The nsDisplayBackground for a canvas frame doesn't paint "
"its background color normally");
*aColor = mExtraBackgroundColor;
*aColor = mColor;
return true;
}
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE
@ -171,16 +161,6 @@ public:
// We need to override so we don't consider border-radius.
aOutFrames->AppendElement(mFrame);
}
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
{
// Put background-attachment:fixed canvas background images in their own
// compositing layer. Since we know their background painting area can't
// change (unless the viewport size itself changes), async scrolling
// will work well.
return mBackgroundStyle &&
mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
!mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty();
}
virtual void NotifyRenderingChanged() MOZ_OVERRIDE
{
mFrame->Properties().Delete(nsIFrame::CachedBackgroundImage());
@ -188,20 +168,43 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE;
// We still need to paint a background color as well as an image for this item,
// so we can't support this yet.
virtual bool SupportsOptimizingToImage() { return false; }
void SetExtraBackgroundColor(nscolor aColor)
{
mExtraBackgroundColor = aColor;
mColor = aColor;
}
NS_DISPLAY_DECL_NAME("CanvasBackground", TYPE_CANVAS_BACKGROUND)
NS_DISPLAY_DECL_NAME("CanvasBackgroundColor", TYPE_CANVAS_BACKGROUND_COLOR)
private:
nscolor mExtraBackgroundColor;
nscolor mColor;
};
class nsDisplayCanvasBackgroundImage : public nsDisplayBackgroundImage {
public:
nsDisplayCanvasBackgroundImage(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
uint32_t aLayer, bool aIsThemed, const nsStyleBackground* aBg)
: nsDisplayBackgroundImage(aBuilder, aFrame, aLayer, aIsThemed, aBg)
{}
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
{
// Put background-attachment:fixed canvas background images in their own
// compositing layer. Since we know their background painting area can't
// change (unless the viewport size itself changes), async scrolling
// will work well.
return mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
!mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty();
}
// We still need to paint a background color as well as an image for this item,
// so we can't support this yet.
virtual bool SupportsOptimizingToImage() MOZ_OVERRIDE { return false; }
NS_DISPLAY_DECL_NAME("CanvasBackgroundImage", TYPE_CANVAS_BACKGROUND_IMAGE)
};
#endif /* nsCanvasFrame_h___ */

View File

@ -1,4 +1,4 @@
random-if(bug685516) == background-image-zoom-1.html background-image-zoom-1-ref.html
random-if(bug685516) fuzzy-if(Android,4,15) == background-image-zoom-1.html background-image-zoom-1-ref.html
== background-image-zoom-2.html about:blank
== image-zoom-1.html image-zoom-1-ref.html
== image-zoom-2.html image-zoom-1-ref.html