mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-03 23:01:31 +00:00
Backed out 8 changesets (bug 810470) due OSX reftest failures.
This commit is contained in:
parent
4bfd2129d6
commit
98268dbc6a
@ -2314,6 +2314,33 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem,
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
FrameLayerBuilder::NeedToInvalidateFixedDisplayItem(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem)
|
||||
{
|
||||
if (!aItem->ShouldFixToViewport(aBuilder)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsRefPtr<LayerManager> layerManager;
|
||||
nsIFrame* referenceFrame = aBuilder->RootReferenceFrame();
|
||||
NS_ASSERTION(referenceFrame == nsLayoutUtils::GetDisplayRootFrame(referenceFrame),
|
||||
"Reference frame must be a display root for us to use the layer manager");
|
||||
nsIWidget* window = referenceFrame->GetNearestWidget();
|
||||
if (window) {
|
||||
layerManager = window->GetLayerManager();
|
||||
}
|
||||
|
||||
if (layerManager) {
|
||||
DisplayItemData* data = GetDisplayItemDataForManager(aItem, layerManager);
|
||||
if (data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
|
||||
nsDisplayItem* aItem,
|
||||
|
@ -321,6 +321,16 @@ public:
|
||||
|
||||
LayerManager* GetRetainingLayerManager() { return mRetainingManager; }
|
||||
|
||||
/**
|
||||
* Returns true if the given item (which we assume here is
|
||||
* background-attachment:fixed) needs to be repainted as we scroll in its
|
||||
* document.
|
||||
* Returns false if it doesn't need to be repainted because the layer system
|
||||
* is ensuring its fixed-ness for us.
|
||||
*/
|
||||
static bool NeedToInvalidateFixedDisplayItem(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem);
|
||||
|
||||
/**
|
||||
* Returns true if the given display item was rendered during the previous
|
||||
* paint. Returns false otherwise.
|
||||
|
@ -1810,27 +1810,27 @@ nsCSSRendering::DetermineBackgroundColor(nsPresContext* aPresContext,
|
||||
aDrawBackgroundColor = aPresContext->GetBackgroundColorDraw();
|
||||
}
|
||||
|
||||
const nsStyleBackground *bg = aStyleContext->GetStyleBackground();
|
||||
nscolor bgColor;
|
||||
if (aDrawBackgroundColor) {
|
||||
bgColor =
|
||||
aStyleContext->GetVisitedDependentColor(eCSSProperty_background_color);
|
||||
if (NS_GET_A(bgColor) == 0) {
|
||||
if (NS_GET_A(bgColor) == 0)
|
||||
aDrawBackgroundColor = false;
|
||||
}
|
||||
} else {
|
||||
// If GetBackgroundColorDraw() is false, we are still expected to
|
||||
// draw color in the background of any frame that's not completely
|
||||
// transparent, but we are expected to use white instead of whatever
|
||||
// color was specified.
|
||||
bgColor = NS_RGB(255, 255, 255);
|
||||
if (aDrawBackgroundImage || !bg->IsTransparent()) {
|
||||
if (aDrawBackgroundImage ||
|
||||
!aStyleContext->GetStyleBackground()->IsTransparent())
|
||||
aDrawBackgroundColor = true;
|
||||
} else {
|
||||
else
|
||||
bgColor = NS_RGBA(0,0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
const nsStyleBackground *bg = aStyleContext->GetStyleBackground();
|
||||
|
||||
// We can skip painting the background color if a background image is opaque.
|
||||
if (aDrawBackgroundColor &&
|
||||
bg->BottomLayer().mRepeat.mXRepeat == NS_STYLE_BG_REPEAT_REPEAT &&
|
||||
@ -2736,103 +2736,6 @@ IsTransformed(nsIFrame* aForFrame, nsIFrame* aTopFrame)
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsCSSRendering::ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aBorderArea,
|
||||
const nsStyleBackground& aBackground,
|
||||
const nsStyleBackground::Layer& aLayer,
|
||||
nsIFrame** aAttachedToFrame)
|
||||
{
|
||||
// Compute background origin area relative to aBorderArea now as we may need
|
||||
// it to compute the effective image size for a CSS gradient.
|
||||
nsRect bgPositioningArea(0, 0, 0, 0);
|
||||
|
||||
nsIAtom* frameType = aForFrame->GetType();
|
||||
nsIFrame* geometryFrame = aForFrame;
|
||||
if (frameType == nsGkAtoms::inlineFrame) {
|
||||
// XXXjwalden Strictly speaking this is not quite faithful to how
|
||||
// background-break is supposed to interact with background-origin values,
|
||||
// but it's a non-trivial amount of work to make it fully conformant, and
|
||||
// until the specification is more finalized (and assuming background-break
|
||||
// even makes the cut) it doesn't make sense to hammer out exact behavior.
|
||||
switch (aBackground.mBackgroundInlinePolicy) {
|
||||
case NS_STYLE_BG_INLINE_POLICY_EACH_BOX:
|
||||
bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size());
|
||||
break;
|
||||
case NS_STYLE_BG_INLINE_POLICY_BOUNDING_BOX:
|
||||
bgPositioningArea = gInlineBGData->GetBoundingRect(aForFrame);
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Unknown background-inline-policy value! "
|
||||
"Please, teach me what to do.");
|
||||
case NS_STYLE_BG_INLINE_POLICY_CONTINUOUS:
|
||||
bgPositioningArea = gInlineBGData->GetContinuousRect(aForFrame);
|
||||
break;
|
||||
}
|
||||
} else if (frameType == nsGkAtoms::canvasFrame) {
|
||||
geometryFrame = aForFrame->GetFirstPrincipalChild();
|
||||
// geometryFrame might be null if this canvas is a page created
|
||||
// as an overflow container (e.g. the in-flow content has already
|
||||
// finished and this page only displays the continuations of
|
||||
// absolutely positioned content).
|
||||
if (geometryFrame) {
|
||||
bgPositioningArea = geometryFrame->GetRect();
|
||||
}
|
||||
} else {
|
||||
bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size());
|
||||
}
|
||||
|
||||
// Background images are tiled over the 'background-clip' area
|
||||
// but the origin of the tiling is based on the 'background-origin' area
|
||||
if (aLayer.mOrigin != NS_STYLE_BG_ORIGIN_BORDER && geometryFrame) {
|
||||
nsMargin border = geometryFrame->GetUsedBorder();
|
||||
if (aLayer.mOrigin != NS_STYLE_BG_ORIGIN_PADDING) {
|
||||
border += geometryFrame->GetUsedPadding();
|
||||
NS_ASSERTION(aLayer.mOrigin == NS_STYLE_BG_ORIGIN_CONTENT,
|
||||
"unknown background-origin value");
|
||||
}
|
||||
geometryFrame->ApplySkipSides(border);
|
||||
bgPositioningArea.Deflate(border);
|
||||
}
|
||||
|
||||
nsIFrame* attachedToFrame = aForFrame;
|
||||
if (NS_STYLE_BG_ATTACHMENT_FIXED == aLayer.mAttachment) {
|
||||
// If it's a fixed background attachment, then the image is placed
|
||||
// relative to the viewport, which is the area of the root frame
|
||||
// in a screen context or the page content frame in a print context.
|
||||
attachedToFrame = aPresContext->PresShell()->FrameManager()->GetRootFrame();
|
||||
NS_ASSERTION(attachedToFrame, "no root frame");
|
||||
nsIFrame* pageContentFrame = nullptr;
|
||||
if (aPresContext->IsPaginated()) {
|
||||
pageContentFrame =
|
||||
nsLayoutUtils::GetClosestFrameOfType(aForFrame, nsGkAtoms::pageContentFrame);
|
||||
if (pageContentFrame) {
|
||||
attachedToFrame = pageContentFrame;
|
||||
}
|
||||
// else this is an embedded shell and its root frame is what we want
|
||||
}
|
||||
|
||||
// Set the background positioning area to the viewport's area
|
||||
// (relative to aForFrame)
|
||||
bgPositioningArea =
|
||||
nsRect(-aForFrame->GetOffsetTo(attachedToFrame), attachedToFrame->GetSize());
|
||||
|
||||
if (!pageContentFrame) {
|
||||
// Subtract the size of scrollbars.
|
||||
nsIScrollableFrame* scrollableFrame =
|
||||
aPresContext->PresShell()->GetRootScrollFrameAsScrollable();
|
||||
if (scrollableFrame) {
|
||||
nsMargin scrollbars = scrollableFrame->GetActualScrollbarSizes();
|
||||
bgPositioningArea.Deflate(scrollbars);
|
||||
}
|
||||
}
|
||||
}
|
||||
*aAttachedToFrame = attachedToFrame;
|
||||
|
||||
return bgPositioningArea;
|
||||
}
|
||||
|
||||
nsBackgroundLayerState
|
||||
nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext,
|
||||
nsIFrame* aForFrame,
|
||||
@ -2908,13 +2811,57 @@ nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext,
|
||||
return state;
|
||||
}
|
||||
|
||||
// The frame to which the background is attached
|
||||
nsIFrame* attachedToFrame = aForFrame;
|
||||
// Compute background origin area relative to aBorderArea now as we may need
|
||||
// it to compute the effective image size for a CSS gradient.
|
||||
nsRect bgPositioningArea =
|
||||
ComputeBackgroundPositioningArea(aPresContext, aForFrame, aBorderArea,
|
||||
aBackground, aLayer, &attachedToFrame);
|
||||
nsRect bgPositioningArea(0, 0, 0, 0);
|
||||
|
||||
nsIAtom* frameType = aForFrame->GetType();
|
||||
nsIFrame* geometryFrame = aForFrame;
|
||||
if (frameType == nsGkAtoms::inlineFrame) {
|
||||
// XXXjwalden Strictly speaking this is not quite faithful to how
|
||||
// background-break is supposed to interact with background-origin values,
|
||||
// but it's a non-trivial amount of work to make it fully conformant, and
|
||||
// until the specification is more finalized (and assuming background-break
|
||||
// even makes the cut) it doesn't make sense to hammer out exact behavior.
|
||||
switch (aBackground.mBackgroundInlinePolicy) {
|
||||
case NS_STYLE_BG_INLINE_POLICY_EACH_BOX:
|
||||
bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size());
|
||||
break;
|
||||
case NS_STYLE_BG_INLINE_POLICY_BOUNDING_BOX:
|
||||
bgPositioningArea = gInlineBGData->GetBoundingRect(aForFrame);
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Unknown background-inline-policy value! "
|
||||
"Please, teach me what to do.");
|
||||
case NS_STYLE_BG_INLINE_POLICY_CONTINUOUS:
|
||||
bgPositioningArea = gInlineBGData->GetContinuousRect(aForFrame);
|
||||
break;
|
||||
}
|
||||
} else if (frameType == nsGkAtoms::canvasFrame) {
|
||||
geometryFrame = aForFrame->GetFirstPrincipalChild();
|
||||
// geometryFrame might be null if this canvas is a page created
|
||||
// as an overflow container (e.g. the in-flow content has already
|
||||
// finished and this page only displays the continuations of
|
||||
// absolutely positioned content).
|
||||
if (geometryFrame) {
|
||||
bgPositioningArea = geometryFrame->GetRect();
|
||||
}
|
||||
} else {
|
||||
bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size());
|
||||
}
|
||||
|
||||
// Background images are tiled over the 'background-clip' area
|
||||
// but the origin of the tiling is based on the 'background-origin' area
|
||||
if (aLayer.mOrigin != NS_STYLE_BG_ORIGIN_BORDER && geometryFrame) {
|
||||
nsMargin border = geometryFrame->GetUsedBorder();
|
||||
if (aLayer.mOrigin != NS_STYLE_BG_ORIGIN_PADDING) {
|
||||
border += geometryFrame->GetUsedPadding();
|
||||
NS_ASSERTION(aLayer.mOrigin == NS_STYLE_BG_ORIGIN_CONTENT,
|
||||
"unknown background-origin value");
|
||||
}
|
||||
geometryFrame->ApplySkipSides(border);
|
||||
bgPositioningArea.Deflate(border);
|
||||
}
|
||||
|
||||
// For background-attachment:fixed backgrounds, we'll limit the area
|
||||
// where the background can be drawn to the viewport.
|
||||
@ -2926,8 +2873,40 @@ nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext,
|
||||
// of aForFrame's border-box will be rendered)
|
||||
nsPoint imageTopLeft;
|
||||
if (NS_STYLE_BG_ATTACHMENT_FIXED == aLayer.mAttachment) {
|
||||
if ((aFlags & nsCSSRendering::PAINTBG_TO_WINDOW) &&
|
||||
!IsTransformed(aForFrame, attachedToFrame)) {
|
||||
aPresContext->SetHasFixedBackgroundFrame();
|
||||
|
||||
// If it's a fixed background attachment, then the image is placed
|
||||
// relative to the viewport, which is the area of the root frame
|
||||
// in a screen context or the page content frame in a print context.
|
||||
nsIFrame* topFrame =
|
||||
aPresContext->PresShell()->FrameManager()->GetRootFrame();
|
||||
NS_ASSERTION(topFrame, "no root frame");
|
||||
nsIFrame* pageContentFrame = nullptr;
|
||||
if (aPresContext->IsPaginated()) {
|
||||
pageContentFrame =
|
||||
nsLayoutUtils::GetClosestFrameOfType(aForFrame, nsGkAtoms::pageContentFrame);
|
||||
if (pageContentFrame) {
|
||||
topFrame = pageContentFrame;
|
||||
}
|
||||
// else this is an embedded shell and its root frame is what we want
|
||||
}
|
||||
|
||||
// Set the background positioning area to the viewport's area
|
||||
// (relative to aForFrame)
|
||||
bgPositioningArea = nsRect(-aForFrame->GetOffsetTo(topFrame), topFrame->GetSize());
|
||||
|
||||
if (!pageContentFrame) {
|
||||
// Subtract the size of scrollbars.
|
||||
nsIScrollableFrame* scrollableFrame =
|
||||
aPresContext->PresShell()->GetRootScrollFrameAsScrollable();
|
||||
if (scrollableFrame) {
|
||||
nsMargin scrollbars = scrollableFrame->GetActualScrollbarSizes();
|
||||
bgPositioningArea.Deflate(scrollbars);
|
||||
}
|
||||
}
|
||||
|
||||
if (aFlags & nsCSSRendering::PAINTBG_TO_WINDOW &&
|
||||
!IsTransformed(aForFrame, topFrame)) {
|
||||
// Clip background-attachment:fixed backgrounds to the viewport, if we're
|
||||
// painting to the screen and not transformed. This avoids triggering
|
||||
// tiling in common cases, without affecting output since drawing is
|
||||
|
@ -300,14 +300,6 @@ struct nsCSSRendering {
|
||||
bool& aDrawBackgroundImage,
|
||||
bool& aDrawBackgroundColor);
|
||||
|
||||
static nsRect
|
||||
ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aBorderArea,
|
||||
const nsStyleBackground& aBackground,
|
||||
const nsStyleBackground::Layer& aLayer,
|
||||
nsIFrame** aAttachedToFrame);
|
||||
|
||||
static nsBackgroundLayerState
|
||||
PrepareBackgroundLayer(nsPresContext* aPresContext,
|
||||
nsIFrame* aForFrame,
|
||||
|
@ -1465,22 +1465,20 @@ RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
|
||||
borderBox.ToNearestPixels(aFrame->PresContext()->AppUnitsPerDevPixel()));
|
||||
}
|
||||
|
||||
nsDisplayBackgroundImage::nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame,
|
||||
uint32_t aLayer,
|
||||
bool aIsThemed,
|
||||
const nsStyleBackground* aBackgroundStyle)
|
||||
nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame,
|
||||
uint32_t aLayer,
|
||||
bool aSkipFixedItemBoundsCheck)
|
||||
: nsDisplayItem(aBuilder, aFrame)
|
||||
, mBackgroundStyle(aBackgroundStyle)
|
||||
, mLayer(aLayer)
|
||||
, mIsThemed(aIsThemed)
|
||||
, mIsFixed(false)
|
||||
, mIsBottommostLayer(true)
|
||||
, mLayer(aLayer)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayBackgroundImage);
|
||||
MOZ_COUNT_CTOR(nsDisplayBackground);
|
||||
const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
|
||||
mIsThemed = mFrame->IsThemed(disp, &mThemeTransparency);
|
||||
|
||||
if (mIsThemed) {
|
||||
const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
|
||||
mFrame->IsThemed(disp, &mThemeTransparency);
|
||||
// Perform necessary RegisterThemeGeometry
|
||||
if (disp->mAppearance == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
|
||||
disp->mAppearance == NS_THEME_TOOLBAR) {
|
||||
@ -1489,38 +1487,72 @@ nsDisplayBackgroundImage::nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilde
|
||||
disp->mAppearance == NS_THEME_WIN_GLASS) {
|
||||
aBuilder->SetGlassDisplayItem(this);
|
||||
}
|
||||
} else if (mBackgroundStyle) {
|
||||
} else {
|
||||
// Set HasFixedItems if we construct a background-attachment:fixed item
|
||||
if (mLayer != mBackgroundStyle->mImageCount - 1) {
|
||||
mIsBottommostLayer = false;
|
||||
}
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
nsStyleContext* bgSC;
|
||||
bool hasBG = nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
|
||||
if (hasBG) {
|
||||
const nsStyleBackground* bg = bgSC->GetStyleBackground();
|
||||
if (mLayer != bg->mImageCount - 1) {
|
||||
mIsBottommostLayer = false;
|
||||
}
|
||||
|
||||
// Check if this background layer is attachment-fixed
|
||||
if (!mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty() &&
|
||||
mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED) {
|
||||
aBuilder->SetHasFixedItems();
|
||||
// Check if this background layer is attachment-fixed
|
||||
if (!bg->mLayers[mLayer].mImage.IsEmpty() &&
|
||||
bg->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED) {
|
||||
aBuilder->SetHasFixedItems();
|
||||
|
||||
// Check whether we should fix to viewport scrolling
|
||||
if (bg->mLayers[mLayer].mClip == NS_STYLE_BG_CLIP_BORDER &&
|
||||
!nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->mBorderRadius)) {
|
||||
if (aSkipFixedItemBoundsCheck) {
|
||||
mIsFixed = true;
|
||||
} else {
|
||||
nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
|
||||
if (rootScrollFrame) {
|
||||
bool snap;
|
||||
nsRect bounds = GetBounds(aBuilder, &snap);
|
||||
|
||||
// This bounds check prevents an item fixing to the viewport unless it
|
||||
// it encompasses the scroll-port. If a fixed background doesn't
|
||||
// encompass the scroll-port, it usually means that scrolling will
|
||||
// expose a new area of the fixed background and cause a lot of
|
||||
// invalidation. This performs badly, and looks especially bad when
|
||||
// async scrolling is being used.
|
||||
// XXX A better check would be to see if the underlying frame is fixed to
|
||||
// the viewport/is the viewport.
|
||||
nsIScrollableFrame* scrollable = do_QueryFrame(rootScrollFrame);
|
||||
nsRect scrollport(scrollable->GetScrollPortRect().TopLeft() +
|
||||
aBuilder->ToReferenceFrame(rootScrollFrame),
|
||||
scrollable->GetScrollPositionClampingScrollPortSize());
|
||||
|
||||
mIsFixed = bounds.Contains(scrollport);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsDisplayBackgroundImage::~nsDisplayBackgroundImage()
|
||||
nsDisplayBackground::~nsDisplayBackground()
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
MOZ_COUNT_DTOR(nsDisplayBackgroundImage);
|
||||
MOZ_COUNT_DTOR(nsDisplayBackground);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/ nsresult
|
||||
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame,
|
||||
nsDisplayList* aList,
|
||||
nsDisplayBackgroundImage** aBackground)
|
||||
nsDisplayBackground::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame,
|
||||
nsDisplayList* aList,
|
||||
nsDisplayBackground** aBackground)
|
||||
{
|
||||
nsStyleContext* bgSC = nullptr;
|
||||
const nsStyleBackground* bg = nullptr;
|
||||
nsPresContext* presContext = aFrame->PresContext();
|
||||
bool isThemed = aFrame->IsThemed();
|
||||
if (!isThemed &&
|
||||
if (!aFrame->IsThemed() &&
|
||||
nsCSSRendering::FindBackground(presContext, aFrame, &bgSC)) {
|
||||
bg = bgSC->GetStyleBackground();
|
||||
}
|
||||
@ -1537,15 +1569,15 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
|
||||
// Even if we don't actually have a background color to paint, we still need
|
||||
// to create the item because it's used for hit testing.
|
||||
aList->AppendNewToTop(
|
||||
new (aBuilder) nsDisplayBackgroundColor(aBuilder, aFrame, bg,
|
||||
new (aBuilder) nsDisplayBackgroundColor(aBuilder, aFrame,
|
||||
drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0)));
|
||||
|
||||
// Passing bg == nullptr in this macro will result in one iteration with
|
||||
// i = 0.
|
||||
bool backgroundSet = !aBackground;
|
||||
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
|
||||
nsDisplayBackgroundImage* bgItem =
|
||||
new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, isThemed, bg);
|
||||
nsDisplayBackground* bgItem =
|
||||
new (aBuilder) nsDisplayBackground(aBuilder, aFrame, i);
|
||||
nsresult rv = aList->AppendNewToTop(bgItem);
|
||||
if (rv != NS_OK) {
|
||||
return rv;
|
||||
@ -1647,24 +1679,47 @@ RoundedBorderIntersectsRect(nsIFrame* aFrame,
|
||||
//
|
||||
// See also RoundedRectIntersectsRect.
|
||||
static bool RoundedRectContainsRect(const nsRect& aRoundedRect,
|
||||
const nscoord aRadii[8],
|
||||
const nsRect& aContainedRect) {
|
||||
const nscoord aRadii[8],
|
||||
const nsRect& aContainedRect) {
|
||||
nsRegion rgn = nsLayoutUtils::RoundedRectIntersectRect(aRoundedRect, aRadii, aContainedRect);
|
||||
return rgn.Contains(aContainedRect);
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aClipRect,
|
||||
gfxRect* aDestRect)
|
||||
nsDisplayBackground::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder, const nsRect& aClipRect)
|
||||
{
|
||||
if (mIsThemed || !mBackgroundStyle)
|
||||
if (mIsThemed)
|
||||
return false;
|
||||
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
nsStyleContext* bgSC;
|
||||
if (!nsCSSRendering::FindBackground(presContext, mFrame, &bgSC))
|
||||
return false;
|
||||
|
||||
bool drawBackgroundImage;
|
||||
bool drawBackgroundColor;
|
||||
nsCSSRendering::DetermineBackgroundColor(presContext,
|
||||
bgSC,
|
||||
mFrame,
|
||||
drawBackgroundImage,
|
||||
drawBackgroundColor);
|
||||
|
||||
// For now we don't know how to draw image layers with a background color.
|
||||
if (!drawBackgroundImage || drawBackgroundColor)
|
||||
return false;
|
||||
|
||||
const nsStyleBackground *bg = bgSC->GetStyleBackground();
|
||||
|
||||
// We could pretty easily support multiple image layers, but for now we
|
||||
// just punt here.
|
||||
if (bg->mLayers.Length() != 1)
|
||||
return false;
|
||||
|
||||
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
|
||||
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
|
||||
const nsStyleBackground::Layer &layer = mBackgroundStyle->mLayers[mLayer];
|
||||
nsPoint offset = ToReferenceFrame();
|
||||
nsRect borderArea = nsRect(offset, mFrame->GetSize());
|
||||
|
||||
const nsStyleBackground::Layer &layer = bg->mLayers[0];
|
||||
|
||||
if (layer.mAttachment != NS_STYLE_BG_ATTACHMENT_FIXED)
|
||||
return false;
|
||||
@ -1675,7 +1730,7 @@ nsDisplayBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuil
|
||||
flags,
|
||||
borderArea,
|
||||
aClipRect,
|
||||
*mBackgroundStyle,
|
||||
*bg,
|
||||
layer);
|
||||
|
||||
nsImageRenderer* imageRenderer = &state.mImageRenderer;
|
||||
@ -1684,21 +1739,41 @@ nsDisplayBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuil
|
||||
return false;
|
||||
|
||||
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
|
||||
*aDestRect = nsLayoutUtils::RectToGfxRect(state.mFillArea, appUnitsPerDevPixel);
|
||||
mDestRect = nsLayoutUtils::RectToGfxRect(state.mFillArea, appUnitsPerDevPixel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackgroundImage::TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder)
|
||||
nsDisplayBackground::TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
if (mIsThemed || !mBackgroundStyle)
|
||||
if (mIsThemed)
|
||||
return false;
|
||||
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
nsStyleContext* bgSC;
|
||||
if (!nsCSSRendering::FindBackground(presContext, mFrame, &bgSC))
|
||||
return false;
|
||||
|
||||
bool drawBackgroundImage;
|
||||
bool drawBackgroundColor;
|
||||
nsCSSRendering::DetermineBackgroundColor(presContext,
|
||||
bgSC,
|
||||
mFrame,
|
||||
drawBackgroundImage,
|
||||
drawBackgroundColor);
|
||||
|
||||
// For now we don't know how to draw image layers with a background color.
|
||||
if (!drawBackgroundImage || drawBackgroundColor)
|
||||
return false;
|
||||
|
||||
const nsStyleBackground *bg = bgSC->GetStyleBackground();
|
||||
|
||||
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
|
||||
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
|
||||
const nsStyleBackground::Layer &layer = mBackgroundStyle->mLayers[mLayer];
|
||||
nsPoint offset = ToReferenceFrame();
|
||||
nsRect borderArea = nsRect(offset, mFrame->GetSize());
|
||||
|
||||
const nsStyleBackground::Layer &layer = bg->mLayers[mLayer];
|
||||
|
||||
nsBackgroundLayerState state =
|
||||
nsCSSRendering::PrepareBackgroundLayer(presContext,
|
||||
@ -1706,7 +1781,7 @@ nsDisplayBackgroundImage::TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder
|
||||
flags,
|
||||
borderArea,
|
||||
borderArea,
|
||||
*mBackgroundStyle,
|
||||
*bg,
|
||||
layer);
|
||||
|
||||
nsImageRenderer* imageRenderer = &state.mImageRenderer;
|
||||
@ -1738,9 +1813,9 @@ nsDisplayBackgroundImage::TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder
|
||||
}
|
||||
|
||||
LayerState
|
||||
nsDisplayBackgroundImage::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const FrameLayerBuilder::ContainerParameters& aParameters)
|
||||
nsDisplayBackground::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const FrameLayerBuilder::ContainerParameters& aParameters)
|
||||
{
|
||||
if (!aManager->IsCompositingCheap() ||
|
||||
!nsLayoutUtils::GPUImageScalingEnabled() ||
|
||||
@ -1773,9 +1848,9 @@ nsDisplayBackgroundImage::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
|
||||
already_AddRefed<Layer>
|
||||
nsDisplayBackgroundImage::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters)
|
||||
nsDisplayBackground::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters)
|
||||
{
|
||||
nsRefPtr<ImageLayer> layer = aManager->CreateImageLayer();
|
||||
layer->SetContainer(mImageContainer);
|
||||
@ -1784,7 +1859,7 @@ nsDisplayBackgroundImage::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayBackgroundImage::ConfigureLayer(ImageLayer* aLayer)
|
||||
nsDisplayBackground::ConfigureLayer(ImageLayer* aLayer)
|
||||
{
|
||||
aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame));
|
||||
|
||||
@ -1800,10 +1875,10 @@ nsDisplayBackgroundImage::ConfigureLayer(ImageLayer* aLayer)
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayBackgroundImage::HitTest(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aRect,
|
||||
HitTestState* aState,
|
||||
nsTArray<nsIFrame*> *aOutFrames)
|
||||
nsDisplayBackground::HitTest(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aRect,
|
||||
HitTestState* aState,
|
||||
nsTArray<nsIFrame*> *aOutFrames)
|
||||
{
|
||||
if (mIsThemed) {
|
||||
// For theme backgrounds, assume that any point in our border rect is a hit.
|
||||
@ -1820,9 +1895,9 @@ nsDisplayBackgroundImage::HitTest(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackgroundImage::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion)
|
||||
nsDisplayBackground::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion)
|
||||
{
|
||||
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion)) {
|
||||
@ -1832,14 +1907,16 @@ nsDisplayBackgroundImage::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
// Return false if the background was propagated away from this
|
||||
// frame. We don't want this display item to show up and confuse
|
||||
// anything.
|
||||
return mIsThemed || mBackgroundStyle;
|
||||
nsStyleContext* bgSC;
|
||||
return mIsThemed ||
|
||||
nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC);
|
||||
}
|
||||
|
||||
/* static */ nsRegion
|
||||
nsDisplayBackgroundImage::GetInsideClipRegion(nsDisplayItem* aItem,
|
||||
nsPresContext* aPresContext,
|
||||
uint8_t aClip, const nsRect& aRect,
|
||||
bool* aSnap)
|
||||
nsDisplayBackground::GetInsideClipRegion(nsDisplayItem* aItem,
|
||||
nsPresContext* aPresContext,
|
||||
uint8_t aClip, const nsRect& aRect,
|
||||
bool* aSnap)
|
||||
{
|
||||
nsRegion result;
|
||||
if (aRect.IsEmpty())
|
||||
@ -1878,8 +1955,8 @@ nsDisplayBackgroundImage::GetInsideClipRegion(nsDisplayItem* aItem,
|
||||
}
|
||||
|
||||
nsRegion
|
||||
nsDisplayBackgroundImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) {
|
||||
nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) {
|
||||
nsRegion result;
|
||||
*aSnap = false;
|
||||
// theme background overrides any other background
|
||||
@ -1890,9 +1967,11 @@ nsDisplayBackgroundImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!mBackgroundStyle)
|
||||
nsStyleContext* bgSC;
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
if (!nsCSSRendering::FindBackground(presContext, mFrame, &bgSC))
|
||||
return result;
|
||||
|
||||
const nsStyleBackground* bg = bgSC->GetStyleBackground();
|
||||
|
||||
*aSnap = true;
|
||||
|
||||
@ -1901,15 +1980,14 @@ nsDisplayBackgroundImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
// which expects frames to be sent to it in content order, not reverse
|
||||
// content order which we'll produce here.
|
||||
// Of course, if there's only one frame in the flow, it doesn't matter.
|
||||
if (mBackgroundStyle->mBackgroundInlinePolicy == NS_STYLE_BG_INLINE_POLICY_EACH_BOX ||
|
||||
if (bg->mBackgroundInlinePolicy == NS_STYLE_BG_INLINE_POLICY_EACH_BOX ||
|
||||
(!mFrame->GetPrevContinuation() && !mFrame->GetNextContinuation())) {
|
||||
const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer];
|
||||
const nsStyleBackground::Layer& layer = bg->mLayers[mLayer];
|
||||
if (layer.mImage.IsOpaque()) {
|
||||
nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
nsRect r = nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
|
||||
borderBox, *mBackgroundStyle, layer);
|
||||
result = GetInsideClipRegion(this, presContext, layer.mClip, r, aSnap);
|
||||
borderBox, *bg, layer);
|
||||
result.Or(result, GetInsideClipRegion(this, presContext, layer.mClip, r, aSnap));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1917,7 +1995,7 @@ nsDisplayBackgroundImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackgroundImage::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) {
|
||||
nsDisplayBackground::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) {
|
||||
// theme background overrides any other background
|
||||
if (mIsThemed) {
|
||||
const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
|
||||
@ -1929,11 +2007,15 @@ nsDisplayBackgroundImage::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aCo
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mBackgroundStyle) {
|
||||
nsStyleContext *bgSC;
|
||||
bool hasBG =
|
||||
nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC);
|
||||
if (!hasBG) {
|
||||
*aColor = NS_RGBA(0,0,0,0);
|
||||
return true;
|
||||
}
|
||||
if (mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty()) {
|
||||
const nsStyleBackground* bg = bgSC->GetStyleBackground();
|
||||
if (bg->mLayers[mLayer].mImage.IsEmpty()) {
|
||||
*aColor = NS_RGBA(0,0,0,0);
|
||||
return true;
|
||||
}
|
||||
@ -1941,16 +2023,21 @@ nsDisplayBackgroundImage::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aCo
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackgroundImage::IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame)
|
||||
nsDisplayBackground::IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame)
|
||||
{
|
||||
// theme background overrides any other background and is never fixed
|
||||
if (mIsThemed)
|
||||
return false;
|
||||
|
||||
if (!mBackgroundStyle)
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
nsStyleContext *bgSC;
|
||||
bool hasBG =
|
||||
nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
|
||||
if (!hasBG)
|
||||
return false;
|
||||
if (!mBackgroundStyle->HasFixedBackground())
|
||||
const nsStyleBackground* bg = bgSC->GetStyleBackground();
|
||||
if (!bg->HasFixedBackground())
|
||||
return false;
|
||||
|
||||
// If aFrame is mFrame or an ancestor in this document, and aFrame is
|
||||
@ -1961,44 +2048,40 @@ nsDisplayBackgroundImage::IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* a
|
||||
nsLayoutUtils::IsProperAncestorFrame(aFrame, mFrame));
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplayBackgroundImage::GetPositioningArea()
|
||||
{
|
||||
if (!mBackgroundStyle) {
|
||||
return nsRect();
|
||||
}
|
||||
nsIFrame* attachedToFrame;
|
||||
return nsCSSRendering::ComputeBackgroundPositioningArea(
|
||||
mFrame->PresContext(), mFrame,
|
||||
nsRect(ToReferenceFrame(), mFrame->GetSize()),
|
||||
*mBackgroundStyle, mBackgroundStyle->mLayers[mLayer],
|
||||
&attachedToFrame) + ToReferenceFrame();
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackgroundImage::RenderingMightDependOnPositioningAreaSizeChange()
|
||||
nsDisplayBackground::RenderingMightDependOnFrameSize()
|
||||
{
|
||||
// theme background overrides any other background and we don't know what to do here
|
||||
if (mIsThemed)
|
||||
return true;
|
||||
|
||||
if (!mBackgroundStyle)
|
||||
return false;
|
||||
|
||||
|
||||
// We could be smarter with rounded corners and only invalidate the new area + the piece that was previously
|
||||
// clipped out.
|
||||
nscoord radii[8];
|
||||
if (mFrame->GetBorderRadii(radii)) {
|
||||
// A change in the size of the positioning area might change the position
|
||||
// of the rounded corners.
|
||||
if (mFrame->GetBorderRadii(radii))
|
||||
return true;
|
||||
}
|
||||
|
||||
const nsStyleBackground::Layer &layer = mBackgroundStyle->mLayers[mLayer];
|
||||
if (layer.RenderingMightDependOnPositioningAreaSizeChange()) {
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
nsStyleContext *bgSC;
|
||||
bool hasBG =
|
||||
nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
|
||||
if (!hasBG)
|
||||
return false;
|
||||
const nsStyleBackground* bg = bgSC->GetStyleBackground();
|
||||
|
||||
const nsStyleBackground::Layer &layer = bg->mLayers[mLayer];
|
||||
if (layer.RenderingMightDependOnFrameSize()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackground::ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
return mIsFixed;
|
||||
}
|
||||
|
||||
static void CheckForBorderItem(nsDisplayItem *aItem, uint32_t& aFlags)
|
||||
{
|
||||
nsDisplayItem* nextItem = aItem->GetAbove();
|
||||
@ -2013,8 +2096,8 @@ static void CheckForBorderItem(nsDisplayItem *aItem, uint32_t& aFlags)
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx) {
|
||||
nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx) {
|
||||
|
||||
nsPoint offset = ToReferenceFrame();
|
||||
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
|
||||
@ -2025,36 +2108,30 @@ nsDisplayBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
|
||||
flags, nullptr, mLayer);
|
||||
}
|
||||
|
||||
void nsDisplayBackgroundImage::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion)
|
||||
void nsDisplayBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion)
|
||||
{
|
||||
if (!mBackgroundStyle) {
|
||||
const nsDisplayBackgroundGeometry* geometry = static_cast<const nsDisplayBackgroundGeometry*>(aGeometry);
|
||||
if (ShouldFixToViewport(aBuilder)) {
|
||||
// This is incorrect, We definitely need to check more things here.
|
||||
return;
|
||||
}
|
||||
|
||||
const nsDisplayBackgroundGeometry* geometry = static_cast<const nsDisplayBackgroundGeometry*>(aGeometry);
|
||||
|
||||
bool snap;
|
||||
nsRect bounds = GetBounds(aBuilder, &snap);
|
||||
nsRect positioningArea = GetPositioningArea();
|
||||
if (positioningArea.TopLeft() != geometry->mPositioningArea.TopLeft() ||
|
||||
(positioningArea.Size() != geometry->mPositioningArea.Size() &&
|
||||
RenderingMightDependOnPositioningAreaSizeChange())) {
|
||||
// Positioning area changed in a way that could cause everything to change,
|
||||
// so invalidate everything (both old and new painting areas).
|
||||
aInvalidRegion->Or(bounds, geometry->mBounds);
|
||||
return;
|
||||
}
|
||||
if (!bounds.IsEqualInterior(geometry->mBounds)) {
|
||||
// Positioning area is unchanged, so invalidate just the change in the
|
||||
// painting area.
|
||||
aInvalidRegion->Xor(bounds, geometry->mBounds);
|
||||
if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
|
||||
!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect()) ||
|
||||
!geometry->mContentRect.IsEqualInterior(GetContentRect())) {
|
||||
if (!RenderingMightDependOnFrameSize() && geometry->mBounds.TopLeft() == GetBounds(aBuilder, &snap).TopLeft()) {
|
||||
aInvalidRegion->Xor(GetBounds(aBuilder, &snap), geometry->mBounds);
|
||||
} else {
|
||||
aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplayBackgroundImage::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
|
||||
nsDisplayBackground::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
|
||||
*aSnap = true;
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
|
||||
@ -2071,18 +2148,20 @@ nsDisplayBackgroundImage::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
|
||||
return r + ToReferenceFrame();
|
||||
}
|
||||
|
||||
if (!mBackgroundStyle) {
|
||||
nsStyleContext* bgSC;
|
||||
if (!nsCSSRendering::FindBackground(presContext, mFrame, &bgSC)) {
|
||||
return nsRect();
|
||||
}
|
||||
|
||||
const nsStyleBackground* bg = bgSC->GetStyleBackground();
|
||||
nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
|
||||
const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer];
|
||||
const nsStyleBackground::Layer& layer = bg->mLayers[mLayer];
|
||||
return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
|
||||
borderBox, *mBackgroundStyle, layer);
|
||||
borderBox, *bg, layer);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
nsDisplayBackgroundImage::GetPerFrameKey()
|
||||
nsDisplayBackground::GetPerFrameKey()
|
||||
{
|
||||
return (mLayer << nsDisplayItem::TYPE_BITS) |
|
||||
nsDisplayItem::GetPerFrameKey();
|
||||
@ -2113,27 +2192,31 @@ nsDisplayBackgroundColor::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
return nsRegion();
|
||||
}
|
||||
|
||||
if (!mBackgroundStyle)
|
||||
nsStyleContext* bgSC;
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
if (!nsCSSRendering::FindBackground(presContext, mFrame, &bgSC))
|
||||
return nsRegion();
|
||||
const nsStyleBackground* bg = bgSC->GetStyleBackground();
|
||||
const nsStyleBackground::Layer& bottomLayer = bg->BottomLayer();
|
||||
|
||||
*aSnap = true;
|
||||
|
||||
const nsStyleBackground::Layer& bottomLayer = mBackgroundStyle->BottomLayer();
|
||||
nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
return nsDisplayBackgroundImage::GetInsideClipRegion(this, presContext, bottomLayer.mClip, borderBox, aSnap);
|
||||
return nsDisplayBackground::GetInsideClipRegion(this, presContext, bottomLayer.mClip, borderBox, aSnap);
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackgroundColor::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
|
||||
{
|
||||
*aColor = mColor;
|
||||
|
||||
if (!mBackgroundStyle)
|
||||
nsStyleContext* bgSC;
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
if (!nsCSSRendering::FindBackground(presContext, mFrame, &bgSC))
|
||||
return true;
|
||||
|
||||
const nsStyleBackground* bg = bgSC->GetStyleBackground();
|
||||
return (!nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->mBorderRadius) &&
|
||||
mBackgroundStyle->BottomLayer().mClip == NS_STYLE_BG_CLIP_BORDER);
|
||||
bg->BottomLayer().mClip == NS_STYLE_BG_CLIP_BORDER);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1782,21 +1782,17 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* A display item to paint one background-image for a frame. Each background
|
||||
* image layer gets its own nsDisplayBackgroundImage.
|
||||
* The standard display item to paint the CSS background of a frame.
|
||||
*/
|
||||
class nsDisplayBackgroundImage : public nsDisplayItem {
|
||||
class nsDisplayBackground : public nsDisplayItem {
|
||||
public:
|
||||
/**
|
||||
* aLayer signifies which background layer this item represents.
|
||||
* aIsThemed should be the value of aFrame->IsThemed.
|
||||
* aBackgroundStyle should be the result of
|
||||
* nsCSSRendering::FindBackground, or null if FindBackground returned false.
|
||||
*/
|
||||
nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
uint32_t aLayer, bool aIsThemed,
|
||||
const nsStyleBackground* aBackgroundStyle);
|
||||
virtual ~nsDisplayBackgroundImage();
|
||||
// aLayer signifies which background layer this item represents. Normally
|
||||
// a background layer will only be marked as fixed if it covers the scroll-
|
||||
// port of the root scroll-frame. This check can be skipped using
|
||||
// aSkipFixedItemBoundsCheck.
|
||||
nsDisplayBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
uint32_t aLayer, bool aSkipFixedItemBoundsCheck = false);
|
||||
virtual ~nsDisplayBackground();
|
||||
|
||||
// This will create and append new items for all the layers of the
|
||||
// background. If given, aBackground will be set with the address of the
|
||||
@ -1804,7 +1800,7 @@ public:
|
||||
static nsresult AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame,
|
||||
nsDisplayList* aList,
|
||||
nsDisplayBackgroundImage** aBackground = nullptr);
|
||||
nsDisplayBackground** aBackground = nullptr);
|
||||
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
@ -1824,9 +1820,7 @@ public:
|
||||
virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame) MOZ_OVERRIDE;
|
||||
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE;
|
||||
/**
|
||||
* GetBounds() returns the background painting area.
|
||||
*/
|
||||
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
|
||||
virtual uint32_t GetPerFrameKey() MOZ_OVERRIDE;
|
||||
@ -1834,22 +1828,13 @@ public:
|
||||
// Returns the value of GetUnderlyingFrame()->IsThemed(), but cached
|
||||
bool IsThemed() { return mIsThemed; }
|
||||
|
||||
/**
|
||||
* Return the background positioning area.
|
||||
* (GetBounds() returns the background painting area.)
|
||||
* Can be called only when mBackgroundStyle is non-null.
|
||||
*/
|
||||
nsRect GetPositioningArea();
|
||||
|
||||
/**
|
||||
* Returns true if existing rendered pixels of this display item may need
|
||||
* to be redrawn if the positioning area size changes but its position does
|
||||
* not.
|
||||
* If false, only the changed painting area needs to be redrawn when the
|
||||
* positioning area size changes but its position does not.
|
||||
* to be redrawn if the frame size changes.
|
||||
* If false, only the changed area needs to be redrawn.
|
||||
*/
|
||||
bool RenderingMightDependOnPositioningAreaSizeChange();
|
||||
|
||||
bool RenderingMightDependOnFrameSize();
|
||||
|
||||
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
return new nsDisplayBackgroundGeometry(this, aBuilder);
|
||||
@ -1865,35 +1850,31 @@ protected:
|
||||
typedef class mozilla::layers::ImageContainer ImageContainer;
|
||||
typedef class mozilla::layers::ImageLayer ImageLayer;
|
||||
|
||||
|
||||
bool TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
|
||||
bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aClipRect,
|
||||
gfxRect* aDestRect);
|
||||
bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder, const nsRect& aClipRect);
|
||||
void ConfigureLayer(ImageLayer* aLayer);
|
||||
|
||||
// Cache the result of nsCSSRendering::FindBackground. Always null if
|
||||
// mIsThemed is true or if FindBackground returned false.
|
||||
const nsStyleBackground* mBackgroundStyle;
|
||||
/* Used to cache mFrame->IsThemed() since it isn't a cheap call */
|
||||
bool mIsThemed;
|
||||
/* true if this item represents a background-attachment:fixed layer and
|
||||
* should fix to the viewport. */
|
||||
bool mIsFixed;
|
||||
/* true if this item represents the bottom-most background layer */
|
||||
bool mIsBottommostLayer;
|
||||
nsITheme::Transparency mThemeTransparency;
|
||||
|
||||
/* If this background can be a simple image layer, we store the format here. */
|
||||
nsRefPtr<ImageContainer> mImageContainer;
|
||||
gfxRect mDestRect;
|
||||
uint32_t mLayer;
|
||||
|
||||
nsITheme::Transparency mThemeTransparency;
|
||||
/* Used to cache mFrame->IsThemed() since it isn't a cheap call */
|
||||
bool mIsThemed;
|
||||
/* true if this item represents the bottom-most background layer */
|
||||
bool mIsBottommostLayer;
|
||||
};
|
||||
|
||||
class nsDisplayBackgroundColor : public nsDisplayItem
|
||||
{
|
||||
public:
|
||||
nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
const nsStyleBackground* aBackgroundStyle,
|
||||
nscolor aColor)
|
||||
nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nscolor aColor)
|
||||
: nsDisplayItem(aBuilder, aFrame)
|
||||
, mBackgroundStyle(aBackgroundStyle)
|
||||
, mColor(aColor)
|
||||
{ }
|
||||
|
||||
@ -1913,8 +1894,6 @@ public:
|
||||
|
||||
NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
|
||||
|
||||
protected:
|
||||
const nsStyleBackground* mBackgroundStyle;
|
||||
nscolor mColor;
|
||||
};
|
||||
|
||||
|
@ -42,17 +42,18 @@ nsDisplayBorderGeometry::MoveBy(const nsPoint& aOffset)
|
||||
mContentRect.MoveBy(aOffset);
|
||||
}
|
||||
|
||||
nsDisplayBackgroundGeometry::nsDisplayBackgroundGeometry(nsDisplayBackgroundImage* aItem,
|
||||
nsDisplayListBuilder* aBuilder)
|
||||
nsDisplayBackgroundGeometry::nsDisplayBackgroundGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
|
||||
: nsDisplayItemGeometry(aItem, aBuilder)
|
||||
, mPositioningArea(aItem->GetPositioningArea())
|
||||
, mPaddingRect(aItem->GetPaddingRect())
|
||||
, mContentRect(aItem->GetContentRect())
|
||||
{}
|
||||
|
||||
void
|
||||
nsDisplayBackgroundGeometry::MoveBy(const nsPoint& aOffset)
|
||||
{
|
||||
mBounds.MoveBy(aOffset);
|
||||
mPositioningArea.MoveBy(aOffset);
|
||||
mPaddingRect.MoveBy(aOffset);
|
||||
mContentRect.MoveBy(aOffset);
|
||||
}
|
||||
|
||||
nsDisplayBoxShadowInnerGeometry::nsDisplayBoxShadowInnerGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
class nsDisplayItem;
|
||||
class nsDisplayListBuilder;
|
||||
class nsDisplayBackgroundImage;
|
||||
|
||||
/**
|
||||
* This stores the geometry of an nsDisplayItem, and the area
|
||||
@ -76,11 +75,12 @@ public:
|
||||
class nsDisplayBackgroundGeometry : public nsDisplayItemGeometry
|
||||
{
|
||||
public:
|
||||
nsDisplayBackgroundGeometry(nsDisplayBackgroundImage* aItem, nsDisplayListBuilder* aBuilder);
|
||||
nsDisplayBackgroundGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
|
||||
|
||||
virtual void MoveBy(const nsPoint& aOffset);
|
||||
|
||||
nsRect mPositioningArea;
|
||||
nsRect mPaddingRect;
|
||||
nsRect mContentRect;
|
||||
};
|
||||
|
||||
class nsDisplayBoxShadowInnerGeometry : public nsDisplayItemGeometry
|
||||
|
@ -939,6 +939,9 @@ public:
|
||||
PropertyTable()->DeleteAllFor(aFrame);
|
||||
}
|
||||
|
||||
bool MayHaveFixedBackgroundFrames() { return mMayHaveFixedBackgroundFrames; }
|
||||
void SetHasFixedBackgroundFrame() { mMayHaveFixedBackgroundFrames = true; }
|
||||
|
||||
virtual size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
|
||||
virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
@ -1218,6 +1221,7 @@ protected:
|
||||
unsigned mPendingUIResolutionChanged : 1;
|
||||
unsigned mPendingMediaFeatureValuesChanged : 1;
|
||||
unsigned mPrefChangePendingNeedsReflow : 1;
|
||||
unsigned mMayHaveFixedBackgroundFrames : 1;
|
||||
// True if the requests in mInvalidateRequestsSinceLastPaint cover the
|
||||
// entire viewport
|
||||
unsigned mAllInvalidated : 1;
|
||||
|
@ -206,25 +206,18 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRefPtr<gfxContext> dest = aCtx->ThebesContext();
|
||||
nsRefPtr<gfxASurface> surf;
|
||||
nsRefPtr<gfxContext> ctx;
|
||||
gfxRect destRect;
|
||||
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
|
||||
if (IsSingleFixedPositionImage(aBuilder, bgClipRect, &destRect) &&
|
||||
aBuilder->IsPaintingToWindow() && !aBuilder->IsCompositingCheap() &&
|
||||
!dest->CurrentMatrix().HasNonIntegerTranslation()) {
|
||||
// Snap image rectangle to nearest pixel boundaries. This is the right way
|
||||
// to snap for this context, because we checked HasNonIntegerTranslation above.
|
||||
destRect.Round();
|
||||
if (IsSingleFixedPositionImage(aBuilder, bgClipRect) && aBuilder->IsPaintingToWindow() && !aBuilder->IsCompositingCheap()) {
|
||||
surf = static_cast<gfxASurface*>(GetUnderlyingFrame()->Properties().Get(nsIFrame::CachedBackgroundImage()));
|
||||
nsRefPtr<gfxASurface> destSurf = dest->CurrentSurface();
|
||||
if (surf && surf->GetType() == destSurf->GetType()) {
|
||||
BlitSurface(dest, destRect, surf);
|
||||
BlitSurface(dest, mDestRect, surf);
|
||||
return;
|
||||
}
|
||||
surf = destSurf->CreateSimilarSurface(gfxASurface::CONTENT_COLOR_ALPHA,
|
||||
gfxIntSize(destRect.width, destRect.height));
|
||||
surf = destSurf->CreateSimilarSurface(gfxASurface::CONTENT_COLOR_ALPHA, gfxIntSize(ceil(mDestRect.width), ceil(mDestRect.height)));
|
||||
if (surf) {
|
||||
ctx = new gfxContext(surf);
|
||||
ctx->Translate(-gfxPoint(destRect.x, destRect.y));
|
||||
ctx->Translate(-gfxPoint(mDestRect.x, mDestRect.y));
|
||||
context.Init(aCtx->DeviceContext(), ctx);
|
||||
}
|
||||
}
|
||||
@ -236,7 +229,7 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||
aBuilder->GetBackgroundPaintFlags(),
|
||||
&bgClipRect, mLayer);
|
||||
if (surf) {
|
||||
BlitSurface(dest, destRect, surf);
|
||||
BlitSurface(dest, mDestRect, surf);
|
||||
|
||||
GetUnderlyingFrame()->Properties().Set(nsIFrame::CachedBackgroundImage(), surf.forget().get());
|
||||
GetUnderlyingFrame()->AddStateBits(NS_FRAME_HAS_CACHED_BACKGROUND);
|
||||
@ -298,16 +291,14 @@ nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
if (IsVisibleForPainting(aBuilder)) {
|
||||
nsStyleContext* bgSC;
|
||||
const nsStyleBackground* bg = nullptr;
|
||||
bool isThemed = IsThemed();
|
||||
if (!isThemed &&
|
||||
if (!IsThemed() &&
|
||||
nsCSSRendering::FindBackground(PresContext(), this, &bgSC)) {
|
||||
bg = bgSC->GetStyleBackground();
|
||||
}
|
||||
// Create separate items for each background layer.
|
||||
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
|
||||
rv = aLists.BorderBackground()->AppendNewToTop(
|
||||
new (aBuilder) nsDisplayCanvasBackground(aBuilder, this, i,
|
||||
isThemed, bg));
|
||||
new (aBuilder) nsDisplayCanvasBackground(aBuilder, this, i));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
@ -525,6 +516,39 @@ nsCanvasFrame::Reflow(nsPresContext* aPresContext,
|
||||
aDesiredSize.SetOverflowAreasToDesiredBounds();
|
||||
aDesiredSize.mOverflowAreas.UnionWith(
|
||||
kidDesiredSize.mOverflowAreas + kidPt);
|
||||
|
||||
// Handle invalidating fixed-attachment backgrounds propagated to the
|
||||
// canvas when the canvas size (and therefore the background positioning
|
||||
// area's size) changes. Such backgrounds are not invalidated in the
|
||||
// normal manner because the size of the original frame for that background
|
||||
// may not have changed.
|
||||
//
|
||||
// This isn't the right fix for this issue, taken more generally. In
|
||||
// particular, this doesn't handle fixed-attachment backgrounds that are *not*
|
||||
// propagated. If a layer with the characteristics tested for below exists
|
||||
// in a non-propagated background, we should invalidate the "corresponding"
|
||||
// frame (which subsumes this special case if defined broadly). For now,
|
||||
// however, this addresses the most common case. Given that this behavior has
|
||||
// long been broken (non-zero percent background-size may be a new instance,
|
||||
// but non-zero percent background-position is longstanding), we defer a
|
||||
// fully correct fix until later.
|
||||
if (nsSize(aDesiredSize.width, aDesiredSize.height) != GetSize()) {
|
||||
nsIFrame* rootElementFrame =
|
||||
aPresContext->PresShell()->FrameConstructor()->GetRootElementStyleFrame();
|
||||
nsStyleContext* bgSC =
|
||||
nsCSSRendering::FindCanvasBackground(this, rootElementFrame);
|
||||
const nsStyleBackground* bg = bgSC->GetStyleBackground();
|
||||
if (!bg->IsTransparent()) {
|
||||
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
|
||||
const nsStyleBackground::Layer& layer = bg->mLayers[i];
|
||||
if (layer.mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
|
||||
layer.RenderingMightDependOnFrameSize()) {
|
||||
InvalidateFrame();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prevCanvasFrame) {
|
||||
|
@ -116,20 +116,40 @@ protected:
|
||||
bool mAddedScrollPositionListener;
|
||||
};
|
||||
|
||||
class nsDisplayCanvasBackgroundGeometry : public nsDisplayItemGeometry
|
||||
{
|
||||
public:
|
||||
nsDisplayCanvasBackgroundGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder, const nsRect& aChildBorder)
|
||||
: nsDisplayItemGeometry(aItem, aBuilder)
|
||||
, mChildBorder(aChildBorder)
|
||||
, mPaddingRect(aItem->GetPaddingRect())
|
||||
, mContentRect(aItem->GetContentRect())
|
||||
{}
|
||||
|
||||
virtual void MoveBy(const nsPoint& aOffset)
|
||||
{
|
||||
mBounds.MoveBy(aOffset);
|
||||
mPaddingRect.MoveBy(aOffset);
|
||||
mContentRect.MoveBy(aOffset);
|
||||
}
|
||||
|
||||
nsRect mChildBorder;
|
||||
nsRect mPaddingRect;
|
||||
nsRect mContentRect;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 nsDisplayBackgroundImage {
|
||||
class nsDisplayCanvasBackground : public nsDisplayBackground {
|
||||
public:
|
||||
nsDisplayCanvasBackground(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
|
||||
uint32_t aLayer, bool aIsThemed,
|
||||
const nsStyleBackground* aBackgroundStyle)
|
||||
: nsDisplayBackgroundImage(aBuilder, aFrame, aLayer, aIsThemed, aBackgroundStyle),
|
||||
mExtraBackgroundColor(NS_RGBA(0,0,0,0))
|
||||
nsDisplayCanvasBackground(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame, uint32_t aLayer)
|
||||
: nsDisplayBackground(aBuilder, aFrame, aLayer, true)
|
||||
{
|
||||
mExtraBackgroundColor = NS_RGBA(0,0,0,0);
|
||||
}
|
||||
|
||||
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
@ -137,7 +157,7 @@ public:
|
||||
const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE
|
||||
{
|
||||
return NS_GET_A(mExtraBackgroundColor) > 0 ||
|
||||
nsDisplayBackgroundImage::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
nsDisplayBackground::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion);
|
||||
}
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
@ -146,12 +166,12 @@ public:
|
||||
if (NS_GET_A(mExtraBackgroundColor) == 255) {
|
||||
return nsRegion(GetBounds(aBuilder, aSnap));
|
||||
}
|
||||
return nsDisplayBackgroundImage::GetOpaqueRegion(aBuilder, aSnap);
|
||||
return nsDisplayBackground::GetOpaqueRegion(aBuilder, aSnap);
|
||||
}
|
||||
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE
|
||||
{
|
||||
nscolor background;
|
||||
if (!nsDisplayBackgroundImage::IsUniform(aBuilder, &background))
|
||||
if (!nsDisplayBackground::IsUniform(aBuilder, &background))
|
||||
return false;
|
||||
NS_ASSERTION(background == NS_RGBA(0,0,0,0),
|
||||
"The nsDisplayBackground for a canvas frame doesn't paint "
|
||||
@ -171,17 +191,39 @@ public:
|
||||
// We need to override so we don't consider border-radius.
|
||||
aOutFrames->AppendElement(mFrame);
|
||||
}
|
||||
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
|
||||
|
||||
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
// Put background-attachment:fixed canvas background images in their own
|
||||
// compositing layer. Since we know their background painting area can't
|
||||
// change (unless the viewport size itself changes), async scrolling
|
||||
// will work well.
|
||||
return mBackgroundStyle &&
|
||||
mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
|
||||
!mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty();
|
||||
nsIFrame *child = mFrame->GetFirstPrincipalChild();
|
||||
return new nsDisplayCanvasBackgroundGeometry(this, aBuilder,
|
||||
child ? child->GetRect() : nsRect());;
|
||||
}
|
||||
|
||||
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion)
|
||||
{
|
||||
const nsDisplayCanvasBackgroundGeometry* geometry = static_cast<const nsDisplayCanvasBackgroundGeometry*>(aGeometry);
|
||||
if (ShouldFixToViewport(aBuilder)) {
|
||||
// This is incorrect, We definitely need to check more things here.
|
||||
return;
|
||||
}
|
||||
|
||||
nsIFrame *child = mFrame->GetFirstPrincipalChild();
|
||||
|
||||
bool snap;
|
||||
if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
|
||||
(child && !geometry->mChildBorder.IsEqualInterior(child->GetRect())) ||
|
||||
!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect()) ||
|
||||
!geometry->mContentRect.IsEqualInterior(GetContentRect())) {
|
||||
if (!RenderingMightDependOnFrameSize() && geometry->mBounds.TopLeft() == GetBounds(aBuilder, &snap).TopLeft()) {
|
||||
aInvalidRegion->Xor(GetBounds(aBuilder, &snap), geometry->mBounds);
|
||||
} else {
|
||||
aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx) MOZ_OVERRIDE;
|
||||
|
||||
@ -196,4 +238,5 @@ private:
|
||||
nscolor mExtraBackgroundColor;
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsCanvasFrame_h___ */
|
||||
|
@ -1495,7 +1495,7 @@ nsresult
|
||||
nsFrame::DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists,
|
||||
bool aForceBackground,
|
||||
nsDisplayBackgroundImage** aBackground)
|
||||
nsDisplayBackground** aBackground)
|
||||
{
|
||||
*aBackground = nullptr;
|
||||
|
||||
@ -1504,7 +1504,7 @@ nsFrame::DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
|
||||
// true.
|
||||
if (aBuilder->IsForEventDelivery() || aForceBackground ||
|
||||
!GetStyleBackground()->IsTransparent() || GetStyleDisplay()->mAppearance) {
|
||||
return nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, this,
|
||||
return nsDisplayBackground::AppendBackgroundItemsToTop(aBuilder, this,
|
||||
aLists.BorderBackground(),
|
||||
aBackground);
|
||||
}
|
||||
@ -1530,7 +1530,7 @@ nsFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsDisplayBackgroundImage* bg;
|
||||
nsDisplayBackground* bg;
|
||||
nsresult rv =
|
||||
DisplayBackgroundUnconditional(aBuilder, aLists, aForceBackground, &bg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -99,7 +99,7 @@
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
struct nsBoxLayoutMetrics;
|
||||
class nsDisplayBackgroundImage;
|
||||
class nsDisplayBackground;
|
||||
|
||||
/**
|
||||
* Implementation of a simple frame that's not splittable and has no
|
||||
@ -510,7 +510,7 @@ public:
|
||||
nsresult DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists,
|
||||
bool aForceBackground,
|
||||
nsDisplayBackgroundImage** aBackground);
|
||||
nsDisplayBackground** aBackground);
|
||||
/**
|
||||
* Adds display items for standard CSS borders, background and outline for
|
||||
* for this frame, as necessary. Checks IsVisibleForPainting and won't
|
||||
|
@ -1671,6 +1671,56 @@ CanScrollWithBlitting(nsIFrame* aFrame)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
InvalidateFixedBackgroundFramesFromList(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aMovingFrame,
|
||||
const nsDisplayList& aList)
|
||||
{
|
||||
for (nsDisplayItem* item = aList.GetBottom(); item; item = item->GetAbove()) {
|
||||
nsDisplayList* sublist = item->GetSameCoordinateSystemChildren();
|
||||
if (sublist) {
|
||||
InvalidateFixedBackgroundFramesFromList(aBuilder, aMovingFrame, *sublist);
|
||||
continue;
|
||||
}
|
||||
nsIFrame* f = item->GetUnderlyingFrame();
|
||||
if (f &&
|
||||
item->IsVaryingRelativeToMovingFrame(aBuilder, aMovingFrame)) {
|
||||
if (FrameLayerBuilder::NeedToInvalidateFixedDisplayItem(aBuilder, item)) {
|
||||
// FrameLayerBuilder does not take care of scrolling this one
|
||||
f->InvalidateFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
InvalidateFixedBackgroundFrames(nsIFrame* aRootFrame,
|
||||
nsIFrame* aMovingFrame,
|
||||
const nsRect& aUpdateRect)
|
||||
{
|
||||
if (!aMovingFrame->PresContext()->MayHaveFixedBackgroundFrames())
|
||||
return;
|
||||
|
||||
NS_ASSERTION(aRootFrame != aMovingFrame,
|
||||
"The root frame shouldn't be the one that's moving, that makes no sense");
|
||||
|
||||
// Build the 'after' display list over the whole area of interest.
|
||||
nsDisplayListBuilder builder(aRootFrame, nsDisplayListBuilder::OTHER, true);
|
||||
builder.EnterPresShell(aRootFrame, aUpdateRect);
|
||||
nsDisplayList list;
|
||||
nsresult rv =
|
||||
aRootFrame->BuildDisplayListForStackingContext(&builder, aUpdateRect, &list);
|
||||
builder.LeavePresShell(aRootFrame, aUpdateRect);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
nsRegion visibleRegion(aUpdateRect);
|
||||
list.ComputeVisibilityForRoot(&builder, &visibleRegion);
|
||||
|
||||
InvalidateFixedBackgroundFramesFromList(&builder, aMovingFrame, list);
|
||||
list.DeleteAll();
|
||||
}
|
||||
|
||||
bool nsGfxScrollFrameInner::IsIgnoringViewportClipping() const
|
||||
{
|
||||
if (!mIsRoot)
|
||||
@ -1746,11 +1796,14 @@ void nsGfxScrollFrameInner::ScrollVisual(nsPoint aOldScrolledFramePos)
|
||||
AdjustViews(mScrolledFrame);
|
||||
// We need to call this after fixing up the view positions
|
||||
// to be consistent with the frame hierarchy.
|
||||
bool invalidate = false;
|
||||
bool canScrollWithBlitting = CanScrollWithBlitting(mOuter);
|
||||
mOuter->RemoveStateBits(NS_SCROLLFRAME_INVALIDATE_CONTENTS_ON_SCROLL);
|
||||
if (IsScrollingActive()) {
|
||||
if (!canScrollWithBlitting) {
|
||||
MarkInactive();
|
||||
} else {
|
||||
invalidate = true;
|
||||
}
|
||||
}
|
||||
if (canScrollWithBlitting) {
|
||||
@ -1758,6 +1811,16 @@ void nsGfxScrollFrameInner::ScrollVisual(nsPoint aOldScrolledFramePos)
|
||||
}
|
||||
|
||||
mOuter->SchedulePaint();
|
||||
|
||||
if (invalidate) {
|
||||
nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(mOuter);
|
||||
nsRect update =
|
||||
GetScrollPortRect() + mOuter->GetOffsetToCrossDoc(displayRoot);
|
||||
nsRect displayRootUpdate = update.ConvertAppUnitsRoundOut(
|
||||
mOuter->PresContext()->AppUnitsPerDevPixel(),
|
||||
displayRoot->PresContext()->AppUnitsPerDevPixel());
|
||||
InvalidateFixedBackgroundFrames(displayRoot, mScrolledFrame, displayRootUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2236,6 +2236,7 @@ public:
|
||||
/**
|
||||
* Called when a frame is about to be removed and needs to be invalidated.
|
||||
* Normally does nothing since DLBI handles removed frames.
|
||||
*
|
||||
*/
|
||||
virtual void InvalidateFrameForRemoval() {}
|
||||
|
||||
|
@ -1833,7 +1833,7 @@ nsStyleBackground::Position::SetInitialValues()
|
||||
}
|
||||
|
||||
bool
|
||||
nsStyleBackground::Size::DependsOnPositioningAreaSize(const nsStyleImage& aImage) const
|
||||
nsStyleBackground::Size::DependsOnFrameSize(const nsStyleImage& aImage) const
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aImage.GetType() != eStyleImageType_Null,
|
||||
"caller should have handled this");
|
||||
@ -1963,15 +1963,14 @@ nsStyleBackground::Layer::SetInitialValues()
|
||||
}
|
||||
|
||||
bool
|
||||
nsStyleBackground::Layer::RenderingMightDependOnPositioningAreaSizeChange() const
|
||||
nsStyleBackground::Layer::RenderingMightDependOnFrameSize() const
|
||||
{
|
||||
// Do we even have an image?
|
||||
if (mImage.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mPosition.DependsOnPositioningAreaSize() ||
|
||||
mSize.DependsOnPositioningAreaSize(mImage);
|
||||
return mPosition.DependsOnFrameSize() || mSize.DependsOnFrameSize(mImage);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -330,7 +330,7 @@ struct nsStyleBackground {
|
||||
|
||||
// True if the effective background image position described by this depends
|
||||
// on the size of the corresponding frame.
|
||||
bool DependsOnPositioningAreaSize() const {
|
||||
bool DependsOnFrameSize() const {
|
||||
return mXPosition.mPercent != 0.0f || mYPosition.mPercent != 0.0f;
|
||||
}
|
||||
|
||||
@ -371,7 +371,7 @@ struct nsStyleBackground {
|
||||
// Except for eLengthPercentage, Dimension types which might change
|
||||
// how a layer is painted when the corresponding frame's dimensions
|
||||
// change *must* precede all dimension types which are agnostic to
|
||||
// frame size; see DependsOnDependsOnPositioningAreaSizeSize.
|
||||
// frame size; see DependsOnFrameSize.
|
||||
enum DimensionType {
|
||||
// If one of mWidth and mHeight is eContain or eCover, then both are.
|
||||
// Also, these two values must equal the corresponding values in
|
||||
@ -387,7 +387,7 @@ struct nsStyleBackground {
|
||||
// True if the effective image size described by this depends on the size of
|
||||
// the corresponding frame, when aImage (which must not have null type) is
|
||||
// the background image.
|
||||
bool DependsOnPositioningAreaSize(const nsStyleImage& aImage) const;
|
||||
bool DependsOnFrameSize(const nsStyleImage& aImage) const;
|
||||
|
||||
// Initialize nothing
|
||||
Size() {}
|
||||
@ -450,11 +450,11 @@ struct nsStyleBackground {
|
||||
void SetInitialValues();
|
||||
|
||||
// True if the rendering of this layer might change when the size
|
||||
// of the background positioning area changes. This is true for any
|
||||
// of the corresponding frame changes. This is true for any
|
||||
// non-solid-color background whose position or size depends on
|
||||
// the size of the positioning area. It's also true for SVG images
|
||||
// whose root <svg> node has a viewBox.
|
||||
bool RenderingMightDependOnPositioningAreaSizeChange() const;
|
||||
// the frame size. It's also true for SVG images whose root <svg>
|
||||
// node has a viewBox.
|
||||
bool RenderingMightDependOnFrameSize() const;
|
||||
|
||||
// An equality operator that compares the images using URL-equality
|
||||
// rather than pointer-equality.
|
||||
|
@ -1165,7 +1165,7 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
||||
// handling events.
|
||||
// XXX how to handle collapsed borders?
|
||||
if (aBuilder->IsForEventDelivery()) {
|
||||
nsresult rv = nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
|
||||
nsresult rv = nsDisplayBackground::AppendBackgroundItemsToTop(aBuilder, aFrame,
|
||||
lists->BorderBackground());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
@ -1243,7 +1243,7 @@ nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
// in its own display item, so do that to take advantage of
|
||||
// opacity and visibility optimizations
|
||||
if (deflate == nsMargin(0, 0, 0, 0)) {
|
||||
nsDisplayBackgroundImage* bg;
|
||||
nsDisplayBackground* bg;
|
||||
nsresult rv = DisplayBackgroundUnconditional(aBuilder, aLists, false, &bg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user