Bug 1227327 - Allow specifying a background rect for background dislay items. r=mattwoodrow

MozReview-Commit-ID: 5X6FJYRCnWt

--HG--
extra : rebase_source : 334ea74abc71041246fcf9cbf25ff642c9e92b67
This commit is contained in:
Markus Stange 2016-04-27 17:39:25 -04:00
parent 6ae2cdbdd0
commit 2fc65c65af
5 changed files with 57 additions and 56 deletions

View File

@ -2310,9 +2310,11 @@ RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayBackgroundImage::nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
uint32_t aLayer,
const nsRect& aBackgroundRect,
const nsStyleBackground* aBackgroundStyle)
: nsDisplayImageContainer(aBuilder, aFrame)
, mBackgroundStyle(aBackgroundStyle)
, mBackgroundRect(aBackgroundRect)
, mLayer(aLayer)
, mIsRasterImage(false)
{
@ -2380,13 +2382,12 @@ static nsStyleContext* GetBackgroundStyleContext(nsIFrame* aFrame)
SetBackgroundClipRegion(DisplayListClipState::AutoSaveRestore& aClipState,
nsIFrame* aFrame, const nsPoint& aToReferenceFrame,
const nsStyleImageLayers::Layer& aLayer,
const nsRect& aBackgroundRect,
bool aWillPaintBorder)
{
nsRect borderBox = nsRect(aToReferenceFrame, aFrame->GetSize());
nsCSSRendering::ImageLayerClipState clip;
nsCSSRendering::GetImageLayerClip(aLayer, aFrame, *aFrame->StyleBorder(),
borderBox, borderBox, aWillPaintBorder,
aBackgroundRect, aBackgroundRect, aWillPaintBorder,
aFrame->PresContext()->AppUnitsPerDevPixel(),
&clip);
@ -2402,10 +2403,12 @@ SetBackgroundClipRegion(DisplayListClipState::AutoSaveRestore& aClipState,
/*static*/ bool
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
const nsRect& aBackgroundRect,
nsDisplayList* aList)
{
nsStyleContext* bgSC = nullptr;
const nsStyleBackground* bg = nullptr;
nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame);
nsPresContext* presContext = aFrame->PresContext();
bool isThemed = aFrame->IsThemed();
if (!isThemed) {
@ -2455,11 +2458,11 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
bool useWillPaintBorderOptimization = willPaintBorder &&
nsLayoutUtils::HasNonZeroCorner(borderStyle->mBorderRadius);
SetBackgroundClipRegion(clipState, aFrame, toRef,
bg->BottomLayer(),
bg->BottomLayer(), bgRect,
useWillPaintBorderOptimization);
}
bgItemList.AppendNewToTop(
new (aBuilder) nsDisplayBackgroundColor(aBuilder, aFrame, bg,
new (aBuilder) nsDisplayBackgroundColor(aBuilder, aFrame, bgRect, bg,
drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0)));
}
@ -2471,7 +2474,7 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
new (aBuilder) nsDisplayClearBackground(aBuilder, aFrame));
}
nsDisplayThemedBackground* bgItem =
new (aBuilder) nsDisplayThemedBackground(aBuilder, aFrame);
new (aBuilder) nsDisplayThemedBackground(aBuilder, aFrame, bgRect);
bgItemList.AppendNewToTop(bgItem);
aList->AppendToTop(&bgItemList);
return true;
@ -2502,12 +2505,12 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
if (!aBuilder->IsForEventDelivery()) {
const nsStyleImageLayers::Layer& layer = bg->mImage.mLayers[i];
SetBackgroundClipRegion(clipState, aFrame, toRef,
layer, willPaintBorder);
layer, bgRect, willPaintBorder);
}
nsDisplayList thisItemList;
nsDisplayBackgroundImage* bgItem =
new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bg);
new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bgRect, bg);
if (bgItem->ShouldFixToViewport(aBuilder)) {
thisItemList.AppendNewToTop(
@ -2774,7 +2777,8 @@ nsDisplayBackgroundImage::ComputeVisibility(nsDisplayListBuilder* aBuilder,
/* static */ nsRegion
nsDisplayBackgroundImage::GetInsideClipRegion(nsDisplayItem* aItem,
uint8_t aClip,
const nsRect& aRect)
const nsRect& aRect,
const nsRect& aBackgroundRect)
{
nsRegion result;
if (aRect.IsEmpty())
@ -2782,26 +2786,18 @@ nsDisplayBackgroundImage::GetInsideClipRegion(nsDisplayItem* aItem,
nsIFrame *frame = aItem->Frame();
nsRect clipRect;
nsRect clipRect = aBackgroundRect;
if (frame->GetType() == nsGkAtoms::canvasFrame) {
nsCanvasFrame* canvasFrame = static_cast<nsCanvasFrame*>(frame);
clipRect = canvasFrame->CanvasArea() + aItem->ToReferenceFrame();
} else {
switch (aClip) {
case NS_STYLE_IMAGELAYER_CLIP_BORDER:
case NS_STYLE_IMAGELAYER_CLIP_TEXT:
clipRect = nsRect(aItem->ToReferenceFrame(), frame->GetSize());
break;
case NS_STYLE_IMAGELAYER_CLIP_PADDING:
clipRect = frame->GetPaddingRect() - frame->GetPosition() + aItem->ToReferenceFrame();
break;
case NS_STYLE_IMAGELAYER_CLIP_CONTENT:
clipRect = frame->GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
break;
default:
NS_NOTREACHED("Unknown clip type");
return result;
} else if (aClip == NS_STYLE_IMAGELAYER_CLIP_PADDING ||
aClip == NS_STYLE_IMAGELAYER_CLIP_CONTENT) {
nsMargin border = frame->GetUsedBorder();
if (aClip == NS_STYLE_IMAGELAYER_CLIP_CONTENT) {
border += frame->GetUsedPadding();
}
border.ApplySkipSides(frame->GetSkipSides());
clipRect.Deflate(border);
}
return clipRect.Intersect(aRect);
@ -2829,7 +2825,7 @@ nsDisplayBackgroundImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
const nsStyleImageLayers::Layer& layer = mBackgroundStyle->mImage.mLayers[mLayer];
if (layer.mImage.IsOpaque() && layer.mBlendMode == NS_STYLE_BLEND_NORMAL &&
layer.mClip != NS_STYLE_IMAGELAYER_CLIP_TEXT) {
result = GetInsideClipRegion(this, layer.mClip, mBounds);
result = GetInsideClipRegion(this, layer.mClip, mBounds, mBackgroundRect);
}
}
@ -2855,7 +2851,7 @@ nsDisplayBackgroundImage::GetPositioningArea()
bool transformedFixed;
return nsCSSRendering::ComputeImageLayerPositioningArea(
mFrame->PresContext(), mFrame,
nsRect(ToReferenceFrame(), mFrame->GetSize()),
mBackgroundRect,
mBackgroundStyle->mImage.mLayers[mLayer],
&attachedToFrame,
&transformedFixed) + ToReferenceFrame();
@ -2907,19 +2903,18 @@ nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder,
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
CheckForBorderItem(this, flags);
nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
gfxContext* ctx = aCtx->ThebesContext();
uint8_t clip = mBackgroundStyle->mImage.mLayers[mLayer].mClip;
if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
ctx->Save();
ClipBackgroundByText(mFrame, aCtx, borderBox);
ClipBackgroundByText(mFrame, aCtx, mBackgroundRect);
}
image::DrawResult result =
nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
aBounds,
borderBox,
mBackgroundRect,
flags, aClipRect, mLayer,
CompositionOp::OP_OVER);
@ -2994,8 +2989,7 @@ nsDisplayBackgroundImage::GetBoundsInternal(nsDisplayListBuilder* aBuilder) {
return nsRect();
}
nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
nsRect clipRect = borderBox;
nsRect clipRect = mBackgroundRect;
if (mFrame->GetType() == nsGkAtoms::canvasFrame) {
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
clipRect = frame->CanvasArea() + ToReferenceFrame();
@ -3011,7 +3005,7 @@ nsDisplayBackgroundImage::GetBoundsInternal(nsDisplayListBuilder* aBuilder) {
}
const nsStyleImageLayers::Layer& layer = mBackgroundStyle->mImage.mLayers[mLayer];
return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
borderBox, clipRect, layer,
mBackgroundRect, clipRect, layer,
aBuilder->GetBackgroundPaintFlags());
}
@ -3023,8 +3017,10 @@ nsDisplayBackgroundImage::GetPerFrameKey()
}
nsDisplayThemedBackground::nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame)
nsIFrame* aFrame,
const nsRect& aBackgroundRect)
: nsDisplayItem(aBuilder, aFrame)
, mBackgroundRect(aBackgroundRect)
{
MOZ_COUNT_CTOR(nsDisplayThemedBackground);
@ -3067,8 +3063,8 @@ nsDisplayThemedBackground::HitTest(nsDisplayListBuilder* aBuilder,
HitTestState* aState,
nsTArray<nsIFrame*> *aOutFrames)
{
// Assume that any point in our border rect is a hit.
if (nsRect(ToReferenceFrame(), mFrame->GetSize()).Intersects(aRect)) {
// Assume that any point in our background rect is a hit.
if (mBackgroundRect.Intersects(aRect)) {
aOutFrames->AppendElement(mFrame);
}
}
@ -3080,7 +3076,7 @@ nsDisplayThemedBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
*aSnap = false;
if (mThemeTransparency == nsITheme::eOpaque) {
result = nsRect(ToReferenceFrame(), mFrame->GetSize());
result = mBackgroundRect;
}
return result;
}
@ -3105,7 +3101,7 @@ nsDisplayThemedBackground::ProvidesFontSmoothingBackgroundColor(nscolor* aColor)
nsRect
nsDisplayThemedBackground::GetPositioningArea()
{
return nsRect(ToReferenceFrame(), mFrame->GetSize());
return mBackgroundRect;
}
void
@ -3124,12 +3120,11 @@ nsDisplayThemedBackground::PaintInternal(nsDisplayListBuilder* aBuilder,
// XXXzw this ignores aClipRect.
nsPresContext* presContext = mFrame->PresContext();
nsITheme *theme = presContext->GetTheme();
nsRect borderArea(ToReferenceFrame(), mFrame->GetSize());
nsRect drawing(borderArea);
nsRect drawing(mBackgroundRect);
theme->GetWidgetOverflow(presContext->DeviceContext(), mFrame, mAppearance,
&drawing);
drawing.IntersectRect(drawing, aBounds);
theme->DrawWidgetBackground(aCtx, mFrame, mAppearance, borderArea, drawing);
theme->DrawWidgetBackground(aCtx, mFrame, mAppearance, mBackgroundRect, drawing);
}
bool nsDisplayThemedBackground::IsWindowActive()
@ -3174,7 +3169,7 @@ nsRect
nsDisplayThemedBackground::GetBoundsInternal() {
nsPresContext* presContext = mFrame->PresContext();
nsRect r(nsPoint(0,0), mFrame->GetSize());
nsRect r = mBackgroundRect - ToReferenceFrame();
presContext->GetTheme()->
GetWidgetOverflow(presContext->DeviceContext(), mFrame,
mFrame->StyleDisplay()->mAppearance, &r);
@ -3319,8 +3314,6 @@ nsDisplayBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
return;
}
nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
#if 0
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1148418#c21 for why this
// results in a precision induced rounding issue that makes the rect one
@ -3334,7 +3327,7 @@ nsDisplayBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
DrawTarget& aDrawTarget = *aCtx->GetDrawTarget();
Rect rect = NSRectToSnappedRect(borderBox,
Rect rect = NSRectToSnappedRect(mBackgroundRect,
mFrame->PresContext()->AppUnitsPerDevPixel(),
aDrawTarget);
ColorPattern color(ToDeviceColor(mColor));
@ -3346,7 +3339,7 @@ nsDisplayBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
gfxContextAutoSaveRestore save(ctx);
ClipBackgroundByText(mFrame, aCtx, borderBox);
ClipBackgroundByText(mFrame, aCtx, mBackgroundRect);
ctx->SetColor(mColor);
ctx->Fill();
@ -3354,7 +3347,7 @@ nsDisplayBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
}
gfxRect bounds =
nsLayoutUtils::RectToGfxRect(borderBox, mFrame->PresContext()->AppUnitsPerDevPixel());
nsLayoutUtils::RectToGfxRect(mBackgroundRect, mFrame->PresContext()->AppUnitsPerDevPixel());
ctx->SetColor(mColor);
ctx->NewPath();
@ -3379,9 +3372,8 @@ nsDisplayBackgroundColor::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
*aSnap = true;
const nsStyleImageLayers::Layer& bottomLayer = mBackgroundStyle->BottomLayer();
nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
return nsDisplayBackgroundImage::GetInsideClipRegion(this, bottomLayer.mClip,
borderBox);
mBackgroundRect, mBackgroundRect);
}
bool

View File

@ -2661,9 +2661,10 @@ public:
* aIsThemed should be the value of aFrame->IsThemed.
* aBackgroundStyle should be the result of
* nsCSSRendering::FindBackground, or null if FindBackground returned false.
* aBackgroundRect is relative to aFrame.
*/
nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
uint32_t aLayer,
uint32_t aLayer, const nsRect& aBackgroundRect,
const nsStyleBackground* aBackgroundStyle);
virtual ~nsDisplayBackgroundImage();
@ -2671,6 +2672,7 @@ public:
// background. Returns whether we appended a themed background.
static bool AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
const nsRect& aBackgroundRect,
nsDisplayList* aList);
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
@ -2727,7 +2729,7 @@ public:
virtual nsRect GetDestRect() override;
static nsRegion GetInsideClipRegion(nsDisplayItem* aItem, uint8_t aClip,
const nsRect& aRect);
const nsRect& aRect, const nsRect& aBackgroundRect);
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) override;
@ -2758,6 +2760,7 @@ protected:
// mIsThemed is true or if FindBackground returned false.
const nsStyleBackground* mBackgroundStyle;
nsCOMPtr<imgIContainer> mImage;
nsRect mBackgroundRect; // relative to the reference frame
nsRect mFillRect;
nsRect mDestRect;
/* Bounds of this display item */
@ -2774,7 +2777,8 @@ protected:
*/
class nsDisplayThemedBackground : public nsDisplayItem {
public:
nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBackgroundRect);
virtual ~nsDisplayThemedBackground();
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
@ -2820,6 +2824,7 @@ protected:
void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
const nsRect& aBounds, nsRect* aClipRect);
nsRect mBackgroundRect;
nsRect mBounds;
nsITheme::Transparency mThemeTransparency;
uint8_t mAppearance;
@ -2831,9 +2836,11 @@ class nsDisplayBackgroundColor : public nsDisplayItem
public:
nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBackgroundRect,
const nsStyleBackground* aBackgroundStyle,
nscolor aColor)
: nsDisplayItem(aBuilder, aFrame)
, mBackgroundRect(aBackgroundRect)
, mBackgroundStyle(aBackgroundStyle)
, mColor(Color::FromABGR(aColor))
{ }
@ -2854,7 +2861,7 @@ public:
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override
{
*aSnap = true;
return nsRect(ToReferenceFrame(), Frame()->GetSize());
return mBackgroundRect;
}
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
@ -2879,6 +2886,7 @@ public:
virtual void WriteDebugInfo(std::stringstream& aStream) override;
protected:
const nsRect mBackgroundRect;
const nsStyleBackground* mBackgroundStyle;
mozilla::gfx::Color mColor;
};

View File

@ -199,7 +199,7 @@ class nsDisplayCanvasBackgroundImage : public nsDisplayBackgroundImage {
public:
nsDisplayCanvasBackgroundImage(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
uint32_t aLayer, const nsStyleBackground* aBg)
: nsDisplayBackgroundImage(aBuilder, aFrame, aLayer, aBg)
: nsDisplayBackgroundImage(aBuilder, aFrame, aLayer, aFrame->GetRectRelativeToSelf(), aBg)
{
if (ShouldFixToViewport(aBuilder)) {
mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(this);
@ -239,7 +239,7 @@ public:
class nsDisplayCanvasThemedBackground : public nsDisplayThemedBackground {
public:
nsDisplayCanvasThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayThemedBackground(aBuilder, aFrame)
: nsDisplayThemedBackground(aBuilder, aFrame, aFrame->GetRectRelativeToSelf())
{}
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) override;

View File

@ -1875,7 +1875,7 @@ nsFrame::DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
if (aBuilder->IsForEventDelivery() || aForceBackground ||
!StyleBackground()->IsTransparent() || StyleDisplay()->mAppearance) {
return nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
aBuilder, this, aLists.BorderBackground());
aBuilder, this, GetRectRelativeToSelf(), aLists.BorderBackground());
}
return false;
}

View File

@ -1253,6 +1253,7 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
// XXX how to handle collapsed borders?
if (aBuilder->IsForEventDelivery()) {
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
aFrame->GetRectRelativeToSelf(),
lists->BorderBackground());
}