mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 12:25:53 +00:00
Bug 653133 - Fennec crashes when loading a page with huge background-attachment:fixed background r=roc
This commit is contained in:
parent
0679b2f21a
commit
3dd472d1eb
@ -138,20 +138,22 @@ static PRBool IsFixedFrame(nsIFrame* aFrame)
|
||||
return aFrame && aFrame->GetParent() && !aFrame->GetParent()->GetParent();
|
||||
}
|
||||
|
||||
static PRBool IsFixedItem(nsDisplayItem *aItem, nsDisplayListBuilder* aBuilder)
|
||||
static PRBool IsFixedItem(nsDisplayItem *aItem, nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aIsFixedBackground)
|
||||
{
|
||||
nsIFrame* activeScrolledRoot =
|
||||
nsLayoutUtils::GetActiveScrolledRootFor(aItem, aBuilder);
|
||||
nsLayoutUtils::GetActiveScrolledRootFor(aItem, aBuilder, aIsFixedBackground);
|
||||
return activeScrolledRoot &&
|
||||
!nsLayoutUtils::ScrolledByViewportScrolling(activeScrolledRoot,
|
||||
aBuilder);
|
||||
}
|
||||
|
||||
static PRBool ForceVisiblityForFixedItem(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem)
|
||||
nsDisplayItem* aItem,
|
||||
PRBool* aIsFixedBackground)
|
||||
{
|
||||
return aBuilder->GetHasDisplayPort() && aBuilder->GetHasFixedItems() &&
|
||||
IsFixedItem(aItem, aBuilder);
|
||||
return aBuilder->GetDisplayPort() && aBuilder->GetHasFixedItems() &&
|
||||
IsFixedItem(aItem, aBuilder, aIsFixedBackground);
|
||||
}
|
||||
|
||||
void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
|
||||
@ -434,6 +436,26 @@ TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder,
|
||||
return opaque;
|
||||
}
|
||||
|
||||
static nsRect GetDisplayPortBounds(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
PRBool aIgnoreTransform)
|
||||
{
|
||||
nsIFrame* frame = aItem->GetUnderlyingFrame();
|
||||
nscoord auPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
|
||||
gfxMatrix transform;
|
||||
|
||||
if (!aIgnoreTransform) {
|
||||
transform = nsLayoutUtils::GetTransformToAncestor(frame,
|
||||
aBuilder->ReferenceFrame());
|
||||
transform.Invert();
|
||||
}
|
||||
|
||||
const nsRect* displayport = aBuilder->GetDisplayPort();
|
||||
return nsLayoutUtils::MatrixTransformRect(
|
||||
nsRect(0, 0, displayport->width, displayport->height),
|
||||
transform, auPerDevPixel);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
@ -477,12 +499,13 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
|
||||
nsRect bounds = item->GetBounds(aBuilder);
|
||||
|
||||
nsRegion itemVisible;
|
||||
itemVisible.And(*aVisibleRegion, bounds);
|
||||
item->mVisibleRect = itemVisible.GetBounds();
|
||||
|
||||
if (ForceVisiblityForFixedItem(aBuilder, item)) {
|
||||
item->mVisibleRect = bounds;
|
||||
PRBool isFixedBackground;
|
||||
if (ForceVisiblityForFixedItem(aBuilder, item, &isFixedBackground)) {
|
||||
itemVisible.And(GetDisplayPortBounds(aBuilder, item, isFixedBackground), bounds);
|
||||
} else {
|
||||
itemVisible.And(*aVisibleRegion, bounds);
|
||||
}
|
||||
item->mVisibleRect = itemVisible.GetBounds();
|
||||
|
||||
PRBool containsRootContentDocBG = PR_FALSE;
|
||||
if (item->ComputeVisibility(aBuilder, aVisibleRegion, aAllowVisibleRegionExpansion,
|
||||
@ -808,12 +831,13 @@ PRBool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRect bounds = GetBounds(aBuilder);
|
||||
|
||||
nsRegion itemVisible;
|
||||
itemVisible.And(*aVisibleRegion, bounds);
|
||||
mVisibleRect = itemVisible.GetBounds();
|
||||
|
||||
if (ForceVisiblityForFixedItem(aBuilder, this)) {
|
||||
mVisibleRect = bounds;
|
||||
PRBool isFixedBackground;
|
||||
if (ForceVisiblityForFixedItem(aBuilder, this, &isFixedBackground)) {
|
||||
itemVisible.And(GetDisplayPortBounds(aBuilder, this, isFixedBackground), bounds);
|
||||
} else {
|
||||
itemVisible.And(*aVisibleRegion, bounds);
|
||||
}
|
||||
mVisibleRect = itemVisible.GetBounds();
|
||||
|
||||
// When we recompute visibility within layers we don't need to
|
||||
// expand the visible region for content behind plugins (the plugin
|
||||
|
@ -295,8 +295,11 @@ public:
|
||||
/**
|
||||
* Call this if using display port for scrolling.
|
||||
*/
|
||||
void SetHasDisplayPort() { mHasDisplayPort = PR_TRUE; }
|
||||
PRBool GetHasDisplayPort() { return mHasDisplayPort; }
|
||||
void SetDisplayPort(const nsRect& aDisplayPort) {
|
||||
mHasDisplayPort = PR_TRUE;
|
||||
mDisplayPort = aDisplayPort;
|
||||
}
|
||||
const nsRect* GetDisplayPort() { return mHasDisplayPort ? &mDisplayPort : nsnull; }
|
||||
|
||||
/**
|
||||
* Call this if ReferenceFrame() is a viewport frame with fixed-position
|
||||
@ -510,6 +513,7 @@ private:
|
||||
PRPackedBool mIsPaintingToWindow;
|
||||
PRPackedBool mSnappingEnabled;
|
||||
PRPackedBool mHasDisplayPort;
|
||||
nsRect mDisplayPort;
|
||||
PRPackedBool mHasFixedItems;
|
||||
};
|
||||
|
||||
|
@ -786,13 +786,20 @@ nsLayoutUtils::GetActiveScrolledRootFor(nsIFrame* aFrame,
|
||||
|
||||
nsIFrame*
|
||||
nsLayoutUtils::GetActiveScrolledRootFor(nsDisplayItem* aItem,
|
||||
nsDisplayListBuilder* aBuilder)
|
||||
nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aShouldFixToViewport)
|
||||
{
|
||||
nsIFrame* f = aItem->GetUnderlyingFrame();
|
||||
if (aShouldFixToViewport) {
|
||||
*aShouldFixToViewport = PR_FALSE;
|
||||
}
|
||||
if (!f) {
|
||||
return nsnull;
|
||||
}
|
||||
if (aItem->ShouldFixToViewport(aBuilder)) {
|
||||
if (aShouldFixToViewport) {
|
||||
*aShouldFixToViewport = PR_TRUE;
|
||||
}
|
||||
// Make its active scrolled root be the active scrolled root of
|
||||
// the enclosing viewport, since it shouldn't be scrolled by scrolled
|
||||
// frames in its document. InvalidateFixedBackgroundFramesFromList in
|
||||
@ -1087,24 +1094,21 @@ nsLayoutUtils::MatrixTransformPoint(const nsPoint &aPoint,
|
||||
NSFloatPixelsToAppUnits(float(image.y), aFactor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the CTM at the specified frame.
|
||||
*
|
||||
* @param aFrame The frame at which we should calculate the CTM.
|
||||
* @return The CTM at the specified frame.
|
||||
*/
|
||||
static gfxMatrix GetCTMAt(nsIFrame *aFrame)
|
||||
gfxMatrix nsLayoutUtils::GetTransformToAncestor(nsIFrame *aFrame,
|
||||
nsIFrame* aStopAtAncestor)
|
||||
{
|
||||
gfxMatrix ctm;
|
||||
|
||||
/* Starting at the specified frame, we'll use the GetTransformMatrix
|
||||
* function of the frame, which gives us a matrix from this frame up
|
||||
* to some other ancestor frame. Once this function returns null,
|
||||
* we've hit the top of the frame tree and can stop. We get the CTM
|
||||
* by simply accumulating all of these matrices together.
|
||||
* to some other ancestor frame. If aStopAtAncestor frame is not reached,
|
||||
* we stop at root. We get the CTM by simply accumulating all of these
|
||||
* matrices together.
|
||||
*/
|
||||
while (aFrame)
|
||||
while (aFrame && aFrame != aStopAtAncestor) {
|
||||
ctm *= aFrame->GetTransformMatrix(&aFrame);
|
||||
}
|
||||
NS_ASSERTION(aFrame == aStopAtAncestor, "How did we manage to miss the ancestor?");
|
||||
return ctm;
|
||||
}
|
||||
|
||||
@ -1117,7 +1121,7 @@ nsLayoutUtils::InvertTransformsToRoot(nsIFrame *aFrame,
|
||||
/* To invert everything to the root, we'll get the CTM, invert it, and use it to transform
|
||||
* the point.
|
||||
*/
|
||||
gfxMatrix ctm = GetCTMAt(aFrame);
|
||||
gfxMatrix ctm = GetTransformToAncestor(aFrame);
|
||||
|
||||
/* If the ctm is singular, hand back (0, 0) as a sentinel. */
|
||||
if (ctm.IsSingular())
|
||||
@ -1447,7 +1451,7 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
nsDisplayListBuilder builder(aFrame, nsDisplayListBuilder::PAINTING,
|
||||
!(aFlags & PAINT_HIDE_CARET));
|
||||
if (usingDisplayPort) {
|
||||
builder.SetHasDisplayPort();
|
||||
builder.SetDisplayPort(displayport);
|
||||
}
|
||||
|
||||
nsDisplayList list;
|
||||
|
@ -330,7 +330,8 @@ public:
|
||||
nsIFrame* aStopAtAncestor);
|
||||
|
||||
static nsIFrame* GetActiveScrolledRootFor(nsDisplayItem* aItem,
|
||||
nsDisplayListBuilder* aBuilder);
|
||||
nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aShouldFixToViewport = nsnull);
|
||||
|
||||
static PRBool ScrolledByViewportScrolling(nsIFrame* aActiveScrolledRoot,
|
||||
nsDisplayListBuilder* aBuilder);
|
||||
@ -508,6 +509,18 @@ public:
|
||||
PRBool aShouldIgnoreSuppression = PR_FALSE,
|
||||
PRBool aIgnoreRootScrollFrame = PR_FALSE);
|
||||
|
||||
/**
|
||||
* Returns the CTM at the specified frame. This matrix can be used to map
|
||||
* coordinates from aFrame's to aStopAtAncestor's coordinate system.
|
||||
*
|
||||
* @param aFrame The frame at which we should calculate the CTM.
|
||||
* @param aStopAtAncestor is an ancestor frame to stop at. If it's nsnull,
|
||||
* matrix accumulating stops at root.
|
||||
* @return The CTM at the specified frame.
|
||||
*/
|
||||
static gfxMatrix GetTransformToAncestor(nsIFrame *aFrame,
|
||||
nsIFrame* aStopAtAncestor = nsnull);
|
||||
|
||||
/**
|
||||
* Given a point in the global coordinate space, returns that point expressed
|
||||
* in the coordinate system of aFrame. This effectively inverts all transforms
|
||||
|
Loading…
Reference in New Issue
Block a user