Bug 564991. Part 26: Put background-attachment:fixed backgrounds that propagated to the canvas in their own layer. r=mats,sr=dbaron

This commit is contained in:
Robert O'Callahan 2010-07-16 09:08:06 +12:00
parent 1cbc86420d
commit c5362bf642
6 changed files with 85 additions and 6 deletions

View File

@ -877,6 +877,18 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
&offsetToActiveScrolledRoot); &offsetToActiveScrolledRoot);
NS_ASSERTION(offsetToActiveScrolledRoot == f->GetOffsetTo(activeScrolledRoot), NS_ASSERTION(offsetToActiveScrolledRoot == f->GetOffsetTo(activeScrolledRoot),
"Wrong offset"); "Wrong offset");
if (item->IsFixedAndCoveringViewport(mBuilder)) {
// Make its active scrolled root be the active scrolled root of
// the enclosing viewport, since it shouldn't be scrolled by scrolled
// frames in its document. InvalidateFixedBackgroundFramesFromList in
// nsGfxScrollFrame will not repaint this item when scrolling occurs.
nsIFrame* viewportFrame =
nsLayoutUtils::GetClosestFrameOfType(f, nsGkAtoms::viewportFrame);
NS_ASSERTION(viewportFrame, "no viewport???");
activeScrolledRoot =
nsLayoutUtils::GetActiveScrolledRootFor(viewportFrame, mBuilder->ReferenceFrame(),
&offsetToActiveScrolledRoot);
}
nscolor uniformColor; nscolor uniformColor;
PRBool isUniform = item->IsUniform(mBuilder, &uniformColor); PRBool isUniform = item->IsUniform(mBuilder, &uniformColor);

View File

@ -631,13 +631,26 @@ static PRBool RoundedRectContainsRect(const nsRect& aRoundedRect,
return PR_FALSE; return PR_FALSE;
} }
PRBool
nsDisplayBackground::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove)
{
// Return false if the background was propagated away from this
// frame. We don't want this display item to show up and confuse
// anything.
nsStyleContext* bgSC;
return mIsThemed ||
nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC);
}
PRBool PRBool
nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder) { nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder) {
// theme background overrides any other background // theme background overrides any other background
if (mIsThemed) if (mIsThemed)
return mThemeTransparency == nsITheme::eOpaque; return mThemeTransparency == nsITheme::eOpaque;
nsStyleContext *bgSC; nsStyleContext* bgSC;
if (!nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC)) if (!nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC))
return PR_FALSE; return PR_FALSE;
const nsStyleBackground* bg = bgSC->GetStyleBackground(); const nsStyleBackground* bg = bgSC->GetStyleBackground();
@ -694,7 +707,7 @@ nsDisplayBackground::IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuild
nsPresContext* presContext = mFrame->PresContext(); nsPresContext* presContext = mFrame->PresContext();
nsStyleContext *bgSC; nsStyleContext *bgSC;
PRBool hasBG = PRBool hasBG =
nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC); nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
if (!hasBG) if (!hasBG)
return PR_FALSE; return PR_FALSE;
const nsStyleBackground* bg = bgSC->GetStyleBackground(); const nsStyleBackground* bg = bgSC->GetStyleBackground();

View File

@ -547,6 +547,13 @@ public:
*/ */
virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder) virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder)
{ return PR_FALSE; } { return PR_FALSE; }
/**
* @return PR_TRUE if the contents of this item are rendered fixed relative
* to the nearest viewport *and* they cover the viewport. Only return true
* if the contents actually vary when scrolling in the viewport.
*/
virtual PRBool IsFixedAndCoveringViewport(nsDisplayListBuilder* aBuilder)
{ return PR_FALSE; }
/** /**
* @return LAYER_NONE if BuildLayer will return null. In this case * @return LAYER_NONE if BuildLayer will return null. In this case
@ -1290,13 +1297,16 @@ public:
{ {
aOutFrames->AppendElement(mFrame); aOutFrames->AppendElement(mFrame);
} }
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove);
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder); virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder); virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder);
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor); virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder); virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND) NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
private: protected:
/* Used to cache mFrame->IsThemed() since it isn't a cheap call */ /* Used to cache mFrame->IsThemed() since it isn't a cheap call */
PRPackedBool mIsThemed; PRPackedBool mIsThemed;
nsITheme::Transparency mThemeTransparency; nsITheme::Transparency mThemeTransparency;

View File

@ -249,6 +249,37 @@ nsRect nsCanvasFrame::CanvasArea() const
return result; return result;
} }
PRBool
nsDisplayCanvasBackground::IsFixedAndCoveringViewport(nsDisplayListBuilder* aBuilder)
{
if (mIsThemed)
return PR_FALSE;
nsPresContext* presContext = mFrame->PresContext();
nsStyleContext* bgSC;
PRBool hasBG =
nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
NS_ASSERTION(hasBG, "This item should have been pruned if it has no real background");
if (!hasBG)
return PR_FALSE;
const nsStyleBackground* bg = bgSC->GetStyleBackground();
if (!bg->HasFixedBackground())
return PR_FALSE;
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
const nsStyleBackground::Layer& layer = bg->mLayers[i];
if (layer.mAttachment != NS_STYLE_BG_ATTACHMENT_FIXED &&
!layer.mImage.IsEmpty()) {
return PR_FALSE;
}
}
// The canvas background always covers the (scrolled) area of the
// viewport
return PR_TRUE;
}
void void
nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder, nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx) nsIRenderingContext* aCtx)

View File

@ -171,11 +171,20 @@ public:
mExtraBackgroundColor = NS_RGBA(0,0,0,0); mExtraBackgroundColor = NS_RGBA(0,0,0,0);
} }
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove)
{
return NS_GET_A(mExtraBackgroundColor) > 0 ||
nsDisplayBackground::ComputeVisibility(aBuilder, aVisibleRegion,
aVisibleRegionBeforeMove);
}
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder) virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder)
{ {
return NS_GET_A(mExtraBackgroundColor) == 255 || return NS_GET_A(mExtraBackgroundColor) == 255 ||
nsDisplayBackground::IsOpaque(aBuilder); nsDisplayBackground::IsOpaque(aBuilder);
} }
virtual PRBool IsFixedAndCoveringViewport(nsDisplayListBuilder* aBuilder);
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
{ {
nscolor background; nscolor background;

View File

@ -1555,9 +1555,13 @@ InvalidateFixedBackgroundFramesFromList(nsDisplayListBuilder* aBuilder,
if (sublist) { if (sublist) {
InvalidateFixedBackgroundFramesFromList(aBuilder, *sublist); InvalidateFixedBackgroundFramesFromList(aBuilder, *sublist);
} else if (item->IsVaryingRelativeToMovingFrame(aBuilder)) { } else if (item->IsVaryingRelativeToMovingFrame(aBuilder)) {
nsIFrame* f = item->GetUnderlyingFrame(); if (item->IsFixedAndCoveringViewport(aBuilder)) {
NS_ASSERTION(f, "No underlying frame for varying item?"); // FrameLayerBuilder takes care of scrolling these
f->Invalidate(item->GetVisibleRect() - aBuilder->ToReferenceFrame(f)); } else {
nsIFrame* f = item->GetUnderlyingFrame();
NS_ASSERTION(f, "No underlying frame for varying item?");
f->Invalidate(item->GetVisibleRect() - aBuilder->ToReferenceFrame(f));
}
} }
} }
} }