Bug 1227327 - Use regular background image display items for painting button backgrounds. r=mattwoodrow

This has multiple benefits:
 - It makes DLBI detection of background-position changes work for buttons.
 - It makes background-attachment: fixed work for button backgrounds.
 - It allows the willPaintBorder optimization to be used for button background
   drawing, which reduces the background clip to not overlap with opaque borders.

The willPaintBorder optimization requires a change to the reftest 611574-2.html.
This reftest compares backgrounds to inset box shadows. Box shadows those don't
have a willPaintBorder optimization, so we'd get different results due to the
borders - inset box shadows will bleed through the rounded corner anti-aliasing
of the border, backgrounds won't any more. So we just turn off button borders
and cover the outer edges of the borders with an outline in that reftest.

MozReview-Commit-ID: Lvx2p5szjw7
***
Cover the antialiasing in 611574-2.html with a black outline.

MozReview-Commit-ID: IHC3B7Eq72j

--HG--
extra : rebase_source : fbd7d3152b819232adfc97dd9df1481a582925c5
This commit is contained in:
Markus Stange 2016-04-29 13:16:23 -04:00
Родитель 6231d39a7c
Коммит bb440eec66
4 изменённых файлов: 29 добавлений и 30 удалений

Просмотреть файл

@ -112,19 +112,18 @@ nsDisplayButtonBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
buttonRect, mVisibleRect); buttonRect, mVisibleRect);
} }
class nsDisplayButtonBorderBackground : public nsDisplayItem { class nsDisplayButtonBorder : public nsDisplayItem {
public: public:
nsDisplayButtonBorderBackground(nsDisplayListBuilder* aBuilder, nsDisplayButtonBorder(nsDisplayListBuilder* aBuilder,
nsButtonFrameRenderer* aRenderer) nsButtonFrameRenderer* aRenderer)
: nsDisplayItem(aBuilder, aRenderer->GetFrame()), mBFR(aRenderer) { : nsDisplayItem(aBuilder, aRenderer->GetFrame()), mBFR(aRenderer) {
MOZ_COUNT_CTOR(nsDisplayButtonBorderBackground); MOZ_COUNT_CTOR(nsDisplayButtonBorder);
} }
#ifdef NS_BUILD_REFCNT_LOGGING #ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayButtonBorderBackground() { virtual ~nsDisplayButtonBorder() {
MOZ_COUNT_DTOR(nsDisplayButtonBorderBackground); MOZ_COUNT_DTOR(nsDisplayButtonBorder);
} }
#endif #endif
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, HitTestState* aState,
nsTArray<nsIFrame*> *aOutFrames) override { nsTArray<nsIFrame*> *aOutFrames) override {
@ -144,13 +143,13 @@ private:
}; };
nsDisplayItemGeometry* nsDisplayItemGeometry*
nsDisplayButtonBorderBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder) nsDisplayButtonBorder::AllocateGeometry(nsDisplayListBuilder* aBuilder)
{ {
return new nsDisplayItemGenericImageGeometry(this, aBuilder); return new nsDisplayItemGenericImageGeometry(this, aBuilder);
} }
void void
nsDisplayButtonBorderBackground::ComputeInvalidationRegion( nsDisplayButtonBorder::ComputeInvalidationRegion(
nsDisplayListBuilder* aBuilder, nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry, const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion) nsRegion *aInvalidRegion)
@ -167,22 +166,22 @@ nsDisplayButtonBorderBackground::ComputeInvalidationRegion(
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
} }
void nsDisplayButtonBorderBackground::Paint(nsDisplayListBuilder* aBuilder, void nsDisplayButtonBorder::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) nsRenderingContext* aCtx)
{ {
NS_ASSERTION(mFrame, "No frame?"); NS_ASSERTION(mFrame, "No frame?");
nsPresContext* pc = mFrame->PresContext(); nsPresContext* pc = mFrame->PresContext();
nsRect r = nsRect(ToReferenceFrame(), mFrame->GetSize()); nsRect r = nsRect(ToReferenceFrame(), mFrame->GetSize());
// draw the border and background inside the focus and outline borders // draw the border and background inside the focus and outline borders
DrawResult result = DrawResult result =
mBFR->PaintBorderAndBackground(aBuilder, pc, *aCtx, mVisibleRect, r); mBFR->PaintBorder(aBuilder, pc, *aCtx, mVisibleRect, r);
nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result); nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
} }
nsRect nsRect
nsDisplayButtonBorderBackground::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) { nsDisplayButtonBorder::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false; *aSnap = false;
return aBuilder->IsForEventDelivery() ? nsRect(ToReferenceFrame(), mFrame->GetSize()) return aBuilder->IsForEventDelivery() ? nsRect(ToReferenceFrame(), mFrame->GetSize())
: mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame(); : mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
@ -264,10 +263,14 @@ nsButtonFrameRenderer::DisplayButton(nsDisplayListBuilder* aBuilder,
nsDisplayButtonBoxShadowOuter(aBuilder, this)); nsDisplayButtonBoxShadowOuter(aBuilder, this));
} }
// Almost all buttons draw some kind of background so there's not much nsRect buttonRect;
// point in checking whether we should create this item. GetButtonRect(mFrame->GetRectRelativeToSelf(), buttonRect);
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
aBuilder, mFrame, buttonRect, aBackground);
aBackground->AppendNewToTop(new (aBuilder) aBackground->AppendNewToTop(new (aBuilder)
nsDisplayButtonBorderBackground(aBuilder, this)); nsDisplayButtonBorder(aBuilder, this));
// Only display focus rings if we actually have them. Since at most one // Only display focus rings if we actually have them. Since at most one
// button would normally display a focus ring, most buttons won't have them. // button would normally display a focus ring, most buttons won't have them.
@ -325,9 +328,8 @@ nsButtonFrameRenderer::PaintOutlineAndFocusBorders(
return result; return result;
} }
DrawResult DrawResult
nsButtonFrameRenderer::PaintBorderAndBackground( nsButtonFrameRenderer::PaintBorder(
nsDisplayListBuilder* aBuilder, nsDisplayListBuilder* aBuilder,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext, nsRenderingContext& aRenderingContext,
@ -340,19 +342,14 @@ nsButtonFrameRenderer::PaintBorderAndBackground(
nsStyleContext* context = mFrame->StyleContext(); nsStyleContext* context = mFrame->StyleContext();
uint32_t bgFlags = aBuilder->GetBackgroundPaintFlags();
PaintBorderFlags borderFlags = aBuilder->ShouldSyncDecodeImages() PaintBorderFlags borderFlags = aBuilder->ShouldSyncDecodeImages()
? PaintBorderFlags::SYNC_DECODE_IMAGES ? PaintBorderFlags::SYNC_DECODE_IMAGES
: PaintBorderFlags(); : PaintBorderFlags();
DrawResult result =
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, mFrame,
aDirtyRect, buttonRect, bgFlags);
nsCSSRendering::PaintBoxShadowInner(aPresContext, aRenderingContext, nsCSSRendering::PaintBoxShadowInner(aPresContext, aRenderingContext,
mFrame, buttonRect); mFrame, buttonRect);
result &= DrawResult result =
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame, nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
aDirtyRect, buttonRect, context, borderFlags); aDirtyRect, buttonRect, context, borderFlags);

Просмотреть файл

@ -45,11 +45,11 @@ public:
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const nsRect& aRect); const nsRect& aRect);
DrawResult PaintBorderAndBackground(nsDisplayListBuilder* aBuilder, DrawResult PaintBorder(nsDisplayListBuilder* aBuilder,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext, nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const nsRect& aRect); const nsRect& aRect);
void SetFrame(nsFrame* aFrame, nsPresContext* aPresContext); void SetFrame(nsFrame* aFrame, nsPresContext* aPresContext);

Просмотреть файл

@ -2,6 +2,7 @@
<html> <html>
<head><style> <head><style>
button,span,fieldset { border-radius: 7px 3px; background-color: #0F0; } button,span,fieldset { border-radius: 7px 3px; background-color: #0F0; }
button { border: none; outline: 3px solid black; -moz-outline-radius: 7px 3px; outline-offset: -2px; }
</style></head> </style></head>
<body style="margin:30px"> <body style="margin:30px">
<div style="-moz-column-count:3"> <div style="-moz-column-count:3">

Просмотреть файл

@ -2,6 +2,7 @@
<html> <html>
<head><style> <head><style>
button,span,fieldset { border-radius: 7px 3px; background-color: #0F0; } button,span,fieldset { border-radius: 7px 3px; background-color: #0F0; }
button { border: none; outline: 3px solid black; -moz-outline-radius: 7px 3px; outline-offset: -2px; }
</style></head> </style></head>
<body style="margin:30px"> <body style="margin:30px">
<div style="-moz-column-count:3"> <div style="-moz-column-count:3">