Bug 475968. Eliminate NS_FRAME_OUTSIDE_CHILDREN flag, store small overflow areas cheaply within the frame. r+sr=roc
This commit is contained in:
@@ -148,7 +148,7 @@ The table cell requires its children to compute the MES. It is reported back fro
|
|||||||
The block has been required to compute the max. element size only once and it reports now:
|
The block has been required to compute the max. element size only once and it reports now:
|
||||||
<p> <code class="log">block 02D7BCF8 d=1410,300</code></p>
|
<p> <code class="log">block 02D7BCF8 d=1410,300</code></p>
|
||||||
<p>The block shows the same address as the previous one.
|
<p>The block shows the same address as the previous one.
|
||||||
<p>Frames with children that overflow the parent have the <code>NS_FRAME_OUTSIDE_CHILDREN</code> flag set. For these frames
|
<p>Frames with children that overflow the parent will return <code>PR_TRUE</code> from <code>HasOverflowRect()</code>. For these frames
|
||||||
the overflow area is displayed as <code class="log">block 025ED8F0 d=8940,1020 o=(0,0) 9180 x 1020</code>. The overflow area is specified as (x,y) origin and width x height.
|
the overflow area is displayed as <code class="log">block 025ED8F0 d=8940,1020 o=(0,0) 9180 x 1020</code>. The overflow area is specified as (x,y) origin and width x height.
|
||||||
<p> The reflow finishes at the same level where it started.
|
<p> The reflow finishes at the same level where it started.
|
||||||
|
|
||||||
|
|||||||
@@ -368,7 +368,7 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
fprintf(out, " [state=%08x]", mState);
|
fprintf(out, " [state=%08x]", mState);
|
||||||
}
|
}
|
||||||
nsBlockFrame* f = const_cast<nsBlockFrame*>(this);
|
nsBlockFrame* f = const_cast<nsBlockFrame*>(this);
|
||||||
if (f->GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
|
if (f->HasOverflowRect()) {
|
||||||
nsRect overflowArea = f->GetOverflowRect();
|
nsRect overflowArea = f->GetOverflowRect();
|
||||||
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
|
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
|
||||||
overflowArea.width, overflowArea.height);
|
overflowArea.width, overflowArea.height);
|
||||||
@@ -1186,7 +1186,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
aStatus, NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not ",
|
aStatus, NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not ",
|
||||||
aMetrics.width, aMetrics.height,
|
aMetrics.width, aMetrics.height,
|
||||||
aMetrics.mCarriedOutBottomMargin.get());
|
aMetrics.mCarriedOutBottomMargin.get());
|
||||||
if (mState & NS_FRAME_OUTSIDE_CHILDREN) {
|
if (HasOverflowRect()) {
|
||||||
printf(" combinedArea={%d,%d,%d,%d}",
|
printf(" combinedArea={%d,%d,%d,%d}",
|
||||||
aMetrics.mOverflowArea.x,
|
aMetrics.mOverflowArea.x,
|
||||||
aMetrics.mOverflowArea.y,
|
aMetrics.mOverflowArea.y,
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!(NS_FRAME_OUTSIDE_CHILDREN & mFrame->GetStateBits())) {
|
if (!mFrame->HasOverflowRect()) {
|
||||||
// Provide overflow area for child that doesn't have any
|
// Provide overflow area for child that doesn't have any
|
||||||
mMetrics.mOverflowArea.x = 0;
|
mMetrics.mOverflowArea.x = 0;
|
||||||
mMetrics.mOverflowArea.y = 0;
|
mMetrics.mOverflowArea.y = 0;
|
||||||
|
|||||||
@@ -564,8 +564,8 @@ nsContainerFrame::SyncFrameViewAfterReflow(nsPresContext* aPresContext,
|
|||||||
vm->ResizeView(aView, *aCombinedArea, PR_TRUE);
|
vm->ResizeView(aView, *aCombinedArea, PR_TRUE);
|
||||||
|
|
||||||
// Even if the size hasn't changed, we need to sync up the
|
// Even if the size hasn't changed, we need to sync up the
|
||||||
// geometry dependent properties, because (kidState &
|
// geometry dependent properties, because overflow areas of
|
||||||
// NS_FRAME_OUTSIDE_CHILDREN) might have changed, and we can't
|
// children might have changed, and we can't
|
||||||
// detect whether it has or not. Likewise, whether the view size
|
// detect whether it has or not. Likewise, whether the view size
|
||||||
// has changed or not, we may need to change the transparency
|
// has changed or not, we may need to change the transparency
|
||||||
// state even if there is no clip.
|
// state even if there is no clip.
|
||||||
@@ -1608,7 +1608,7 @@ nsContainerFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
}
|
}
|
||||||
fprintf(out, " [content=%p]", static_cast<void*>(mContent));
|
fprintf(out, " [content=%p]", static_cast<void*>(mContent));
|
||||||
nsContainerFrame* f = const_cast<nsContainerFrame*>(this);
|
nsContainerFrame* f = const_cast<nsContainerFrame*>(this);
|
||||||
if (f->GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
|
if (f->HasOverflowRect()) {
|
||||||
nsRect overflowArea = f->GetOverflowRect();
|
nsRect overflowArea = f->GetOverflowRect();
|
||||||
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
|
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
|
||||||
overflowArea.width, overflowArea.height);
|
overflowArea.width, overflowArea.height);
|
||||||
|
|||||||
@@ -3975,11 +3975,22 @@ nsIFrame::GetOverflowRect() const
|
|||||||
// areas will invalidate the appropriate area, so any (mis)uses of
|
// areas will invalidate the appropriate area, so any (mis)uses of
|
||||||
// this method will be fixed up.
|
// this method will be fixed up.
|
||||||
|
|
||||||
if (GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN)
|
if (mOverflow.mType == NS_FRAME_OVERFLOW_LARGE) {
|
||||||
|
// there is an overflow rect, and it's not stored as deltas but as
|
||||||
|
// a separately-allocated rect
|
||||||
return *const_cast<nsIFrame*>(this)->GetOverflowAreaProperty(PR_FALSE);
|
return *const_cast<nsIFrame*>(this)->GetOverflowAreaProperty(PR_FALSE);
|
||||||
// NOTE this won't return accurate info if the overflow rect was updated
|
}
|
||||||
// but the mRect hasn't been set yet!
|
|
||||||
return nsRect(nsPoint(0, 0), GetSize());
|
// Calculate the rect using deltas from the frame's border rect.
|
||||||
|
// Note that the mOverflow.mDeltas fields are unsigned, but we will often
|
||||||
|
// need to return negative values for the left and top, so take care
|
||||||
|
// to cast away the unsigned-ness.
|
||||||
|
return nsRect(-(PRInt32)mOverflow.mDeltas.mLeft,
|
||||||
|
-(PRInt32)mOverflow.mDeltas.mTop,
|
||||||
|
mRect.width + mOverflow.mDeltas.mRight +
|
||||||
|
mOverflow.mDeltas.mLeft,
|
||||||
|
mRect.height + mOverflow.mDeltas.mBottom +
|
||||||
|
mOverflow.mDeltas.mTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRect
|
nsRect
|
||||||
@@ -4068,7 +4079,7 @@ nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
|
|||||||
{
|
{
|
||||||
if (aReflowState.mReflowDepth > MAX_FRAME_DEPTH) {
|
if (aReflowState.mReflowDepth > MAX_FRAME_DEPTH) {
|
||||||
mState |= NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
|
mState |= NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
ClearOverflowRect();
|
||||||
aMetrics.width = 0;
|
aMetrics.width = 0;
|
||||||
aMetrics.height = 0;
|
aMetrics.height = 0;
|
||||||
aMetrics.ascent = 0;
|
aMetrics.ascent = 0;
|
||||||
@@ -4148,7 +4159,7 @@ nsFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
}
|
}
|
||||||
fprintf(out, " [content=%p]", static_cast<void*>(mContent));
|
fprintf(out, " [content=%p]", static_cast<void*>(mContent));
|
||||||
nsFrame* f = const_cast<nsFrame*>(this);
|
nsFrame* f = const_cast<nsFrame*>(this);
|
||||||
if (f->GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
|
if (f->HasOverflowRect()) {
|
||||||
nsRect overflowArea = f->GetOverflowRect();
|
nsRect overflowArea = f->GetOverflowRect();
|
||||||
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
|
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
|
||||||
overflowArea.width, overflowArea.height);
|
overflowArea.width, overflowArea.height);
|
||||||
@@ -5569,7 +5580,8 @@ nsFrame::GetAccessible(nsIAccessible** aAccessible)
|
|||||||
nsRect*
|
nsRect*
|
||||||
nsIFrame::GetOverflowAreaProperty(PRBool aCreateIfNecessary)
|
nsIFrame::GetOverflowAreaProperty(PRBool aCreateIfNecessary)
|
||||||
{
|
{
|
||||||
if (!((GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) || aCreateIfNecessary)) {
|
if (!((mOverflow.mType == NS_FRAME_OVERFLOW_LARGE) ||
|
||||||
|
aCreateIfNecessary)) {
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5588,10 +5600,44 @@ nsIFrame::GetOverflowAreaProperty(PRBool aCreateIfNecessary)
|
|||||||
return overflow;
|
return overflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_NOTREACHED("Frame abuses NS_FRAME_OUTSIDE_CHILDREN flag");
|
NS_NOTREACHED("Frame abuses GetOverflowAreaProperty()");
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set the overflowArea rect, storing it as deltas or a separate rect
|
||||||
|
* depending on its size in relation to the primary frame rect.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
nsIFrame::SetOverflowRect(const nsRect& aRect)
|
||||||
|
{
|
||||||
|
PRUint32 l = -aRect.x, // left edge: positive delta is leftwards
|
||||||
|
t = -aRect.y, // top: positive is upwards
|
||||||
|
r = aRect.XMost() - mRect.width, // right: positive is rightwards
|
||||||
|
b = aRect.YMost() - mRect.height; // bottom: positive is downwards
|
||||||
|
if (l <= NS_FRAME_OVERFLOW_DELTA_MAX &&
|
||||||
|
t <= NS_FRAME_OVERFLOW_DELTA_MAX &&
|
||||||
|
r <= NS_FRAME_OVERFLOW_DELTA_MAX &&
|
||||||
|
b <= NS_FRAME_OVERFLOW_DELTA_MAX &&
|
||||||
|
(l | t | r | b) != 0) {
|
||||||
|
// It's a "small" overflow area so we store the deltas for each edge
|
||||||
|
// directly in the frame, rather than allocating a separate rect.
|
||||||
|
// Note that we do NOT store in this way if *all* the deltas are zero,
|
||||||
|
// as that would be indistinguishable from the complete absence of
|
||||||
|
// an overflow rect.
|
||||||
|
DeleteProperty(nsGkAtoms::overflowAreaProperty);
|
||||||
|
mOverflow.mDeltas.mLeft = l;
|
||||||
|
mOverflow.mDeltas.mTop = t;
|
||||||
|
mOverflow.mDeltas.mRight = r;
|
||||||
|
mOverflow.mDeltas.mBottom = b;
|
||||||
|
} else {
|
||||||
|
// it's a large overflow area that we need to store as a property
|
||||||
|
mOverflow.mType = NS_FRAME_OVERFLOW_LARGE;
|
||||||
|
nsRect* overflowArea = GetOverflowAreaProperty(PR_TRUE);
|
||||||
|
NS_ASSERTION(overflowArea, "should have created rect");
|
||||||
|
*overflowArea = aRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline PRBool
|
inline PRBool
|
||||||
IsInlineFrame(nsIFrame *aFrame)
|
IsInlineFrame(nsIFrame *aFrame)
|
||||||
{
|
{
|
||||||
@@ -5682,18 +5728,14 @@ nsIFrame::FinishAndStoreOverflow(nsRect* aOverflowArea, nsSize aNewSize)
|
|||||||
|
|
||||||
PRBool overflowChanged;
|
PRBool overflowChanged;
|
||||||
if (*aOverflowArea != nsRect(nsPoint(0, 0), aNewSize)) {
|
if (*aOverflowArea != nsRect(nsPoint(0, 0), aNewSize)) {
|
||||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
overflowChanged = *aOverflowArea != GetOverflowRect();
|
||||||
nsRect* overflowArea = GetOverflowAreaProperty(PR_TRUE);
|
SetOverflowRect(*aOverflowArea);
|
||||||
NS_ASSERTION(overflowArea, "should have created rect");
|
|
||||||
overflowChanged = *overflowArea != *aOverflowArea;
|
|
||||||
*overflowArea = *aOverflowArea;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (mState & NS_FRAME_OUTSIDE_CHILDREN) {
|
if (HasOverflowRect()) {
|
||||||
// remove the previously stored overflow area
|
// remove the previously stored overflow area
|
||||||
DeleteProperty(nsGkAtoms::overflowAreaProperty);
|
ClearOverflowRect();
|
||||||
overflowChanged = PR_TRUE;
|
overflowChanged = PR_TRUE;
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
} else {
|
} else {
|
||||||
overflowChanged = PR_FALSE;
|
overflowChanged = PR_FALSE;
|
||||||
}
|
}
|
||||||
@@ -6624,7 +6666,7 @@ nsFrame::BoxReflow(nsBoxLayoutState& aState,
|
|||||||
|
|
||||||
// see if the overflow option is set. If it is then if our child's bounds overflow then
|
// see if the overflow option is set. If it is then if our child's bounds overflow then
|
||||||
// we will set the child's rect to include the overflow size.
|
// we will set the child's rect to include the overflow size.
|
||||||
if (GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
|
if (HasOverflowRect()) {
|
||||||
// This kinda sucks. We should be able to handle the case
|
// This kinda sucks. We should be able to handle the case
|
||||||
// where there's overflow above or to the left of the
|
// where there's overflow above or to the left of the
|
||||||
// origin. But for now just chop that stuff off.
|
// origin. But for now just chop that stuff off.
|
||||||
@@ -6661,7 +6703,7 @@ nsFrame::BoxReflow(nsBoxLayoutState& aState,
|
|||||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||||
WillReflow(aPresContext);
|
WillReflow(aPresContext);
|
||||||
Reflow(aPresContext, aDesiredSize, reflowState, status);
|
Reflow(aPresContext, aDesiredSize, reflowState, status);
|
||||||
if (GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN)
|
if (HasOverflowRect())
|
||||||
aDesiredSize.height = aDesiredSize.mOverflowArea.YMost();
|
aDesiredSize.height = aDesiredSize.mOverflowArea.YMost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7694,13 +7736,13 @@ void nsFrame::DisplayReflowExit(nsPresContext* aPresContext,
|
|||||||
if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
|
if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
|
||||||
printf(" status=0x%x", aStatus);
|
printf(" status=0x%x", aStatus);
|
||||||
}
|
}
|
||||||
if (aFrame->GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
|
if (aFrame->HasOverflowRect()) {
|
||||||
DR_state->PrettyUC(aMetrics.mOverflowArea.x, x);
|
DR_state->PrettyUC(aMetrics.mOverflowArea.x, x);
|
||||||
DR_state->PrettyUC(aMetrics.mOverflowArea.y, y);
|
DR_state->PrettyUC(aMetrics.mOverflowArea.y, y);
|
||||||
DR_state->PrettyUC(aMetrics.mOverflowArea.width, width);
|
DR_state->PrettyUC(aMetrics.mOverflowArea.width, width);
|
||||||
DR_state->PrettyUC(aMetrics.mOverflowArea.height, height);
|
DR_state->PrettyUC(aMetrics.mOverflowArea.height, height);
|
||||||
printf(" o=(%s,%s) %s x %s", x, y, width, height);
|
printf(" o=(%s,%s) %s x %s", x, y, width, height);
|
||||||
if (aFrame->GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
|
if (aFrame->HasOverflowRect()) {
|
||||||
nsRect storedOverflow = aFrame->GetOverflowRect();
|
nsRect storedOverflow = aFrame->GetOverflowRect();
|
||||||
DR_state->PrettyUC(storedOverflow.x, x);
|
DR_state->PrettyUC(storedOverflow.x, x);
|
||||||
DR_state->PrettyUC(storedOverflow.y, y);
|
DR_state->PrettyUC(storedOverflow.y, y);
|
||||||
|
|||||||
@@ -540,7 +540,7 @@ nsHTMLScrollFrame::ReflowScrolledFrame(ScrollReflowState* aState,
|
|||||||
// always set mOverflowArea. In fact nsObjectFrame and nsFrameFrame don't
|
// always set mOverflowArea. In fact nsObjectFrame and nsFrameFrame don't
|
||||||
// support the 'outline' property because of this. Rather than fix the world
|
// support the 'outline' property because of this. Rather than fix the world
|
||||||
// right now, just fix up the overflow area if necessary. Note that we don't
|
// right now, just fix up the overflow area if necessary. Note that we don't
|
||||||
// check NS_FRAME_OUTSIDE_CHILDREN because it could be set even though the
|
// check HasOverflowRect() because it could be set even though the
|
||||||
// overflow area doesn't include the frame bounds.
|
// overflow area doesn't include the frame bounds.
|
||||||
aMetrics->mOverflowArea.UnionRect(aMetrics->mOverflowArea,
|
aMetrics->mOverflowArea.UnionRect(aMetrics->mOverflowArea,
|
||||||
nsRect(0, 0, aMetrics->width, aMetrics->height));
|
nsRect(0, 0, aMetrics->width, aMetrics->height));
|
||||||
@@ -712,12 +712,12 @@ nsHTMLScrollFrame::PlaceScrollArea(const ScrollReflowState& aState)
|
|||||||
// Store the new overflow area. Note that this changes where an outline
|
// Store the new overflow area. Note that this changes where an outline
|
||||||
// of the scrolled frame would be painted, but scrolled frames can't have
|
// of the scrolled frame would be painted, but scrolled frames can't have
|
||||||
// outlines (the outline would go on this scrollframe instead).
|
// outlines (the outline would go on this scrollframe instead).
|
||||||
// Using FinishAndStoreOverflow is needed so NS_FRAME_OUTSIDE_CHILDREN
|
// Using FinishAndStoreOverflow is needed so the overflow rect
|
||||||
// gets set correctly. It also messes with the overflow rect in the
|
// gets set correctly. It also messes with the overflow rect in the
|
||||||
// -moz-hidden-unscrollable case, but scrolled frames can't have
|
// -moz-hidden-unscrollable case, but scrolled frames can't have
|
||||||
// 'overflow' either.
|
// 'overflow' either.
|
||||||
// This needs to happen before SyncFrameViewAfterReflow so
|
// This needs to happen before SyncFrameViewAfterReflow so
|
||||||
// NS_FRAME_OUTSIDE_CHILDREN is set.
|
// HasOverflowRect() will return the correct value.
|
||||||
scrolledFrame->FinishAndStoreOverflow(&scrolledArea,
|
scrolledFrame->FinishAndStoreOverflow(&scrolledArea,
|
||||||
scrolledFrame->GetSize());
|
scrolledFrame->GetSize());
|
||||||
|
|
||||||
@@ -2083,9 +2083,7 @@ nsXULScrollFrame::LayoutScrollArea(nsBoxLayoutState& aState, const nsRect& aRect
|
|||||||
// remove overflow area when we update the bounds,
|
// remove overflow area when we update the bounds,
|
||||||
// because we've already accounted for it
|
// because we've already accounted for it
|
||||||
mInner.mScrolledFrame->SetBounds(aState, childRect);
|
mInner.mScrolledFrame->SetBounds(aState, childRect);
|
||||||
PresContext()->PropertyTable()->
|
mInner.mScrolledFrame->ClearOverflowRect();
|
||||||
DeleteProperty(mInner.mScrolledFrame, nsGkAtoms::overflowAreaProperty);
|
|
||||||
mInner.mScrolledFrame->RemoveStateBits(NS_FRAME_OUTSIDE_CHILDREN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aState.SetLayoutFlags(oldflags);
|
aState.SetLayoutFlags(oldflags);
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ struct nsHTMLReflowMetrics {
|
|||||||
nsCollapsingMargin mCarriedOutBottomMargin;
|
nsCollapsingMargin mCarriedOutBottomMargin;
|
||||||
|
|
||||||
// For frames that have content that overflow their content area
|
// For frames that have content that overflow their content area
|
||||||
// (NS_FRAME_OUTSIDE_CHILDREN) this rectangle represents the total area
|
// (HasOverflowRect() is true) this rectangle represents the total area
|
||||||
// of the frame including visible overflow, i.e., don't include overflowing
|
// of the frame including visible overflow, i.e., don't include overflowing
|
||||||
// content that is hidden.
|
// content that is hidden.
|
||||||
// The rect is in the local coordinate space of the frame, and should be at
|
// The rect is in the local coordinate space of the frame, and should be at
|
||||||
|
|||||||
@@ -162,9 +162,14 @@ enum {
|
|||||||
// continuation, e.g. a bidi continuation.
|
// continuation, e.g. a bidi continuation.
|
||||||
NS_FRAME_IS_FLUID_CONTINUATION = 0x00000004,
|
NS_FRAME_IS_FLUID_CONTINUATION = 0x00000004,
|
||||||
|
|
||||||
// This bit is set when the frame's overflow rect is
|
/*
|
||||||
// different from its border rect (i.e. GetOverflowRect() != GetRect())
|
* This bit is obsolete, replaced by HasOverflowRect().
|
||||||
NS_FRAME_OUTSIDE_CHILDREN = 0x00000008,
|
* The definition is left here as a placeholder for now, to remind us
|
||||||
|
* that this bit is now free to allocate for other purposes.
|
||||||
|
* // This bit is set when the frame's overflow rect is
|
||||||
|
* // different from its border rect (i.e. GetOverflowRect() != GetRect())
|
||||||
|
* NS_FRAME_OUTSIDE_CHILDREN = 0x00000008,
|
||||||
|
*/
|
||||||
|
|
||||||
// If this bit is set, then a reference to the frame is being held
|
// If this bit is set, then a reference to the frame is being held
|
||||||
// elsewhere. The frame may want to send a notification when it is
|
// elsewhere. The frame may want to send a notification when it is
|
||||||
@@ -441,6 +446,24 @@ typedef PRBool nsDidReflowStatus;
|
|||||||
#define NS_FRAME_REFLOW_NOT_FINISHED PR_FALSE
|
#define NS_FRAME_REFLOW_NOT_FINISHED PR_FALSE
|
||||||
#define NS_FRAME_REFLOW_FINISHED PR_TRUE
|
#define NS_FRAME_REFLOW_FINISHED PR_TRUE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The overflow rect may be stored as four 1-byte deltas each strictly
|
||||||
|
* LESS THAN 0xff, for the four edges of the rectangle, or the four bytes
|
||||||
|
* may be read as a single 32-bit "overflow-rect type" value including
|
||||||
|
* at least one 0xff byte as an indicator that the value does NOT
|
||||||
|
* represent four deltas.
|
||||||
|
* If all four deltas are zero, this means that no overflow rect has
|
||||||
|
* actually been set (this is the initial state of newly-created frames).
|
||||||
|
*/
|
||||||
|
#define NS_FRAME_OVERFLOW_DELTA_MAX 0xfe // max delta we can store
|
||||||
|
|
||||||
|
#define NS_FRAME_OVERFLOW_NONE 0x00000000 // there is no overflow rect;
|
||||||
|
// code relies on this being
|
||||||
|
// the all-zero value
|
||||||
|
|
||||||
|
#define NS_FRAME_OVERFLOW_LARGE 0x000000ff // overflow is stored as a
|
||||||
|
// separate rect property
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -710,9 +733,32 @@ public:
|
|||||||
nsRect GetRect() const { return mRect; }
|
nsRect GetRect() const { return mRect; }
|
||||||
nsPoint GetPosition() const { return nsPoint(mRect.x, mRect.y); }
|
nsPoint GetPosition() const { return nsPoint(mRect.x, mRect.y); }
|
||||||
nsSize GetSize() const { return nsSize(mRect.width, mRect.height); }
|
nsSize GetSize() const { return nsSize(mRect.width, mRect.height); }
|
||||||
void SetRect(const nsRect& aRect) { mRect = aRect; }
|
|
||||||
|
/**
|
||||||
|
* When we change the size of the frame's border-box rect, we may need to
|
||||||
|
* reset the overflow rect if it was previously stored as deltas.
|
||||||
|
* (If it is currently a "large" overflow and could be re-packed as deltas,
|
||||||
|
* we don't bother as the cost of the allocation has already been paid.)
|
||||||
|
*/
|
||||||
|
void SetRect(const nsRect& aRect) {
|
||||||
|
if (HasOverflowRect() && mOverflow.mType != NS_FRAME_OVERFLOW_LARGE) {
|
||||||
|
nsRect r = GetOverflowRect();
|
||||||
|
mRect = aRect;
|
||||||
|
SetOverflowRect(r);
|
||||||
|
} else {
|
||||||
|
mRect = aRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SetSize(const nsSize& aSize) {
|
||||||
|
if (HasOverflowRect() && mOverflow.mType != NS_FRAME_OVERFLOW_LARGE) {
|
||||||
|
nsRect r = GetOverflowRect();
|
||||||
|
mRect.SizeTo(aSize);
|
||||||
|
SetOverflowRect(r);
|
||||||
|
} else {
|
||||||
|
mRect.SizeTo(aSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); }
|
void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); }
|
||||||
void SetSize(const nsSize& aSize) { mRect.SizeTo(aSize); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return frame's computed offset due to relative positioning
|
* Return frame's computed offset due to relative positioning
|
||||||
@@ -1756,8 +1802,8 @@ public:
|
|||||||
* frame's outline, and descentant frames' outline, but does not include
|
* frame's outline, and descentant frames' outline, but does not include
|
||||||
* areas clipped out by the CSS "overflow" and "clip" properties.
|
* areas clipped out by the CSS "overflow" and "clip" properties.
|
||||||
*
|
*
|
||||||
* The NS_FRAME_OUTSIDE_CHILDREN state bit is set when this overflow rect
|
* HasOverflowRect() (below) will return PR_TRUE when this overflow rect
|
||||||
* is different from nsRect(0, 0, GetRect().width, GetRect().height).
|
* has been explicitly set, even if it matches mRect.
|
||||||
* XXX Note: because of a space optimization using the formula above,
|
* XXX Note: because of a space optimization using the formula above,
|
||||||
* during reflow this function does not give accurate data if
|
* during reflow this function does not give accurate data if
|
||||||
* FinishAndStoreOverflow has been called but mRect hasn't yet been
|
* FinishAndStoreOverflow has been called but mRect hasn't yet been
|
||||||
@@ -1776,7 +1822,7 @@ public:
|
|||||||
* frame's outline, and descentant frames' outline, but does not include
|
* frame's outline, and descentant frames' outline, but does not include
|
||||||
* areas clipped out by the CSS "overflow" and "clip" properties.
|
* areas clipped out by the CSS "overflow" and "clip" properties.
|
||||||
*
|
*
|
||||||
* The NS_FRAME_OUTSIDE_CHILDREN state bit is set when this overflow rect
|
* HasOverflowRect() (below) will return PR_TRUE when this overflow rect
|
||||||
* is different from nsRect(0, 0, GetRect().width, GetRect().height).
|
* is different from nsRect(0, 0, GetRect().width, GetRect().height).
|
||||||
* XXX Note: because of a space optimization using the formula above,
|
* XXX Note: because of a space optimization using the formula above,
|
||||||
* during reflow this function does not give accurate data if
|
* during reflow this function does not give accurate data if
|
||||||
@@ -1800,7 +1846,7 @@ public:
|
|||||||
nsRect GetOverflowRectRelativeToSelf() const;
|
nsRect GetOverflowRectRelativeToSelf() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set/unset the NS_FRAME_OUTSIDE_CHILDREN flag and store the overflow area
|
* Store the overflow area in the frame's mOverflow.mDeltas fields or
|
||||||
* as a frame property in the frame manager so that it can be retrieved
|
* as a frame property in the frame manager so that it can be retrieved
|
||||||
* later without reflowing the frame.
|
* later without reflowing the frame.
|
||||||
*/
|
*/
|
||||||
@@ -1810,6 +1856,22 @@ public:
|
|||||||
FinishAndStoreOverflow(&aMetrics->mOverflowArea, nsSize(aMetrics->width, aMetrics->height));
|
FinishAndStoreOverflow(&aMetrics->mOverflowArea, nsSize(aMetrics->width, aMetrics->height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the frame has an overflow rect that is different from
|
||||||
|
* its border-box.
|
||||||
|
*/
|
||||||
|
PRBool HasOverflowRect() const {
|
||||||
|
return mOverflow.mType != NS_FRAME_OVERFLOW_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes any stored overflow rect from the frame.
|
||||||
|
*/
|
||||||
|
void ClearOverflowRect() {
|
||||||
|
DeleteProperty(nsGkAtoms::overflowAreaProperty);
|
||||||
|
mOverflow.mType = NS_FRAME_OVERFLOW_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether borders should not be painted on certain sides of the
|
* Determine whether borders should not be painted on certain sides of the
|
||||||
* frame.
|
* frame.
|
||||||
@@ -2256,6 +2318,25 @@ protected:
|
|||||||
nsIFrame* mNextSibling; // singly-linked list of frames
|
nsIFrame* mNextSibling; // singly-linked list of frames
|
||||||
nsFrameState mState;
|
nsFrameState mState;
|
||||||
|
|
||||||
|
// When there is an overflow area only slightly larger than mRect,
|
||||||
|
// we store a set of four 1-byte deltas from the edges of mRect
|
||||||
|
// rather than allocating a whole separate rectangle property.
|
||||||
|
// Note that these are unsigned values, all measured "outwards"
|
||||||
|
// from the edges of mRect, so /mLeft/ and /mTop/ are reversed from
|
||||||
|
// our normal coordinate system.
|
||||||
|
// If mOverflow.mType == NS_FRAME_OVERFLOW_LARGE, then the
|
||||||
|
// delta values are not meaningful and the overflow area is stored
|
||||||
|
// as a separate rect property.
|
||||||
|
union {
|
||||||
|
PRUint32 mType;
|
||||||
|
struct {
|
||||||
|
PRUint8 mLeft;
|
||||||
|
PRUint8 mTop;
|
||||||
|
PRUint8 mRight;
|
||||||
|
PRUint8 mBottom;
|
||||||
|
} mDeltas;
|
||||||
|
} mOverflow;
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
/**
|
/**
|
||||||
* For frames that have top-level windows (top-level viewports,
|
* For frames that have top-level windows (top-level viewports,
|
||||||
@@ -2357,6 +2438,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
nsRect* GetOverflowAreaProperty(PRBool aCreateIfNecessary = PR_FALSE);
|
nsRect* GetOverflowAreaProperty(PRBool aCreateIfNecessary = PR_FALSE);
|
||||||
|
void SetOverflowRect(const nsRect& aRect);
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|||||||
@@ -384,7 +384,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
rv = ReflowFrames(aPresContext, aReflowState, irs, aMetrics, aStatus);
|
rv = ReflowFrames(aPresContext, aReflowState, irs, aMetrics, aStatus);
|
||||||
|
|
||||||
// Note: the line layout code will properly compute our
|
// Note: the line layout code will properly compute our
|
||||||
// NS_FRAME_OUTSIDE_CHILDREN state for us.
|
// overflow-rect state for us.
|
||||||
|
|
||||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
||||||
return rv;
|
return rv;
|
||||||
|
|||||||
@@ -2635,8 +2635,8 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea)
|
|||||||
nsContainerFrame::PositionChildViews(frame);
|
nsContainerFrame::PositionChildViews(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do this here (rather than along with NS_FRAME_OUTSIDE_CHILDREN
|
// Do this here (rather than along with setting the overflow rect
|
||||||
// handling below) so we get leaf frames as well. No need to worry
|
// below) so we get leaf frames as well. No need to worry
|
||||||
// about the root span, since it doesn't have a frame.
|
// about the root span, since it doesn't have a frame.
|
||||||
if (frame->HasView())
|
if (frame->HasView())
|
||||||
nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, frame,
|
nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, frame,
|
||||||
@@ -2647,7 +2647,7 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we just computed a spans combined area, we need to update its
|
// If we just computed a spans combined area, we need to update its
|
||||||
// NS_FRAME_OUTSIDE_CHILDREN bit..
|
// overflow rect...
|
||||||
if (psd->mFrame) {
|
if (psd->mFrame) {
|
||||||
PerFrameData* spanPFD = psd->mFrame;
|
PerFrameData* spanPFD = psd->mFrame;
|
||||||
nsIFrame* frame = spanPFD->mFrame;
|
nsIFrame* frame = spanPFD->mFrame;
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Handle all the relative positioning in the line, compute the
|
* Handle all the relative positioning in the line, compute the
|
||||||
* combined area (== overflow area) for the line, and handle view
|
* combined area (== overflow area) for the line, and handle view
|
||||||
* sizing/positioning and the setting of NS_FRAME_OUTSIDE_CHILDREN.
|
* sizing/positioning and the setting of the overflow rect.
|
||||||
*/
|
*/
|
||||||
void RelativePositionFrames(nsRect& aCombinedArea);
|
void RelativePositionFrames(nsRect& aCombinedArea);
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ nsPageContentFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
kidReflowState.mStylePadding->GetPadding(padding);
|
kidReflowState.mStylePadding->GetPadding(padding);
|
||||||
|
|
||||||
// First check the combined area
|
// First check the combined area
|
||||||
if (NS_FRAME_OUTSIDE_CHILDREN & frame->GetStateBits()) {
|
if (frame->HasOverflowRect()) {
|
||||||
// The background covers the content area and padding area, so check
|
// The background covers the content area and padding area, so check
|
||||||
// for children sticking outside the child frame's padding edge
|
// for children sticking outside the child frame's padding edge
|
||||||
if (aDesiredSize.mOverflowArea.XMost() > aDesiredSize.width) {
|
if (aDesiredSize.mOverflowArea.XMost() > aDesiredSize.width) {
|
||||||
|
|||||||
@@ -6625,7 +6625,7 @@ nsTextFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(out, " [content=%p]", static_cast<void*>(mContent));
|
fprintf(out, " [content=%p]", static_cast<void*>(mContent));
|
||||||
if (GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
|
if (HasOverflowRect()) {
|
||||||
nsRect overflowArea = GetOverflowRect();
|
nsRect overflowArea = GetOverflowRect();
|
||||||
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
|
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
|
||||||
overflowArea.width, overflowArea.height);
|
overflowArea.width, overflowArea.height);
|
||||||
|
|||||||
@@ -6423,6 +6423,8 @@ nsTableFrame::PaintBCBorders(nsIRenderingContext& aRenderingContext,
|
|||||||
rowY += rowSize.height;
|
rowY += rowSize.height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// XXX comment refers to the obsolete NS_FRAME_OUTSIDE_CHILDREN flag
|
||||||
|
// XXX but I don't understand it, so not changing it for now
|
||||||
// outer table borders overflow the table, so the table might be
|
// outer table borders overflow the table, so the table might be
|
||||||
// target to other areas as the NS_FRAME_OUTSIDE_CHILDREN is set
|
// target to other areas as the NS_FRAME_OUTSIDE_CHILDREN is set
|
||||||
// on the table
|
// on the table
|
||||||
|
|||||||
@@ -923,7 +923,7 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
desiredSize.width = cellDesiredSize.width;
|
desiredSize.width = cellDesiredSize.width;
|
||||||
desiredSize.height = cellDesiredSize.height;
|
desiredSize.height = cellDesiredSize.height;
|
||||||
if (cellFrame->GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN)
|
if (cellFrame->HasOverflowRect())
|
||||||
desiredSize.mOverflowArea = cellFrame->GetOverflowRect();
|
desiredSize.mOverflowArea = cellFrame->GetOverflowRect();
|
||||||
else
|
else
|
||||||
desiredSize.mOverflowArea.SetRect(0, 0, cellDesiredSize.width,
|
desiredSize.mOverflowArea.SetRect(0, 0, cellDesiredSize.width,
|
||||||
|
|||||||
@@ -280,11 +280,9 @@ nsBox::SetBounds(nsBoxLayoutState& aState, const nsRect& aRect, PRBool aRemoveOv
|
|||||||
|
|
||||||
// Nuke the overflow area. The caller is responsible for restoring
|
// Nuke the overflow area. The caller is responsible for restoring
|
||||||
// it if necessary.
|
// it if necessary.
|
||||||
if (aRemoveOverflowArea && (GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN)) {
|
if (aRemoveOverflowArea && HasOverflowRect()) {
|
||||||
// remove the previously stored overflow area
|
// remove the previously stored overflow area
|
||||||
PresContext()->PropertyTable()->
|
ClearOverflowRect();
|
||||||
DeleteProperty(this, nsGkAtoms::overflowAreaProperty);
|
|
||||||
RemoveStateBits(NS_FRAME_OUTSIDE_CHILDREN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(flags & NS_FRAME_NO_MOVE_VIEW))
|
if (!(flags & NS_FRAME_NO_MOVE_VIEW))
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ nsLeafBoxFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
aDesiredSize.height = mRect.height;
|
aDesiredSize.height = mRect.height;
|
||||||
aDesiredSize.ascent = GetBoxAscent(state);
|
aDesiredSize.ascent = GetBoxAscent(state);
|
||||||
|
|
||||||
// NS_FRAME_OUTSIDE_CHILDREN is set in SetBounds() above
|
// the overflow rect is set in SetBounds() above
|
||||||
aDesiredSize.mOverflowArea = GetOverflowRect();
|
aDesiredSize.mOverflowArea = GetOverflowRect();
|
||||||
|
|
||||||
#ifdef DO_NOISY_REFLOW
|
#ifdef DO_NOISY_REFLOW
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ nsPopupSetFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
}
|
}
|
||||||
fprintf(out, " [content=%p]", static_cast<void*>(mContent));
|
fprintf(out, " [content=%p]", static_cast<void*>(mContent));
|
||||||
nsPopupSetFrame* f = const_cast<nsPopupSetFrame*>(this);
|
nsPopupSetFrame* f = const_cast<nsPopupSetFrame*>(this);
|
||||||
if (f->GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
|
if (f->HasOverflowRect()) {
|
||||||
nsRect overflowArea = f->GetOverflowRect();
|
nsRect overflowArea = f->GetOverflowRect();
|
||||||
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
|
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
|
||||||
overflowArea.width, overflowArea.height);
|
overflowArea.width, overflowArea.height);
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Treat scrollbars as clipping their children; overflowing children
|
* Treat scrollbars as clipping their children; overflowing children
|
||||||
* will not be allowed to make NS_FRAME_OUTSIDE_CHILDREN on this
|
* will not be allowed to set an overflow rect on this
|
||||||
* frame. This means that when the scroll code decides to hide a
|
* frame. This means that when the scroll code decides to hide a
|
||||||
* scrollframe by setting its height or width to zero, that will
|
* scrollframe by setting its height or width to zero, that will
|
||||||
* hide the children too.
|
* hide the children too.
|
||||||
|
|||||||
Reference in New Issue
Block a user