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
parent 6231d39a7c
commit bb440eec66
4 changed files with 29 additions and 30 deletions

View File

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

View File

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

View File

@ -2,6 +2,7 @@
<html>
<head><style>
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>
<body style="margin:30px">
<div style="-moz-column-count:3">

View File

@ -2,6 +2,7 @@
<html>
<head><style>
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>
<body style="margin:30px">
<div style="-moz-column-count:3">