зеркало из https://github.com/mozilla/gecko-dev.git
Bug 335140. Set 'force descend into' bit on frames and then leave it set until we're done with the display list ... then we can be sure of descending to frames whose container is not an ancestor of the placeholder. r=mrbkap
This commit is contained in:
Родитель
7a08d41dc8
Коммит
d9cf8d8bf8
|
@ -50,6 +50,8 @@
|
|||
#include "nsIViewManager.h"
|
||||
#include "nsIBlender.h"
|
||||
#include "nsTransform2D.h"
|
||||
#include "nsFrameManager.h"
|
||||
#include "nsPlaceholderFrame.h"
|
||||
|
||||
#ifdef MOZ_CAIRO_GFX
|
||||
#include "gfxContext.h"
|
||||
|
@ -83,7 +85,68 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
|||
}
|
||||
}
|
||||
|
||||
// Destructor function for the dirty rect property
|
||||
static void
|
||||
DestroyRectFunc(void* aFrame,
|
||||
nsIAtom* aPropertyName,
|
||||
void* aPropertyValue,
|
||||
void* aDtorData)
|
||||
{
|
||||
delete NS_STATIC_CAST(nsRect*, aPropertyValue);
|
||||
}
|
||||
|
||||
static nsIFrame* GetParentOrPlaceholderFor(nsFrameManager* aFrameManager,
|
||||
nsIFrame* aFrame) {
|
||||
if (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
|
||||
return aFrameManager->GetPlaceholderFrameFor(aFrame);
|
||||
}
|
||||
return aFrame->GetParent();
|
||||
}
|
||||
|
||||
static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
|
||||
nsFrameManager* frameManager = aFrame->GetPresContext()->PresShell()->FrameManager();
|
||||
|
||||
for (nsIFrame* f = aFrame; f; f = GetParentOrPlaceholderFor(frameManager, f)) {
|
||||
if (f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)
|
||||
return;
|
||||
f->AddStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
|
||||
if (f == aStopAtFrame) {
|
||||
// we've reached a frame that we know will be painted, so we can stop.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
|
||||
const nsRect& aDirtyRect) {
|
||||
nsRect dirty = aDirtyRect - aFrame->GetOffsetTo(aDirtyFrame);
|
||||
nsRect overflowRect = aFrame->GetOverflowRect();
|
||||
if (!dirty.IntersectRect(dirty, overflowRect))
|
||||
return;
|
||||
// if "new nsRect" fails, this won't do anything, but that's okay
|
||||
aFrame->SetProperty(nsLayoutAtoms::outOfFlowDirtyRectProperty,
|
||||
new nsRect(dirty), DestroyRectFunc);
|
||||
|
||||
MarkFrameForDisplay(aFrame, aDirtyFrame);
|
||||
}
|
||||
|
||||
static void UnmarkFrameForDisplay(nsIFrame* aFrame) {
|
||||
aFrame->DeleteProperty(nsLayoutAtoms::outOfFlowDirtyRectProperty);
|
||||
|
||||
nsFrameManager* frameManager = aFrame->GetPresContext()->PresShell()->FrameManager();
|
||||
|
||||
for (nsIFrame* f = aFrame; f; f = GetParentOrPlaceholderFor(frameManager, f)) {
|
||||
if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO))
|
||||
return;
|
||||
f->RemoveStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
|
||||
}
|
||||
}
|
||||
|
||||
nsDisplayListBuilder::~nsDisplayListBuilder() {
|
||||
for (PRUint32 i = 0; i < mFramesMarkedForDisplay.Length(); ++i) {
|
||||
UnmarkFrameForDisplay(mFramesMarkedForDisplay[i]);
|
||||
}
|
||||
|
||||
PL_FreeArenaPool(&mPool);
|
||||
PL_FinishArenaPool(&mPool);
|
||||
}
|
||||
|
@ -106,18 +169,24 @@ nsDisplayListBuilder::GetCaret() {
|
|||
void
|
||||
nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame,
|
||||
const nsRect& aDirtyRect) {
|
||||
if (!mBuildCaret) {
|
||||
if (!mBuildCaret)
|
||||
return;
|
||||
}
|
||||
|
||||
nsIPresShell* shell = aReferenceFrame->GetPresContext()->PresShell();
|
||||
nsCOMPtr<nsICaret> caret;
|
||||
shell->GetCaret(getter_AddRefs(caret));
|
||||
nsIFrame* frame = caret->GetCaretFrame();
|
||||
|
||||
nsLayoutUtils::MarkCaretSubtreeForPainting(this, aReferenceFrame,
|
||||
frame, caret->GetCaretRect(),
|
||||
aDirtyRect, PR_TRUE);
|
||||
if (frame) {
|
||||
// Check if the dirty rect intersects with the caret's dirty rect.
|
||||
nsRect caretRect =
|
||||
caret->GetCaretRect() + frame->GetOffsetTo(aReferenceFrame);
|
||||
if (caretRect.Intersects(aDirtyRect)) {
|
||||
// Okay, our rects intersect, let's mark the frame and all of its ancestors.
|
||||
mFramesMarkedForDisplay.AppendElement(frame);
|
||||
MarkFrameForDisplay(frame, nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
mCaretStates.AppendElement(frame);
|
||||
}
|
||||
|
@ -126,26 +195,27 @@ void
|
|||
nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame,
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
if (!mBuildCaret) {
|
||||
if (!mBuildCaret)
|
||||
return;
|
||||
}
|
||||
|
||||
// Pop the state off.
|
||||
NS_ASSERTION(mCaretStates.Length() > 0, "Leaving too many PresShell");
|
||||
nsICaret* caret = GetCaret();
|
||||
if (caret) {
|
||||
nsLayoutUtils::MarkCaretSubtreeForPainting(this, aReferenceFrame,
|
||||
GetCaretFrame(),
|
||||
caret->GetCaretRect(),
|
||||
aDirtyRect, PR_FALSE);
|
||||
} else {
|
||||
NS_ASSERTION(GetCaretFrame() == nsnull,
|
||||
"GetCaret and LeavePresShell diagree");
|
||||
}
|
||||
NS_ASSERTION(GetCaret() || GetCaretFrame() == nsnull,
|
||||
"GetCaret and LeavePresShell diagree");
|
||||
|
||||
mCaretStates.SetLength(mCaretStates.Length() - 1);
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame, nsIFrame* aFrames,
|
||||
const nsRect& aDirtyRect) {
|
||||
while (aFrames) {
|
||||
mFramesMarkedForDisplay.AppendElement(aFrames);
|
||||
MarkOutOfFlowFrameForDisplay(aDirtyFrame, aFrames, aDirtyRect);
|
||||
aFrames = aFrames->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
nsDisplayListBuilder::Allocate(size_t aSize) {
|
||||
void *tmp;
|
||||
|
|
|
@ -235,6 +235,17 @@ public:
|
|||
*/
|
||||
void LeavePresShell(nsIFrame* aReferenceFrame, const nsRect& aDirtyRect);
|
||||
|
||||
/**
|
||||
* Mark aFrames and its (next) siblings to be displayed if they
|
||||
* intersect aDirtyRect (which is relative to aDirtyFrame). If the
|
||||
* frame(s) have placeholders that might not be displayed, we mark the
|
||||
* placeholders and their ancestors to ensure that display list construction
|
||||
* descends into them anyway. nsDisplayListBuilder will take care of
|
||||
* unmarking them when it is destroyed.
|
||||
*/
|
||||
void MarkFramesForDisplayList(nsIFrame* aDirtyFrame, nsIFrame* aFrames,
|
||||
const nsRect& aDirtyRect);
|
||||
|
||||
/**
|
||||
* Allocate memory in our arena. It will only be freed when this display list
|
||||
* builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
|
||||
|
@ -272,7 +283,8 @@ private:
|
|||
nsIFrame* mIgnoreScrollFrame;
|
||||
PLArenaPool mPool;
|
||||
nsCOMPtr<nsISelection> mBoundingSelection;
|
||||
nsTArray<nsIFrame *> mCaretStates;
|
||||
nsTArray<nsIFrame*> mCaretStates;
|
||||
nsTArray<nsIFrame*> mFramesMarkedForDisplay;
|
||||
PRPackedBool mBuildCaret;
|
||||
PRPackedBool mEventDelivery;
|
||||
PRPackedBool mIsBackgroundOnly;
|
||||
|
|
|
@ -960,40 +960,3 @@ nsLayoutUtils::ScrollIntoView(nsIFormControlFrame* aFormFrame)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsLayoutUtils::MarkCaretSubtreeForPainting(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aReferenceFrame,
|
||||
nsIFrame* aCaretFrame,
|
||||
const nsRect& aCaretRect,
|
||||
const nsRect& aRealDirtyRect,
|
||||
PRBool aMark)
|
||||
{
|
||||
// Easy test: If there is no caret, we don't have anything to do.
|
||||
if (!aCaretFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(aReferenceFrame, "We must have a reference frame");
|
||||
|
||||
// Check if the dirty rect intersects with the caret's dirty rect.
|
||||
nsRect caretRect = aCaretRect + aCaretFrame->GetOffsetTo(aReferenceFrame);
|
||||
if (!caretRect.Intersects(aRealDirtyRect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aMark) {
|
||||
// Okay, our rects intersect, let's mark the frame and all of its ancestors.
|
||||
do {
|
||||
aCaretFrame->AddStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
|
||||
aCaretFrame = aCaretFrame->GetParent();
|
||||
} while (aCaretFrame);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
aCaretFrame->RemoveStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
|
||||
aCaretFrame = aCaretFrame->GetParent();
|
||||
} while (aCaretFrame);
|
||||
}
|
||||
|
|
|
@ -413,26 +413,6 @@ public:
|
|||
* @param aFormFrame Frame to scroll into view.
|
||||
*/
|
||||
static void ScrollIntoView(nsIFormControlFrame* aFormFrame);
|
||||
|
||||
/**
|
||||
* Ensure that the caret frame's subtree is painted by the next paint.
|
||||
* @param aBuilder The display list builder that we're going to be painting
|
||||
* with.
|
||||
* @param aCaretFrame The frame that the caret is currently in.
|
||||
* @param aReferenceFrame The frame whose coodinate space aRealDirtyRect is
|
||||
* in.
|
||||
* @param aCaretRect The rect (in aCaretFrame's coordinates) that the caret
|
||||
* wants to be in.
|
||||
* @param aRealDirtyRect The rect (in aReferenceFrame's coordinates) that is
|
||||
* the original dirty rect.
|
||||
* @param aMark Whether we're marking or unmarking the frames.
|
||||
*/
|
||||
static void MarkCaretSubtreeForPainting(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aReferenceFrame,
|
||||
nsIFrame* aCaretFrame,
|
||||
const nsRect& aCaretRect,
|
||||
const nsRect& aRealDirtyRect,
|
||||
PRBool aMark);
|
||||
};
|
||||
|
||||
#endif // nsLayoutUtils_h__
|
||||
|
|
|
@ -6301,7 +6301,11 @@ DisplayLine(nsDisplayListBuilder* aBuilder, const nsRect& aLineArea,
|
|||
}
|
||||
DebugOutputDrawLine(aDepth, aLine.get(), intersect);
|
||||
#endif
|
||||
if (!intersect && !(aFrame->GetStateBits() & NS_FRAME_HAS_DESCENDANT_PLACEHOLDER))
|
||||
// The line might contain a placeholder for a visible out-of-flow, in which
|
||||
// case we need to descend into it. If there is such a placeholder, we will
|
||||
// have NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO set.
|
||||
if (!intersect &&
|
||||
!(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO))
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
|
@ -6360,13 +6364,13 @@ nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
DisplayBorderBackgroundOutline(aBuilder, aLists);
|
||||
|
||||
MarkOutOfFlowChildrenForDisplayList(mFloats.FirstChild(), aDirtyRect);
|
||||
MarkOutOfFlowChildrenForDisplayList(mAbsoluteContainer.GetFirstChild(), aDirtyRect);
|
||||
aBuilder->MarkFramesForDisplayList(this, mFloats.FirstChild(), aDirtyRect);
|
||||
aBuilder->MarkFramesForDisplayList(this, mAbsoluteContainer.GetFirstChild(), aDirtyRect);
|
||||
|
||||
// Don't use the line cursor if we have a descendant placeholder ... we could
|
||||
// skip lines that contain placeholders but don't themselves intersect with
|
||||
// the dirty area.
|
||||
nsLineBox* cursor = GetStateBits() & NS_FRAME_HAS_DESCENDANT_PLACEHOLDER
|
||||
// Don't use the line cursor if we might have a descendant placeholder ...
|
||||
// it might skip lines that contain placeholders but don't themselves
|
||||
// intersect with the dirty area.
|
||||
nsLineBox* cursor = GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO
|
||||
? nsnull : GetFirstLineContaining(aDirtyRect.y);
|
||||
line_iterator line_end = end_lines();
|
||||
nsresult rv = NS_OK;
|
||||
|
@ -6443,9 +6447,6 @@ nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
#endif
|
||||
|
||||
UnmarkOutOfFlowChildrenForDisplayList(mFloats.FirstChild());
|
||||
UnmarkOutOfFlowChildrenForDisplayList(mAbsoluteContainer.GetFirstChild());
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -973,7 +973,6 @@ static PRBool ApplyAbsPosClipping(nsDisplayListBuilder* aBuilder,
|
|||
// for nsLayoutUtils::ComputeRepaintRegionForCopy ... but this is a rare
|
||||
// situation.
|
||||
if (aBuilder->HasMovingFrames() &&
|
||||
(aFrame->GetStateBits() & NS_FRAME_HAS_DESCENDANT_PLACEHOLDER) &&
|
||||
aFrame->GetPresContext()->FrameManager()->GetRootFrame()->
|
||||
GetFirstChild(nsLayoutAtoms::fixedList) &&
|
||||
aBuilder->IsMovingFrame(aFrame))
|
||||
|
@ -1138,10 +1137,8 @@ nsresult
|
|||
nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
nsDisplayList* aList) {
|
||||
if (GetStateBits() & NS_FRAME_IS_UNFLOWABLE) {
|
||||
RemoveStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
|
||||
if (GetStateBits() & NS_FRAME_IS_UNFLOWABLE)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Replaced elements have their visibility handled here, because
|
||||
// they're visually atomic
|
||||
|
@ -1167,7 +1164,6 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
nsDisplayListBuilder::AutoIsRootSetter rootSetter(aBuilder, PR_TRUE);
|
||||
rv = BuildDisplayList(aBuilder, dirtyRect, set);
|
||||
}
|
||||
RemoveStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aBuilder->IsBackgroundOnly()) {
|
||||
|
@ -1255,70 +1251,6 @@ static nsIFrame* GetParentOrPlaceholderFor(nsFrameManager* aFrameManager, nsIFra
|
|||
return aFrame->GetParent();
|
||||
}
|
||||
|
||||
// Destructor function for the overflow area property
|
||||
static void
|
||||
DestroyRectFunc(void* aFrame,
|
||||
nsIAtom* aPropertyName,
|
||||
void* aPropertyValue,
|
||||
void* aDtorData)
|
||||
{
|
||||
delete NS_STATIC_CAST(nsRect*, aPropertyValue);
|
||||
}
|
||||
|
||||
static void MarkOutOfFlowChild(nsIFrame* aFrame, nsIFrame* aChild,
|
||||
const nsRect& aDirtyRect, PRBool aMark) {
|
||||
if (aMark) {
|
||||
nsRect dirty = aDirtyRect - aChild->GetOffsetTo(aFrame);
|
||||
nsRect overflowRect = aChild->GetOverflowRect();
|
||||
if (!dirty.IntersectRect(dirty, overflowRect))
|
||||
return;
|
||||
// if "new nsRect" fails, this won't do anything, but that's okay
|
||||
aChild->SetProperty(nsLayoutAtoms::outOfFlowDirtyRectProperty,
|
||||
new nsRect(dirty), DestroyRectFunc);
|
||||
} else {
|
||||
aChild->DeleteProperty(nsLayoutAtoms::outOfFlowDirtyRectProperty);
|
||||
}
|
||||
|
||||
nsFrameManager* frameManager = aChild->GetPresContext()->PresShell()->FrameManager();
|
||||
nsIFrame* placeholder = frameManager->GetPlaceholderFrameFor(aChild);
|
||||
NS_ASSERTION(placeholder, "No placeholder for out of flow?");
|
||||
if (!placeholder)
|
||||
return;
|
||||
|
||||
nsIFrame* f;
|
||||
for (f = placeholder; f; f = GetParentOrPlaceholderFor(frameManager, f)) {
|
||||
if (((f->GetStateBits() & NS_FRAME_HAS_DESCENDANT_PLACEHOLDER) != 0)
|
||||
== aMark)
|
||||
return;
|
||||
if (aMark) {
|
||||
f->AddStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
|
||||
} else {
|
||||
f->RemoveStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
|
||||
}
|
||||
if (f == aFrame)
|
||||
break;
|
||||
}
|
||||
NS_ASSERTION(f, "Did not find ourselves on the placeholder's ancestor chain");
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::MarkOutOfFlowChildrenForDisplayList(nsIFrame* aFirstChild,
|
||||
const nsRect& aDirtyRect) {
|
||||
while (aFirstChild) {
|
||||
MarkOutOfFlowChild(this, aFirstChild, aDirtyRect, PR_TRUE);
|
||||
aFirstChild = aFirstChild->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::UnmarkOutOfFlowChildrenForDisplayList(nsIFrame* aFirstChild) {
|
||||
nsRect empty;
|
||||
while (aFirstChild) {
|
||||
MarkOutOfFlowChild(this, aFirstChild, empty, PR_FALSE);
|
||||
aFirstChild = aFirstChild->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static void PaintDebugBorder(nsIFrame* aFrame, nsIRenderingContext* aCtx,
|
||||
const nsRect& aDirtyRect, nsPoint aPt) {
|
||||
|
@ -1394,13 +1326,10 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
// to descend into it because its scrolled child may intersect the dirty
|
||||
// area even if the scrollframe itself doesn't.
|
||||
if (dirty.IsEmpty() &&
|
||||
!(aChild->GetStateBits() & NS_FRAME_HAS_DESCENDANT_PLACEHOLDER) &&
|
||||
!(aChild->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) &&
|
||||
aChild != aBuilder->GetIgnoreScrollFrame())
|
||||
return NS_OK;
|
||||
|
||||
// Don't remove NS_FRAME_HAS_DESCENDANT_PLACEHOLDER until after we've
|
||||
// processed the frame ... it could be useful for frames to know this
|
||||
|
||||
if (aChild->GetStyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE)
|
||||
return NS_OK;
|
||||
// XXX need to have inline-block and inline-table set pseudoStackingContext
|
||||
|
@ -1455,7 +1384,6 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
rv = aBuilder->DisplayCaret(aChild, dirty, aLists);
|
||||
}
|
||||
}
|
||||
aChild->RemoveStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1495,7 +1423,6 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
rv = aBuilder->DisplayCaret(aChild, dirty, aLists);
|
||||
}
|
||||
}
|
||||
aChild->RemoveStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (isPositioned && applyAbsPosClipping) {
|
||||
|
@ -4610,6 +4537,16 @@ nsFrame::GetAccessible(nsIAccessible** aAccessible)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Destructor function for the overflow area property
|
||||
static void
|
||||
DestroyRectFunc(void* aFrame,
|
||||
nsIAtom* aPropertyName,
|
||||
void* aPropertyValue,
|
||||
void* aDtorData)
|
||||
{
|
||||
delete NS_STATIC_CAST(nsRect*, aPropertyValue);
|
||||
}
|
||||
|
||||
nsRect*
|
||||
nsIFrame::GetOverflowAreaProperty(PRBool aCreateIfNecessary)
|
||||
{
|
||||
|
|
|
@ -140,7 +140,7 @@ typedef PRUint32 nsFrameState;
|
|||
|
||||
#define NS_FRAME_IN_REFLOW 0x00000001
|
||||
// This is only set during painting
|
||||
#define NS_FRAME_HAS_DESCENDANT_PLACEHOLDER 0x00000001
|
||||
#define NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO 0x00000001
|
||||
|
||||
// This bit is set when a frame is created. After it has been reflowed
|
||||
// once (during the DidReflow with a finished state) the bit is
|
||||
|
@ -752,35 +752,6 @@ public:
|
|||
const nsDisplayListSet& aToSet,
|
||||
const nsRect& aClipRect);
|
||||
|
||||
/**
|
||||
* Out-of-flow elements are painted as if they were part of their
|
||||
* containing element, for clipping, compositing and z-ordering (modulo
|
||||
* special z-order rules for floats and positioned elements). Therefore
|
||||
* we paint out-of-flow frames through their placeholders. During
|
||||
* display list construction, a container for out-of-flow frames will invoke
|
||||
* this method on itself to mark ancestors of relevant placeholders --- up to
|
||||
* and including itself --- with NS_FRAME_HAS_DESCENDANT_PLACEHOLDER, to
|
||||
* ensure that those frames are descended into during display list
|
||||
* construction (they might otherwise be excluded if they do not
|
||||
* intersect the dirty rect).
|
||||
*
|
||||
* After display list construction of descendants has finished, we call
|
||||
* UnmarkOutOfFlowChildrenForDisplayList on each out-of-flow child. For
|
||||
* performance reasons we also unmark each frame after we have finished
|
||||
* building a display list for it; this allows
|
||||
* UnmarkOutOfFlowChildrenForDisplayList to terminate early when it reaches
|
||||
* a frame in its parent chain without the NS_FRAME_HAS_DESCENDANT_PLACEHOLDER
|
||||
* bit. If CSS 'visiblity' is not being used and there are no failures during
|
||||
* painting, each out-of-flow's placeholder will have been unmarked and so
|
||||
* UnmarkOutOfFlowChildrenForDisplayList won't need to do any real work.
|
||||
*
|
||||
* @param aFirstChild the first frame to mark; we mark the entire sibling
|
||||
* list
|
||||
*/
|
||||
void MarkOutOfFlowChildrenForDisplayList(nsIFrame* aFirstChild,
|
||||
const nsRect& aDirtyRect);
|
||||
void UnmarkOutOfFlowChildrenForDisplayList(nsIFrame* aFirstChild);
|
||||
|
||||
enum {
|
||||
DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01,
|
||||
DISPLAY_CHILD_INLINE = 0x02
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsIAccessibilityService.h"
|
||||
#endif
|
||||
#include "nsDisplayList.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#undef NOISY_PUSHING
|
||||
|
@ -1085,10 +1086,8 @@ nsPositionedInlineFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists)
|
||||
{
|
||||
MarkOutOfFlowChildrenForDisplayList(mAbsoluteContainer.GetFirstChild(), aDirtyRect);
|
||||
nsresult rv = nsHTMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
|
||||
UnmarkOutOfFlowChildrenForDisplayList(mAbsoluteContainer.GetFirstChild());
|
||||
return rv;
|
||||
aBuilder->MarkFramesForDisplayList(this, mAbsoluteContainer.GetFirstChild(), aDirtyRect);
|
||||
return nsHTMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
|
||||
}
|
||||
|
||||
nsIAtom*
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "nsPresContext.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsDisplayList.h"
|
||||
|
||||
nsIFrame*
|
||||
NS_NewViewportFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
|
@ -93,17 +94,16 @@ ViewportFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
// mark our visible out-of-flow frames (i.e., the fixed position frames) so
|
||||
// that display list construction is guaranteed to recurse into their
|
||||
// ancestors.
|
||||
MarkOutOfFlowChildrenForDisplayList(mFixedContainer.GetFirstChild(), aDirtyRect);
|
||||
aBuilder->MarkFramesForDisplayList(this, mFixedContainer.GetFirstChild(), aDirtyRect);
|
||||
|
||||
nsIFrame* kid = mFrames.FirstChild();
|
||||
nsresult rv = NS_OK;
|
||||
if (kid) {
|
||||
// make the kid's BorderBackground our own. This ensures that the canvas
|
||||
// frame's background becomes our own background and therefore appears
|
||||
// below negative z-index elements.
|
||||
rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
|
||||
}
|
||||
UnmarkOutOfFlowChildrenForDisplayList(mFixedContainer.GetFirstChild());
|
||||
return rv;
|
||||
if (!kid)
|
||||
return NS_OK;
|
||||
|
||||
// make the kid's BorderBackground our own. This ensures that the canvas
|
||||
// frame's background becomes our own background and therefore appears
|
||||
// below negative z-index elements.
|
||||
return BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
Загрузка…
Ссылка в новой задаче