зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
6231d39a7c
Коммит
bb440eec66
|
@ -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">
|
||||||
|
|
Загрузка…
Ссылка в новой задаче