зеркало из https://github.com/mozilla/gecko-dev.git
Bug 572613. Avoid creating a SolidColor display item when possible by poking the color into the canvas background display item. r=tnikkel
This commit is contained in:
Родитель
2e3d02e038
Коммит
2ac3c549db
|
@ -2160,8 +2160,11 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
|
|||
|
||||
// For canvas frames (in the CSS sense) we draw the background color using
|
||||
// a solid color item that gets added in nsLayoutUtils::PaintFrame,
|
||||
// PresShell::RenderDocument, or nsSubDocumentFrame::BuildDisplayList
|
||||
// (bug 488242).
|
||||
// or nsSubDocumentFrame::BuildDisplayList (bug 488242). (The solid
|
||||
// color may be moved into nsDisplayCanvasBackground by
|
||||
// nsPresShell::AddCanvasBackgroundColorItem, and painted by
|
||||
// nsDisplayCanvasBackground directly.) Either way we don't need to
|
||||
// paint the background color here.
|
||||
PRBool isCanvasFrame = IsCanvasFrame(aForFrame);
|
||||
|
||||
// Determine whether we are drawing background images and/or
|
||||
|
|
|
@ -1275,7 +1275,9 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
|
|||
// an nsPageContentFrame. We only want to add the canvas background color
|
||||
// item once, for the nsPageContentFrame.
|
||||
|
||||
// Add the canvas background color.
|
||||
// Add the canvas background color to the bottom of the list. This
|
||||
// happens after we've built the list so that AddCanvasBackgroundColorItem
|
||||
// can monkey with the contents if necessary.
|
||||
rv = presShell->AddCanvasBackgroundColorItem(
|
||||
builder, list, aFrame, canvasArea, aBackstop);
|
||||
}
|
||||
|
|
|
@ -5713,6 +5713,24 @@ PresShell::RenderSelection(nsISelection* aSelection,
|
|||
aScreenRect);
|
||||
}
|
||||
|
||||
static PRBool
|
||||
AddCanvasBackgroundColor(const nsDisplayList& aList, nsIFrame* aCanvasFrame,
|
||||
nscolor aColor)
|
||||
{
|
||||
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);
|
||||
bg->SetExtraBackgroundColor(aColor);
|
||||
return PR_TRUE;
|
||||
}
|
||||
nsDisplayList* sublist = i->GetList();
|
||||
if (sublist && AddCanvasBackgroundColor(*sublist, aCanvasFrame, aColor))
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult PresShell::AddCanvasBackgroundColorItem(nsDisplayListBuilder& aBuilder,
|
||||
nsDisplayList& aList,
|
||||
nsIFrame* aFrame,
|
||||
|
@ -5730,6 +5748,23 @@ nsresult PresShell::AddCanvasBackgroundColorItem(nsDisplayListBuilder& aBuilder,
|
|||
return NS_OK;
|
||||
|
||||
nscolor bgcolor = NS_ComposeColors(aBackstopColor, mCanvasBackgroundColor);
|
||||
|
||||
// To make layers work better, we want to avoid having a big non-scrolled
|
||||
// color background behind a scrolled transparent background. Instead,
|
||||
// we'll try to move the color background into the scrolled content
|
||||
// by making nsDisplayCanvasBackground paint it.
|
||||
if (!aFrame->GetParent()) {
|
||||
nsIScrollableFrame* sf =
|
||||
aFrame->PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
|
||||
if (sf) {
|
||||
nsCanvasFrame* canvasFrame = do_QueryFrame(sf->GetScrolledFrame());
|
||||
if (canvasFrame && canvasFrame->IsVisibleForPainting(&aBuilder)) {
|
||||
if (AddCanvasBackgroundColor(aList, canvasFrame, bgcolor))
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return aList.AppendNewToBottom(
|
||||
new (&aBuilder) nsDisplaySolidColor(aFrame, aBounds, bgcolor));
|
||||
}
|
||||
|
|
|
@ -249,38 +249,25 @@ nsRect nsCanvasFrame::CanvasArea() const
|
|||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Override nsDisplayBackground methods so that we pass aBGClipRect to
|
||||
* PaintBackground, covering the whole overflow area.
|
||||
*/
|
||||
class nsDisplayCanvasBackground : public nsDisplayBackground {
|
||||
public:
|
||||
nsDisplayCanvasBackground(nsIFrame *aFrame)
|
||||
: nsDisplayBackground(aFrame)
|
||||
{
|
||||
void
|
||||
nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsIRenderingContext* aCtx)
|
||||
{
|
||||
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
|
||||
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
|
||||
nsRect bgClipRect = frame->CanvasArea() + offset;
|
||||
|
||||
if (NS_GET_A(mExtraBackgroundColor) > 0) {
|
||||
aCtx->SetColor(mExtraBackgroundColor);
|
||||
aCtx->FillRect(bgClipRect);
|
||||
}
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
|
||||
return frame->CanvasArea() + aBuilder->ToReferenceFrame(mFrame);
|
||||
}
|
||||
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsIRenderingContext* aCtx)
|
||||
{
|
||||
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
|
||||
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
|
||||
nsRect bgClipRect = frame->CanvasArea() + offset;
|
||||
nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
|
||||
mVisibleRect,
|
||||
nsRect(offset, mFrame->GetSize()),
|
||||
aBuilder->GetBackgroundPaintFlags(),
|
||||
&bgClipRect);
|
||||
}
|
||||
|
||||
NS_DISPLAY_DECL_NAME("CanvasBackground", TYPE_CANVAS_BACKGROUND)
|
||||
};
|
||||
nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
|
||||
mVisibleRect,
|
||||
nsRect(offset, mFrame->GetSize()),
|
||||
aBuilder->GetBackgroundPaintFlags(),
|
||||
&bgClipRect);
|
||||
}
|
||||
|
||||
/**
|
||||
* A display item to paint the focus ring for the document.
|
||||
|
|
|
@ -157,4 +157,55 @@ protected:
|
|||
nsAbsoluteContainingBlock mAbsoluteContainer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Override nsDisplayBackground methods so that we pass aBGClipRect to
|
||||
* PaintBackground, covering the whole overflow area.
|
||||
* We can also paint an "extra background color" behind the normal
|
||||
* background.
|
||||
*/
|
||||
class nsDisplayCanvasBackground : public nsDisplayBackground {
|
||||
public:
|
||||
nsDisplayCanvasBackground(nsIFrame *aFrame)
|
||||
: nsDisplayBackground(aFrame)
|
||||
{
|
||||
mExtraBackgroundColor = NS_RGBA(0,0,0,0);
|
||||
}
|
||||
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
return NS_GET_A(mExtraBackgroundColor) == 255 ||
|
||||
nsDisplayBackground::IsOpaque(aBuilder);
|
||||
}
|
||||
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
|
||||
{
|
||||
nscolor background;
|
||||
if (!nsDisplayBackground::IsUniform(aBuilder, &background))
|
||||
return PR_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;
|
||||
return PR_TRUE;
|
||||
}
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
|
||||
return frame->CanvasArea() + aBuilder->ToReferenceFrame(mFrame);
|
||||
}
|
||||
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsIRenderingContext* aCtx);
|
||||
|
||||
void SetExtraBackgroundColor(nscolor aColor)
|
||||
{
|
||||
mExtraBackgroundColor = aColor;
|
||||
}
|
||||
|
||||
NS_DISPLAY_DECL_NAME("CanvasBackground", TYPE_CANVAS_BACKGROUND)
|
||||
|
||||
private:
|
||||
nscolor mExtraBackgroundColor;
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsCanvasFrame_h___ */
|
||||
|
|
|
@ -427,17 +427,19 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
mInnerView->GetPosition() +
|
||||
GetOffsetTo(aBuilder->ReferenceFrame());
|
||||
|
||||
if (f && NS_SUCCEEDED(rv)) {
|
||||
rv = f->BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
|
||||
}
|
||||
|
||||
if (!aBuilder->IsForEventDelivery()) {
|
||||
// Add the canvas background color.
|
||||
// Add the canvas background color to the bottom of the list. This
|
||||
// happens after we've built the list so that AddCanvasBackgroundColorItem
|
||||
// can monkey with the contents if necessary.
|
||||
rv = presShell->AddCanvasBackgroundColorItem(
|
||||
*aBuilder, childItems, f ? f : this, shellBounds, NS_RGBA(0,0,0,0),
|
||||
PR_TRUE);
|
||||
}
|
||||
|
||||
if (f && NS_SUCCEEDED(rv)) {
|
||||
rv = f->BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Clip children to the child root frame's rectangle
|
||||
rv = aLists.Content()->AppendNewToTop(
|
||||
|
|
Загрузка…
Ссылка в новой задаче