diff --git a/content/shared/public/nsLayoutAtomList.h b/content/shared/public/nsLayoutAtomList.h index 110cfc6213eb..6bf11de1b027 100644 --- a/content/shared/public/nsLayoutAtomList.h +++ b/content/shared/public/nsLayoutAtomList.h @@ -104,12 +104,13 @@ LAYOUT_ATOM(textFrame, "TextFrame") LAYOUT_ATOM(viewportFrame, "ViewportFrame") // Alphabetical list of frame property names -LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") -LAYOUT_ATOM(inlineFrameAnnotation, "InlineFrameAnnotation") -LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") -LAYOUT_ATOM(overflowProperty, "OverflowProperty") -LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") -LAYOUT_ATOM(viewProperty, "ViewProperty") +LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint* +LAYOUT_ATOM(inlineFrameAnnotation, "InlineFrameAnnotation") // BOOL +LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") // nsSize* +LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect* +LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame* +LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox* +LAYOUT_ATOM(viewProperty, "ViewProperty") // nsView* // Alphabetical list of event handler names LAYOUT_ATOM(onabort, "onabort") diff --git a/layout/base/nsLayoutAtomList.h b/layout/base/nsLayoutAtomList.h index 110cfc6213eb..6bf11de1b027 100644 --- a/layout/base/nsLayoutAtomList.h +++ b/layout/base/nsLayoutAtomList.h @@ -104,12 +104,13 @@ LAYOUT_ATOM(textFrame, "TextFrame") LAYOUT_ATOM(viewportFrame, "ViewportFrame") // Alphabetical list of frame property names -LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") -LAYOUT_ATOM(inlineFrameAnnotation, "InlineFrameAnnotation") -LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") -LAYOUT_ATOM(overflowProperty, "OverflowProperty") -LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") -LAYOUT_ATOM(viewProperty, "ViewProperty") +LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint* +LAYOUT_ATOM(inlineFrameAnnotation, "InlineFrameAnnotation") // BOOL +LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") // nsSize* +LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect* +LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame* +LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox* +LAYOUT_ATOM(viewProperty, "ViewProperty") // nsView* // Alphabetical list of event handler names LAYOUT_ATOM(onabort, "onabort") diff --git a/layout/base/public/nsIFrame.h b/layout/base/public/nsIFrame.h index c9e2e45050a7..a1108370970b 100644 --- a/layout/base/public/nsIFrame.h +++ b/layout/base/public/nsIFrame.h @@ -217,20 +217,23 @@ struct nsHTMLReflowMetrics { // (generational) bottom margin value. nscoord mCarriedOutBottomMargin; - // For frames that have children that stick outside their rect - // (NS_FRAME_OUTSIDE_CHILDREN) this rectangle will contain the - // absolute bounds of the frame. Since the frame doesn't know where - // it is going to be positioned in its parent, the assumption is - // that it is placed at 0,0 when computing this area. - nsRect mCombinedArea; + // For frames that have content that overflow their content area + // (NS_FRAME_OUTSIDE_CHILDREN) this rectangle represents the total area + // of the frame including visible overflow, i.e., don't include overflowing + // content that is hidden. + // The rect is in the local coordinate space of the frame, and should be at + // least as big as the desired size. If there is no content that overflows, + // then the overflow area is identical to the desired size and should be + // {0, 0, mWidth, mHeight}. + nsRect mOverflowArea; nsHTMLReflowMetrics(nsSize* aMaxElementSize) { maxElementSize = aMaxElementSize; mCarriedOutBottomMargin = 0; - mCombinedArea.x = 0; - mCombinedArea.y = 0; - mCombinedArea.width = 0; - mCombinedArea.height = 0; + mOverflowArea.x = 0; + mOverflowArea.y = 0; + mOverflowArea.width = 0; + mOverflowArea.height = 0; // XXX These are OUT parameters and so they shouldn't have to be // initialized, but there are some bad frame classes that aren't diff --git a/layout/base/public/nsLayoutAtomList.h b/layout/base/public/nsLayoutAtomList.h index 110cfc6213eb..6bf11de1b027 100644 --- a/layout/base/public/nsLayoutAtomList.h +++ b/layout/base/public/nsLayoutAtomList.h @@ -104,12 +104,13 @@ LAYOUT_ATOM(textFrame, "TextFrame") LAYOUT_ATOM(viewportFrame, "ViewportFrame") // Alphabetical list of frame property names -LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") -LAYOUT_ATOM(inlineFrameAnnotation, "InlineFrameAnnotation") -LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") -LAYOUT_ATOM(overflowProperty, "OverflowProperty") -LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") -LAYOUT_ATOM(viewProperty, "ViewProperty") +LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint* +LAYOUT_ATOM(inlineFrameAnnotation, "InlineFrameAnnotation") // BOOL +LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") // nsSize* +LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect* +LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame* +LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox* +LAYOUT_ATOM(viewProperty, "ViewProperty") // nsView* // Alphabetical list of event handler names LAYOUT_ATOM(onabort, "onabort") diff --git a/layout/forms/nsSelectsAreaFrame.cpp b/layout/forms/nsSelectsAreaFrame.cpp index fd4ed94424e4..28c9b6338c6d 100644 --- a/layout/forms/nsSelectsAreaFrame.cpp +++ b/layout/forms/nsSelectsAreaFrame.cpp @@ -23,9 +23,6 @@ #include "nsCOMPtr.h" #include "nsIDOMHTMLOptionElement.h" #include "nsIContent.h" -#include "nsIAreaFrame.h" - -static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); nsresult NS_NewSelectsAreaFrame(nsIPresShell* aShell, nsIFrame** aNewFrame, PRUint32 aFlags) diff --git a/layout/generic/nsAbsoluteContainingBlock.cpp b/layout/generic/nsAbsoluteContainingBlock.cpp index fe0c7f936cb2..29a960f8883e 100644 --- a/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/layout/generic/nsAbsoluteContainingBlock.cpp @@ -19,10 +19,10 @@ * * Contributor(s): */ +#include "nsCOMPtr.h" #include "nsAbsoluteContainingBlock.h" #include "nsContainerFrame.h" #include "nsHTMLIIDs.h" -#include "nsIAreaFrame.h" #include "nsIReflowCommand.h" #include "nsIStyleContext.h" #include "nsIViewManager.h" @@ -30,8 +30,8 @@ #include "nsIReflowCommand.h" #include "nsIPresShell.h" #include "nsHTMLParts.h" - -static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); +#include "nsIPresContext.h" +#include "nsIFrameManager.h" nsresult nsAbsoluteContainingBlock::FirstChild(const nsIFrame* aDelegatingFrame, @@ -127,13 +127,62 @@ nsAbsoluteContainingBlock::RemoveFrame(nsIFrame* aDelegatingFrame, return result ? NS_OK : NS_ERROR_FAILURE; } +// Destructor function for the collapse offset frame property +static void +DestroyRectFunc(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIAtom* aPropertyName, + void* aPropertyValue) +{ + delete (nsRect*)aPropertyValue; +} + +static nsRect* +GetOverflowAreaProperty(nsIPresContext* aPresContext, + nsIFrame* aFrame, + PRBool aCreateIfNecessary = PR_FALSE) +{ + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + + if (presShell) { + nsCOMPtr frameManager; + presShell->GetFrameManager(getter_AddRefs(frameManager)); + + if (frameManager) { + void* value; + + frameManager->GetFrameProperty(aFrame, nsLayoutAtoms::overflowAreaProperty, + 0, &value); + if (value) { + return (nsRect*)value; // the property already exists + + } else if (aCreateIfNecessary) { + // The property isn't set yet, so allocate a new rect, set the property, + // and return the newly allocated rect + nsRect* overflow = new nsRect(0, 0, 0, 0); + + frameManager->SetFrameProperty(aFrame, nsLayoutAtoms::overflowAreaProperty, + overflow, DestroyRectFunc); + return overflow; + } + } + } + + return nsnull; +} + nsresult nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nscoord aContainingBlockWidth, - nscoord aContainingBlockHeight) + nscoord aContainingBlockHeight, + nsRect& aChildBounds) { + // Initialize OUT parameter + aChildBounds.SetRect(0, 0, 0, 0); + // Make a copy of the reflow state. If the reason is eReflowReason_Incremental, // then change it to eReflowReason_Resize nsHTMLReflowState reflowState(aReflowState); @@ -147,20 +196,73 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, nsReflowStatus kidStatus; ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, reflowState, aContainingBlockWidth, aContainingBlockHeight, kidFrame, PR_FALSE, kidStatus); + + // Add in the child's bounds + nsRect kidBounds; + kidFrame->GetRect(kidBounds); + aChildBounds.UnionRect(aChildBounds, kidBounds); + + // If the frame has visible overflow, then take it into account, too. + nsFrameState kidFrameState; + kidFrame->GetFrameState(&kidFrameState); + if (kidFrameState & NS_FRAME_OUTSIDE_CHILDREN) { + // Get the property + nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, kidFrame); + + if (overflowArea) { + // The overflow area is in the child's coordinate space, so translate + // it into the parent's coordinate space + nsRect rect(*overflowArea); + + rect.MoveBy(kidBounds.x, kidBounds.y); + aChildBounds.UnionRect(aChildBounds, rect); + } + } } return NS_OK; } +void +nsAbsoluteContainingBlock::CalculateChildBounds(nsIPresContext* aPresContext, + nsRect& aChildBounds) +{ + for (nsIFrame* f = mAbsoluteFrames.FirstChild(); f; f->GetNextSibling(&f)) { + // Add in the child's bounds + nsRect bounds; + f->GetRect(bounds); + aChildBounds.UnionRect(aChildBounds, bounds); + + // If the frame has visible overflow, then take it into account, too. + nsFrameState frameState; + f->GetFrameState(&frameState); + if (frameState & NS_FRAME_OUTSIDE_CHILDREN) { + // Get the property + nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, f); + + if (overflowArea) { + // The overflow area is in the child's coordinate space, so translate + // it into the parent's coordinate space + nsRect rect(*overflowArea); + + rect.MoveBy(bounds.x, bounds.y); + aChildBounds.UnionRect(aChildBounds, rect); + } + } + } +} + nsresult nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nscoord aContainingBlockWidth, nscoord aContainingBlockHeight, - PRBool& aWasHandled) + PRBool& aWasHandled, + nsRect& aChildBounds) { - // Initialize the OUT paremeter + // Initialize the OUT paremeters aWasHandled = PR_FALSE; + aChildBounds.SetRect(0, 0, 0, 0); // See if the reflow command is targeted at us nsIFrame* targetFrame; @@ -204,6 +306,9 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin // Indicate we handled the reflow command aWasHandled = PR_TRUE; + + // Calculate the total child bounds + CalculateChildBounds(aPresContext, aChildBounds); } } else { @@ -226,6 +331,9 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin // because it has a view if it changes size the view manager will // damage the dirty area aWasHandled = PR_TRUE; + + // Calculate the total child bounds + CalculateChildBounds(aPresContext, aChildBounds); } } @@ -272,7 +380,6 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat kidReflowState.reason = eReflowReason_Initial; } - // XXX TROY // Send the WillReflow() notification and position the frame aKidFrame->WillReflow(aPresContext); aKidFrame->MoveTo(aPresContext, @@ -382,49 +489,22 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat // Size and position the view and set its opacity, visibility, content // transparency, and clip nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame, kidView, - &kidDesiredSize.mCombinedArea); + &kidDesiredSize.mOverflowArea); aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); - return rv; -} -nsresult -nsAbsoluteContainingBlock::GetPositionedInfo(const nsIFrame* aDelegatingFrame, - nscoord& aXMost, - nscoord& aYMost) const -{ - aXMost = aYMost = 0; - for (nsIFrame* f = mAbsoluteFrames.FirstChild(); nsnull != f; f->GetNextSibling(&f)) { - // Get the frame's x-most and y-most. This is for its flowed content only - nsRect rect; - f->GetRect(rect); + // If the frame has visible overflow, then store it as a property on the + // frame. This allows us to be able to recover it without having to reflow + // the frame + nsFrameState kidFrameState; + aKidFrame->GetFrameState(&kidFrameState); + if (kidFrameState & NS_FRAME_OUTSIDE_CHILDREN) { + // Get the property (creating a rect struct if necessary) + nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, aKidFrame, PR_TRUE); - if (rect.XMost() > aXMost) { - aXMost = rect.XMost(); - } - if (rect.YMost() > aYMost) { - aYMost = rect.YMost(); - } - - // If the child frame is also an area frame, then take into account its child - // absolutely positioned elements - nsIAreaFrame* areaFrame; - if (NS_SUCCEEDED(f->QueryInterface(kAreaFrameIID, (void**)&areaFrame))) { - nscoord xMost, yMost; - - areaFrame->GetPositionedInfo(xMost, yMost); - // Convert to our coordinate space - xMost += rect.x; - yMost += rect.y; - - if (xMost > aXMost) { - aXMost = xMost; - } - if (yMost > aYMost) { - aYMost = yMost; - } + if (overflowArea) { + *overflowArea = kidDesiredSize.mOverflowArea; } } - return NS_OK; + return rv; } - diff --git a/layout/generic/nsAbsoluteContainingBlock.h b/layout/generic/nsAbsoluteContainingBlock.h index 434c23a9c4f2..fcffdb8ca28c 100644 --- a/layout/generic/nsAbsoluteContainingBlock.h +++ b/layout/generic/nsAbsoluteContainingBlock.h @@ -71,31 +71,35 @@ public: // Called by the delegating frame after it has done its reflow first. This // function will reflow any absolutely positioned child frames that need to // be reflowed, e.g., because the absolutely positioned child frame has - // 'auto' for an offset, or a percentage based width or height + // 'auto' for an offset, or a percentage based width or height. + // Returns (in the local coordinate space) the bounding rect of the absolutely + // positioned child elements taking into account their overflow area (if it + // is visible) nsresult Reflow(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nscoord aContainingBlockWidth, - nscoord aContainingBlockHeight); + nscoord aContainingBlockHeight, + nsRect& aChildBounds); // Called only for a reflow reason of eReflowReason_Incremental. The // aWasHandled return value indicates whether the reflow command was // handled (i.e., the reflow command involved an absolutely positioned - // child element), or whether the caller should handle it + // child element), or whether the caller should handle it. + // Returns (in the local coordinate space) the bounding rect of the absolutely + // positioned child elements taking into account their overflow area (if it + // is visible). This is only set if the reflow command was handled nsresult IncrementalReflow(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nscoord aContainingBlockWidth, nscoord aContainingBlockHeight, - PRBool& aWasHandled); + PRBool& aWasHandled, + nsRect& aChildBounds); void DestroyFrames(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext); - nsresult GetPositionedInfo(const nsIFrame* aDelegatingFrame, - nscoord& aXMost, - nscoord& aYMost) const; - protected: nsresult ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext, @@ -106,6 +110,8 @@ protected: PRBool aInitialReflow, nsReflowStatus& aStatus); + void CalculateChildBounds(nsIPresContext* aPresContext, nsRect& aChildBounds); + protected: nsFrameList mAbsoluteFrames; // additional named child list }; diff --git a/layout/generic/nsAreaFrame.cpp b/layout/generic/nsAreaFrame.cpp index bff647cc27d7..942e131d64f4 100644 --- a/layout/generic/nsAreaFrame.cpp +++ b/layout/generic/nsAreaFrame.cpp @@ -59,23 +59,6 @@ nsAreaFrame::nsAreaFrame() { } -///////////////////////////////////////////////////////////////////////////// -// nsISupports - -NS_IMETHODIMP -nsAreaFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) -{ - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - } - if (aIID.Equals(kIAreaFrameIID)) { - nsIAreaFrame* tmp = (nsIAreaFrame*)this; - *aInstancePtr = (void*)tmp; - return NS_OK; - } - return nsBlockFrame::QueryInterface(aIID, aInstancePtr); -} - ///////////////////////////////////////////////////////////////////////////// // nsIFrame @@ -186,32 +169,6 @@ nsAreaFrame::FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const return nsBlockFrame::FirstChild(aListName, aFirstChild); } -// Return the x-most and y-most for the child absolutely positioned -// elements -NS_IMETHODIMP -nsAreaFrame::GetPositionedInfo(nscoord& aXMost, nscoord& aYMost) const -{ - nsresult rv = mAbsoluteContainer.GetPositionedInfo(this, aXMost, aYMost); - - // If we have child frames that stick outside of our box, and they should - // be visible, then include them too so the total size is correct - if (mState & NS_FRAME_OUTSIDE_CHILDREN) { - const nsStyleDisplay* display = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - - if (NS_STYLE_OVERFLOW_VISIBLE == display->mOverflow) { - if (mCombinedArea.XMost() > aXMost) { - aXMost = mCombinedArea.XMost(); - } - if (mCombinedArea.YMost() > aYMost) { - aYMost = mCombinedArea.YMost(); - } - } - } - - return rv; -} - static void CalculateContainingBlock(const nsHTMLReflowState& aReflowState, nscoord aFrameWidth, @@ -244,7 +201,7 @@ CalculateContainingBlock(const nsHTMLReflowState& aReflowState, NS_IMETHODIMP nsAreaFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { @@ -262,31 +219,55 @@ nsAreaFrame::Reflow(nsIPresContext* aPresContext, nscoord containingBlockWidth; nscoord containingBlockHeight; PRBool handled; + nsRect childBounds; CalculateContainingBlock(aReflowState, mRect.width, mRect.height, containingBlockWidth, containingBlockHeight); mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, containingBlockWidth, containingBlockHeight, - handled); + handled, childBounds); // If the incremental reflow command was handled by the absolute positioning // code, then we're all done if (handled) { - // Just return our current size as our desired size - aDesiredSize.width = mRect.width; - aDesiredSize.height = mRect.height; - aDesiredSize.ascent = mRect.height; - aDesiredSize.descent = 0; + // Just return our current size as our desired size. + // XXX We need to know the overflow area for the flowed content, and + // we don't have a way to get that currently so for the time being pretend + // a resize reflow occured +#if 0 + aMetrics.width = mRect.width; + aMetrics.height = mRect.height; + aMetrics.ascent = mRect.height; + aMetrics.descent = 0; // Whether or not we're complete hasn't changed aStatus = (nsnull != mNextInFlow) ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE; +#else + nsHTMLReflowState reflowState(aReflowState); + reflowState.reason = eReflowReason_Resize; + reflowState.reflowCommand = nsnull; + rv = nsBlockFrame::Reflow(aPresContext, aMetrics, reflowState, aStatus); +#endif + + // Factor the absolutely positioned child bounds into the overflow area + aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds); + + // Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly + if ((aMetrics.mOverflowArea.x < 0) || + (aMetrics.mOverflowArea.y < 0) || + (aMetrics.mOverflowArea.XMost() > aMetrics.width) || + (aMetrics.mOverflowArea.YMost() > aMetrics.height)) { + mState |= NS_FRAME_OUTSIDE_CHILDREN; + } else { + mState &= ~NS_FRAME_OUTSIDE_CHILDREN; + } return rv; } } // Let the block frame do its reflow first - rv = nsBlockFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + rv = nsBlockFrame::Reflow(aPresContext, aMetrics, aReflowState, aStatus); // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed, e.g., elements with a percentage @@ -294,28 +275,37 @@ nsAreaFrame::Reflow(nsIPresContext* aPresContext, if (NS_SUCCEEDED(rv)) { nscoord containingBlockWidth; nscoord containingBlockHeight; + nsRect childBounds; - CalculateContainingBlock(aReflowState, aDesiredSize.width, aDesiredSize.height, + CalculateContainingBlock(aReflowState, aMetrics.width, aMetrics.height, containingBlockWidth, containingBlockHeight); rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, - containingBlockWidth, containingBlockHeight); + containingBlockWidth, containingBlockHeight, + childBounds); + + // Factor the absolutely positioned child bounds into the overflow area + aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds); + + // Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly + if ((aMetrics.mOverflowArea.x < 0) || + (aMetrics.mOverflowArea.y < 0) || + (aMetrics.mOverflowArea.XMost() > aMetrics.width) || + (aMetrics.mOverflowArea.YMost() > aMetrics.height)) { + mState |= NS_FRAME_OUTSIDE_CHILDREN; + } else { + mState &= ~NS_FRAME_OUTSIDE_CHILDREN; + } } #ifdef NOISY_MAX_ELEMENT_SIZE ListTag(stdout); printf(": maxElementSize=%d,%d desiredSize=%d,%d\n", - aDesiredSize.maxElementSize ? aDesiredSize.maxElementSize->width : 0, - aDesiredSize.maxElementSize ? aDesiredSize.maxElementSize->height : 0, - aDesiredSize.width, aDesiredSize.height); + aMetrics.maxElementSize ? aMetrics.maxElementSize->width : 0, + aMetrics.maxElementSize ? aMetrics.maxElementSize->height : 0, + aMetrics.width, aMetrics.height); #endif - // If we have children that stick outside our box, then remember the - // combined area, because we'll need it later when sizing our view - if (mState & NS_FRAME_OUTSIDE_CHILDREN) { - mCombinedArea = aDesiredSize.mCombinedArea; - } - return rv; } diff --git a/layout/generic/nsAreaFrame.h b/layout/generic/nsAreaFrame.h index 1f4c4b1cbc0e..b291dfab938b 100644 --- a/layout/generic/nsAreaFrame.h +++ b/layout/generic/nsAreaFrame.h @@ -24,7 +24,6 @@ #include "nsBlockFrame.h" #include "nsVoidArray.h" -#include "nsIAreaFrame.h" #include "nsAbsoluteContainingBlock.h" class nsSpaceManager; @@ -44,14 +43,11 @@ struct nsStylePosition; * * @see nsLayoutAtoms::absoluteList */ -class nsAreaFrame : public nsBlockFrame, public nsIAreaFrame +class nsAreaFrame : public nsBlockFrame { public: friend nsresult NS_NewAreaFrame(nsIPresShell* aPresShell, nsIFrame** aResult, PRUint32 aFlags); - // nsISupports - NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); - // nsIFrame NS_IMETHOD Destroy(nsIPresContext* aPresContext); @@ -94,15 +90,11 @@ public: NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; #endif - // nsIAreaFrame - NS_IMETHOD GetPositionedInfo(nscoord& aXMost, nscoord& aYMost) const; - protected: nsAreaFrame(); private: nsAbsoluteContainingBlock mAbsoluteContainer; - nsRect mCombinedArea; }; #endif /* nsAreaFrame_h___ */ diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index d19ad6af826e..777aecf1345d 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1511,7 +1511,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, // children, make sure its big enough to include those that stick // outside the box. if (NS_FRAME_OUTSIDE_CHILDREN & mState) { - nscoord xMost = aMetrics.mCombinedArea.XMost(); + nscoord xMost = aMetrics.mOverflowArea.XMost(); if (xMost > aMetrics.width) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1519,7 +1519,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, #endif aMetrics.width = xMost; } - nscoord yMost = aMetrics.mCombinedArea.YMost(); + nscoord yMost = aMetrics.mOverflowArea.YMost(); if (yMost > aMetrics.height) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1622,10 +1622,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, aMetrics.mCarriedOutBottomMargin); if (mState & NS_FRAME_OUTSIDE_CHILDREN) { printf(" combinedArea={%d,%d,%d,%d}", - aMetrics.mCombinedArea.x, - aMetrics.mCombinedArea.y, - aMetrics.mCombinedArea.width, - aMetrics.mCombinedArea.height); + aMetrics.mOverflowArea.x, + aMetrics.mOverflowArea.y, + aMetrics.mOverflowArea.width, + aMetrics.mOverflowArea.height); } if (aMetrics.maxElementSize) { printf(" maxElementSize=%d,%d", @@ -1969,14 +1969,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, // If the combined area of our children exceeds our bounding box // then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it. - aMetrics.mCombinedArea.x = xa; - aMetrics.mCombinedArea.y = ya; - aMetrics.mCombinedArea.width = xb - xa; - aMetrics.mCombinedArea.height = yb - ya; - if ((aMetrics.mCombinedArea.x < 0) || - (aMetrics.mCombinedArea.y < 0) || - (aMetrics.mCombinedArea.XMost() > aMetrics.width) || - (aMetrics.mCombinedArea.YMost() > aMetrics.height)) { + aMetrics.mOverflowArea.x = xa; + aMetrics.mOverflowArea.y = ya; + aMetrics.mOverflowArea.width = xb - xa; + aMetrics.mOverflowArea.height = yb - ya; + if ((aMetrics.mOverflowArea.x < 0) || + (aMetrics.mOverflowArea.y < 0) || + (aMetrics.mOverflowArea.XMost() > aMetrics.width) || + (aMetrics.mOverflowArea.YMost() > aMetrics.height)) { mState |= NS_FRAME_OUTSIDE_CHILDREN; } else { @@ -2000,6 +2000,7 @@ nsBlockFrame::PrepareChildIncrementalReflow(nsBlockReflowState& aState) // XXX Huh, that's not true anymore. We do cache the width component of // the max-element-size... if (aState.mComputeMaxElementSize) { + printf("BLOCK: marking all child frames dirty...\n"); return PrepareResizeReflow(aState); } @@ -4875,7 +4876,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, aMarginResult.left = m.left; const nsHTMLReflowMetrics& metrics = brc.GetMetrics(); - aCombinedRect = metrics.mCombinedArea; + aCombinedRect = metrics.mOverflowArea; // Set the rect, make sure the view is properly sized and positioned, // and tell the frame we're done reflowing it floater->SizeTo(aState.mPresContext, metrics.width, metrics.height); @@ -4883,7 +4884,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, floater->GetView(aState.mPresContext, &view); if (view) { nsContainerFrame::SyncFrameViewAfterReflow(aState.mPresContext, floater, view, - &metrics.mCombinedArea, + &metrics.mOverflowArea, NS_FRAME_NO_MOVE_VIEW); } floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED); diff --git a/layout/generic/nsBlockReflowContext.cpp b/layout/generic/nsBlockReflowContext.cpp index 103938ae0ade..cb406b64e70a 100644 --- a/layout/generic/nsBlockReflowContext.cpp +++ b/layout/generic/nsBlockReflowContext.cpp @@ -317,11 +317,11 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame, aFrame->GetFrameState(&state); if (0 == (NS_FRAME_OUTSIDE_CHILDREN & state)) { - // Provide combined area for child that doesn't have any - mMetrics.mCombinedArea.x = 0; - mMetrics.mCombinedArea.y = 0; - mMetrics.mCombinedArea.width = mMetrics.width; - mMetrics.mCombinedArea.height = mMetrics.height; + // Provide overflow area for child that doesn't have any + mMetrics.mOverflowArea.x = 0; + mMetrics.mOverflowArea.y = 0; + mMetrics.mOverflowArea.width = mMetrics.width; + mMetrics.mOverflowArea.height = mMetrics.height; } // Now that frame has been reflowed at least one time make sure that @@ -376,8 +376,8 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, nscoord x = mX; nscoord y = mY; // When deciding whether it's an empty paragraph we also need to take into - // account the combined area - if ((0 == mMetrics.height) && (0 == mMetrics.mCombinedArea.height)) { + // account the overflow area + if ((0 == mMetrics.height) && (0 == mMetrics.mOverflowArea.height)) { if (IsHTMLParagraph(mFrame)) { // Special "feature" for HTML compatability - empty paragraphs // collapse into nothingness, including their margins. Signal @@ -432,7 +432,7 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, // Retain combined area information in case we contain a floater // and nothing else. - aCombinedRect = mMetrics.mCombinedArea; + aCombinedRect = mMetrics.mOverflowArea; aCombinedRect.x += x; aCombinedRect.y += y; } @@ -549,10 +549,10 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, // Compute combined-rect in callers coordinate system. The value // returned in the reflow metrics is relative to the child // frame. - aCombinedRect.x = mMetrics.mCombinedArea.x + x; - aCombinedRect.y = mMetrics.mCombinedArea.y + y; - aCombinedRect.width = mMetrics.mCombinedArea.width; - aCombinedRect.height = mMetrics.mCombinedArea.height; + aCombinedRect.x = mMetrics.mOverflowArea.x + x; + aCombinedRect.y = mMetrics.mOverflowArea.y + y; + aCombinedRect.width = mMetrics.mOverflowArea.width; + aCombinedRect.height = mMetrics.mOverflowArea.height; // Now place the frame and complete the reflow process nsContainerFrame::FinishReflowChild(mFrame, mPresContext, mMetrics, x, y, 0); diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index d19ad6af826e..777aecf1345d 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -1511,7 +1511,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, // children, make sure its big enough to include those that stick // outside the box. if (NS_FRAME_OUTSIDE_CHILDREN & mState) { - nscoord xMost = aMetrics.mCombinedArea.XMost(); + nscoord xMost = aMetrics.mOverflowArea.XMost(); if (xMost > aMetrics.width) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1519,7 +1519,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, #endif aMetrics.width = xMost; } - nscoord yMost = aMetrics.mCombinedArea.YMost(); + nscoord yMost = aMetrics.mOverflowArea.YMost(); if (yMost > aMetrics.height) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1622,10 +1622,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, aMetrics.mCarriedOutBottomMargin); if (mState & NS_FRAME_OUTSIDE_CHILDREN) { printf(" combinedArea={%d,%d,%d,%d}", - aMetrics.mCombinedArea.x, - aMetrics.mCombinedArea.y, - aMetrics.mCombinedArea.width, - aMetrics.mCombinedArea.height); + aMetrics.mOverflowArea.x, + aMetrics.mOverflowArea.y, + aMetrics.mOverflowArea.width, + aMetrics.mOverflowArea.height); } if (aMetrics.maxElementSize) { printf(" maxElementSize=%d,%d", @@ -1969,14 +1969,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, // If the combined area of our children exceeds our bounding box // then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it. - aMetrics.mCombinedArea.x = xa; - aMetrics.mCombinedArea.y = ya; - aMetrics.mCombinedArea.width = xb - xa; - aMetrics.mCombinedArea.height = yb - ya; - if ((aMetrics.mCombinedArea.x < 0) || - (aMetrics.mCombinedArea.y < 0) || - (aMetrics.mCombinedArea.XMost() > aMetrics.width) || - (aMetrics.mCombinedArea.YMost() > aMetrics.height)) { + aMetrics.mOverflowArea.x = xa; + aMetrics.mOverflowArea.y = ya; + aMetrics.mOverflowArea.width = xb - xa; + aMetrics.mOverflowArea.height = yb - ya; + if ((aMetrics.mOverflowArea.x < 0) || + (aMetrics.mOverflowArea.y < 0) || + (aMetrics.mOverflowArea.XMost() > aMetrics.width) || + (aMetrics.mOverflowArea.YMost() > aMetrics.height)) { mState |= NS_FRAME_OUTSIDE_CHILDREN; } else { @@ -2000,6 +2000,7 @@ nsBlockFrame::PrepareChildIncrementalReflow(nsBlockReflowState& aState) // XXX Huh, that's not true anymore. We do cache the width component of // the max-element-size... if (aState.mComputeMaxElementSize) { + printf("BLOCK: marking all child frames dirty...\n"); return PrepareResizeReflow(aState); } @@ -4875,7 +4876,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, aMarginResult.left = m.left; const nsHTMLReflowMetrics& metrics = brc.GetMetrics(); - aCombinedRect = metrics.mCombinedArea; + aCombinedRect = metrics.mOverflowArea; // Set the rect, make sure the view is properly sized and positioned, // and tell the frame we're done reflowing it floater->SizeTo(aState.mPresContext, metrics.width, metrics.height); @@ -4883,7 +4884,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, floater->GetView(aState.mPresContext, &view); if (view) { nsContainerFrame::SyncFrameViewAfterReflow(aState.mPresContext, floater, view, - &metrics.mCombinedArea, + &metrics.mOverflowArea, NS_FRAME_NO_MOVE_VIEW); } floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED); diff --git a/layout/generic/nsBlockReflowState.h b/layout/generic/nsBlockReflowState.h index d19ad6af826e..777aecf1345d 100644 --- a/layout/generic/nsBlockReflowState.h +++ b/layout/generic/nsBlockReflowState.h @@ -1511,7 +1511,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, // children, make sure its big enough to include those that stick // outside the box. if (NS_FRAME_OUTSIDE_CHILDREN & mState) { - nscoord xMost = aMetrics.mCombinedArea.XMost(); + nscoord xMost = aMetrics.mOverflowArea.XMost(); if (xMost > aMetrics.width) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1519,7 +1519,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, #endif aMetrics.width = xMost; } - nscoord yMost = aMetrics.mCombinedArea.YMost(); + nscoord yMost = aMetrics.mOverflowArea.YMost(); if (yMost > aMetrics.height) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1622,10 +1622,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, aMetrics.mCarriedOutBottomMargin); if (mState & NS_FRAME_OUTSIDE_CHILDREN) { printf(" combinedArea={%d,%d,%d,%d}", - aMetrics.mCombinedArea.x, - aMetrics.mCombinedArea.y, - aMetrics.mCombinedArea.width, - aMetrics.mCombinedArea.height); + aMetrics.mOverflowArea.x, + aMetrics.mOverflowArea.y, + aMetrics.mOverflowArea.width, + aMetrics.mOverflowArea.height); } if (aMetrics.maxElementSize) { printf(" maxElementSize=%d,%d", @@ -1969,14 +1969,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, // If the combined area of our children exceeds our bounding box // then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it. - aMetrics.mCombinedArea.x = xa; - aMetrics.mCombinedArea.y = ya; - aMetrics.mCombinedArea.width = xb - xa; - aMetrics.mCombinedArea.height = yb - ya; - if ((aMetrics.mCombinedArea.x < 0) || - (aMetrics.mCombinedArea.y < 0) || - (aMetrics.mCombinedArea.XMost() > aMetrics.width) || - (aMetrics.mCombinedArea.YMost() > aMetrics.height)) { + aMetrics.mOverflowArea.x = xa; + aMetrics.mOverflowArea.y = ya; + aMetrics.mOverflowArea.width = xb - xa; + aMetrics.mOverflowArea.height = yb - ya; + if ((aMetrics.mOverflowArea.x < 0) || + (aMetrics.mOverflowArea.y < 0) || + (aMetrics.mOverflowArea.XMost() > aMetrics.width) || + (aMetrics.mOverflowArea.YMost() > aMetrics.height)) { mState |= NS_FRAME_OUTSIDE_CHILDREN; } else { @@ -2000,6 +2000,7 @@ nsBlockFrame::PrepareChildIncrementalReflow(nsBlockReflowState& aState) // XXX Huh, that's not true anymore. We do cache the width component of // the max-element-size... if (aState.mComputeMaxElementSize) { + printf("BLOCK: marking all child frames dirty...\n"); return PrepareResizeReflow(aState); } @@ -4875,7 +4876,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, aMarginResult.left = m.left; const nsHTMLReflowMetrics& metrics = brc.GetMetrics(); - aCombinedRect = metrics.mCombinedArea; + aCombinedRect = metrics.mOverflowArea; // Set the rect, make sure the view is properly sized and positioned, // and tell the frame we're done reflowing it floater->SizeTo(aState.mPresContext, metrics.width, metrics.height); @@ -4883,7 +4884,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, floater->GetView(aState.mPresContext, &view); if (view) { nsContainerFrame::SyncFrameViewAfterReflow(aState.mPresContext, floater, view, - &metrics.mCombinedArea, + &metrics.mOverflowArea, NS_FRAME_NO_MOVE_VIEW); } floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED); diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index ccf3222940ac..7db54d6150f7 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -718,7 +718,7 @@ nsContainerFrame::FinishReflowChild(nsIFrame* aKidFrame, // Make sure the frame's view is properly sized and positioned and has // things like opacity correct SyncFrameViewAfterReflow(aPresContext, aKidFrame, view, - &aDesiredSize.mCombinedArea, + &aDesiredSize.mOverflowArea, aFlags); } else if (0 == (aFlags & NS_FRAME_NO_MOVE_CHILD_VIEWS)) { diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 771d4c60b949..4b3c8a181542 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1567,10 +1567,10 @@ nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState, aMetrics.ascent = 0; aMetrics.descent = 0; aMetrics.mCarriedOutBottomMargin = 0; - aMetrics.mCombinedArea.x = 0; - aMetrics.mCombinedArea.y = 0; - aMetrics.mCombinedArea.width = 0; - aMetrics.mCombinedArea.height = 0; + aMetrics.mOverflowArea.x = 0; + aMetrics.mOverflowArea.y = 0; + aMetrics.mOverflowArea.width = 0; + aMetrics.mOverflowArea.height = 0; if (aMetrics.maxElementSize) { aMetrics.maxElementSize->width = 0; aMetrics.maxElementSize->height = 0; diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 79e00a712146..8719d89d8df0 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -34,7 +34,6 @@ #include "nsCSSRendering.h" #include "nsIScrollableView.h" #include "nsWidgetsCID.h" -#include "nsIAreaFrame.h" #include "nsGfxScrollFrame.h" #include "nsLayoutAtoms.h" #include "nsIXMLContent.h" @@ -54,7 +53,6 @@ static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID); -static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); static NS_DEFINE_IID(kIAnonymousContentCreatorIID, NS_IANONYMOUS_CONTENT_CREATOR_IID); @@ -893,23 +891,8 @@ nsGfxScrollFrameInner::CalculateChildTotalSize(nsIFrame* aKidFrame, nsFrameState kidState; aKidFrame->GetFrameState(&kidState); if (NS_FRAME_OUTSIDE_CHILDREN & kidState) { - aKidReflowMetrics.width = aKidReflowMetrics.mCombinedArea.width; - aKidReflowMetrics.height = aKidReflowMetrics.mCombinedArea.height; - } - - // If it's an area frame, then get the total size which includes the - // space taken up by absolutely positioned child elements - nsIAreaFrame* areaFrame; - if (NS_SUCCEEDED(aKidFrame->QueryInterface(kAreaFrameIID, (void**)&areaFrame))) { - nscoord xMost, yMost; - - areaFrame->GetPositionedInfo(xMost, yMost); - if (xMost > aKidReflowMetrics.width) { - aKidReflowMetrics.width = xMost; - } - if (yMost > aKidReflowMetrics.height) { - aKidReflowMetrics.height = yMost; - } + aKidReflowMetrics.width = aKidReflowMetrics.mOverflowArea.width; + aKidReflowMetrics.height = aKidReflowMetrics.mOverflowArea.height; } return NS_OK; diff --git a/layout/generic/nsHTMLFrame.cpp b/layout/generic/nsHTMLFrame.cpp index e78033ea415b..e3d62879b6c7 100644 --- a/layout/generic/nsHTMLFrame.cpp +++ b/layout/generic/nsHTMLFrame.cpp @@ -41,12 +41,10 @@ #include "nsIEventStateManager.h" #include "nsIDeviceContext.h" #include "nsIScrollableView.h" -#include "nsIAreaFrame.h" #include "nsLayoutAtoms.h" #include "nsIPresShell.h" // Interface IDs -static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID); static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); @@ -345,36 +343,16 @@ RootFrame::Reflow(nsIPresContext* aPresContext, nscoord paddingEdgeX = kidDesiredSize.width - border.right; nscoord paddingEdgeY = kidDesiredSize.height - border.bottom; - if (kidDesiredSize.mCombinedArea.XMost() > paddingEdgeX) { - kidDesiredSize.width = kidDesiredSize.mCombinedArea.XMost() + + if (kidDesiredSize.mOverflowArea.XMost() > paddingEdgeX) { + kidDesiredSize.width = kidDesiredSize.mOverflowArea.XMost() + border.right; } - if (kidDesiredSize.mCombinedArea.YMost() > paddingEdgeY) { - kidDesiredSize.height = kidDesiredSize.mCombinedArea.YMost() + + if (kidDesiredSize.mOverflowArea.YMost() > paddingEdgeY) { + kidDesiredSize.height = kidDesiredSize.mOverflowArea.YMost() + border.bottom; } } - // XXX It would be nice if this were also part of the reflow metrics... - nsIAreaFrame* areaFrame; - if (NS_SUCCEEDED(kidFrame->QueryInterface(kAreaFrameIID, (void**)&areaFrame))) { - // Get the x-most and y-most of the absolutely positioned children - nscoord positionedXMost, positionedYMost; - areaFrame->GetPositionedInfo(positionedXMost, positionedYMost); - - // The background covers the content area and padding area, so check - // for children sticking outside the padding edge - nscoord paddingEdgeX = kidDesiredSize.width - border.right; - nscoord paddingEdgeY = kidDesiredSize.height - border.bottom; - - if (positionedXMost > paddingEdgeX) { - kidDesiredSize.width = positionedXMost + border.right; - } - if (positionedYMost > paddingEdgeY) { - kidDesiredSize.height = positionedYMost + border.bottom; - } - } - // If our height is fixed, then make sure the child frame plus its top and // bottom margin is at least that high as well... if (NS_AUTOHEIGHT != aReflowState.mComputedHeight) { diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index c9e2e45050a7..a1108370970b 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -217,20 +217,23 @@ struct nsHTMLReflowMetrics { // (generational) bottom margin value. nscoord mCarriedOutBottomMargin; - // For frames that have children that stick outside their rect - // (NS_FRAME_OUTSIDE_CHILDREN) this rectangle will contain the - // absolute bounds of the frame. Since the frame doesn't know where - // it is going to be positioned in its parent, the assumption is - // that it is placed at 0,0 when computing this area. - nsRect mCombinedArea; + // For frames that have content that overflow their content area + // (NS_FRAME_OUTSIDE_CHILDREN) this rectangle represents the total area + // of the frame including visible overflow, i.e., don't include overflowing + // content that is hidden. + // The rect is in the local coordinate space of the frame, and should be at + // least as big as the desired size. If there is no content that overflows, + // then the overflow area is identical to the desired size and should be + // {0, 0, mWidth, mHeight}. + nsRect mOverflowArea; nsHTMLReflowMetrics(nsSize* aMaxElementSize) { maxElementSize = aMaxElementSize; mCarriedOutBottomMargin = 0; - mCombinedArea.x = 0; - mCombinedArea.y = 0; - mCombinedArea.width = 0; - mCombinedArea.height = 0; + mOverflowArea.x = 0; + mOverflowArea.y = 0; + mOverflowArea.width = 0; + mOverflowArea.height = 0; // XXX These are OUT parameters and so they shouldn't have to be // initialized, but there are some bad frame classes that aren't diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index f6b68a5e592d..326470af89b4 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -461,12 +461,12 @@ nsInlineFrame::ReflowFrames(nsIPresContext* aPresContext, } } - // For now our combined area is zero. The real value will be + // For now our overflow area is zero. The real value will be // computed during vertical alignment of the line we are on. - aMetrics.mCombinedArea.x = 0; - aMetrics.mCombinedArea.y = 0; - aMetrics.mCombinedArea.width = aMetrics.width; - aMetrics.mCombinedArea.height = aMetrics.height; + aMetrics.mOverflowArea.x = 0; + aMetrics.mOverflowArea.y = 0; + aMetrics.mOverflowArea.width = aMetrics.width; + aMetrics.mOverflowArea.height = aMetrics.height; #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -973,12 +973,13 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext, if (eReflowReason_Incremental == aReflowState.reason) { // Give the absolute positioning code a chance to handle it PRBool handled; + nsRect childBounds; nscoord containingBlockWidth = -1; nscoord containingBlockHeight = -1; mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, containingBlockWidth, containingBlockHeight, - handled); + handled, childBounds); // If the incremental reflow command was handled by the absolute positioning // code, then we're all done @@ -989,7 +990,25 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowState reflowState(aReflowState); reflowState.reason = eReflowReason_Resize; reflowState.reflowCommand = nsnull; - return nsInlineFrame::Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + rv = nsInlineFrame::Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + + // XXX Although this seems like the correct thing to do the line layout + // code seems to reset the NS_FRAME_OUTSIDE_CHILDREN and so it is ignored +#if 0 + // Factor the absolutely positioned child bounds into the overflow area + aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds); + + // Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly + if ((aDesiredSize.mOverflowArea.x < 0) || + (aDesiredSize.mOverflowArea.y < 0) || + (aDesiredSize.mOverflowArea.XMost() > aDesiredSize.width) || + (aDesiredSize.mOverflowArea.YMost() > aDesiredSize.height)) { + mState |= NS_FRAME_OUTSIDE_CHILDREN; + } else { + mState &= ~NS_FRAME_OUTSIDE_CHILDREN; + } +#endif + return rv; } } @@ -1001,9 +1020,28 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext, if (NS_SUCCEEDED(rv)) { nscoord containingBlockWidth = -1; nscoord containingBlockHeight = -1; + nsRect childBounds; rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, - containingBlockWidth, containingBlockHeight); + containingBlockWidth, containingBlockHeight, + childBounds); + + // XXX Although this seems like the correct thing to do the line layout + // code seems to reset the NS_FRAME_OUTSIDE_CHILDREN and so it is ignored +#if 0 + // Factor the absolutely positioned child bounds into the overflow area + aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds); + + // Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly + if ((aDesiredSize.mOverflowArea.x < 0) || + (aDesiredSize.mOverflowArea.y < 0) || + (aDesiredSize.mOverflowArea.XMost() > aDesiredSize.width) || + (aDesiredSize.mOverflowArea.YMost() > aDesiredSize.height)) { + mState |= NS_FRAME_OUTSIDE_CHILDREN; + } else { + mState &= ~NS_FRAME_OUTSIDE_CHILDREN; + } +#endif } return rv; diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index b2c9ef2bbb4d..dd28f41c7cfb 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -1062,7 +1062,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, aFrame->GetFrameState(&state); if (NS_FRAME_OUTSIDE_CHILDREN & state) { - pfd->mCombinedArea = metrics.mCombinedArea; + pfd->mCombinedArea = metrics.mOverflowArea; } else { pfd->mCombinedArea.x = 0; @@ -1480,7 +1480,7 @@ nsLineLayout::AddBulletFrame(nsIFrame* aFrame, // Note: y value will be updated during vertical alignment aFrame->GetRect(pfd->mBounds); - pfd->mCombinedArea = aMetrics.mCombinedArea; + pfd->mCombinedArea = aMetrics.mOverflowArea; if (mComputeMaxElementSize) { pfd->mMaxElementSize.SizeTo(aMetrics.width, aMetrics.height); } diff --git a/layout/generic/nsViewportFrame.cpp b/layout/generic/nsViewportFrame.cpp index 22045b584b3b..83ac155d6ff2 100644 --- a/layout/generic/nsViewportFrame.cpp +++ b/layout/generic/nsViewportFrame.cpp @@ -375,7 +375,7 @@ ViewportFrame::ReflowFixedFrame(nsIPresContext* aPresContext, // Size and position the view and set its opacity, visibility, content // transparency, and clip nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame, kidView, - &kidDesiredSize.mCombinedArea); + &kidDesiredSize.mOverflowArea); aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); return rv; } diff --git a/layout/html/base/src/nsAbsoluteContainingBlock.cpp b/layout/html/base/src/nsAbsoluteContainingBlock.cpp index fe0c7f936cb2..29a960f8883e 100644 --- a/layout/html/base/src/nsAbsoluteContainingBlock.cpp +++ b/layout/html/base/src/nsAbsoluteContainingBlock.cpp @@ -19,10 +19,10 @@ * * Contributor(s): */ +#include "nsCOMPtr.h" #include "nsAbsoluteContainingBlock.h" #include "nsContainerFrame.h" #include "nsHTMLIIDs.h" -#include "nsIAreaFrame.h" #include "nsIReflowCommand.h" #include "nsIStyleContext.h" #include "nsIViewManager.h" @@ -30,8 +30,8 @@ #include "nsIReflowCommand.h" #include "nsIPresShell.h" #include "nsHTMLParts.h" - -static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); +#include "nsIPresContext.h" +#include "nsIFrameManager.h" nsresult nsAbsoluteContainingBlock::FirstChild(const nsIFrame* aDelegatingFrame, @@ -127,13 +127,62 @@ nsAbsoluteContainingBlock::RemoveFrame(nsIFrame* aDelegatingFrame, return result ? NS_OK : NS_ERROR_FAILURE; } +// Destructor function for the collapse offset frame property +static void +DestroyRectFunc(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIAtom* aPropertyName, + void* aPropertyValue) +{ + delete (nsRect*)aPropertyValue; +} + +static nsRect* +GetOverflowAreaProperty(nsIPresContext* aPresContext, + nsIFrame* aFrame, + PRBool aCreateIfNecessary = PR_FALSE) +{ + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + + if (presShell) { + nsCOMPtr frameManager; + presShell->GetFrameManager(getter_AddRefs(frameManager)); + + if (frameManager) { + void* value; + + frameManager->GetFrameProperty(aFrame, nsLayoutAtoms::overflowAreaProperty, + 0, &value); + if (value) { + return (nsRect*)value; // the property already exists + + } else if (aCreateIfNecessary) { + // The property isn't set yet, so allocate a new rect, set the property, + // and return the newly allocated rect + nsRect* overflow = new nsRect(0, 0, 0, 0); + + frameManager->SetFrameProperty(aFrame, nsLayoutAtoms::overflowAreaProperty, + overflow, DestroyRectFunc); + return overflow; + } + } + } + + return nsnull; +} + nsresult nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nscoord aContainingBlockWidth, - nscoord aContainingBlockHeight) + nscoord aContainingBlockHeight, + nsRect& aChildBounds) { + // Initialize OUT parameter + aChildBounds.SetRect(0, 0, 0, 0); + // Make a copy of the reflow state. If the reason is eReflowReason_Incremental, // then change it to eReflowReason_Resize nsHTMLReflowState reflowState(aReflowState); @@ -147,20 +196,73 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, nsReflowStatus kidStatus; ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, reflowState, aContainingBlockWidth, aContainingBlockHeight, kidFrame, PR_FALSE, kidStatus); + + // Add in the child's bounds + nsRect kidBounds; + kidFrame->GetRect(kidBounds); + aChildBounds.UnionRect(aChildBounds, kidBounds); + + // If the frame has visible overflow, then take it into account, too. + nsFrameState kidFrameState; + kidFrame->GetFrameState(&kidFrameState); + if (kidFrameState & NS_FRAME_OUTSIDE_CHILDREN) { + // Get the property + nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, kidFrame); + + if (overflowArea) { + // The overflow area is in the child's coordinate space, so translate + // it into the parent's coordinate space + nsRect rect(*overflowArea); + + rect.MoveBy(kidBounds.x, kidBounds.y); + aChildBounds.UnionRect(aChildBounds, rect); + } + } } return NS_OK; } +void +nsAbsoluteContainingBlock::CalculateChildBounds(nsIPresContext* aPresContext, + nsRect& aChildBounds) +{ + for (nsIFrame* f = mAbsoluteFrames.FirstChild(); f; f->GetNextSibling(&f)) { + // Add in the child's bounds + nsRect bounds; + f->GetRect(bounds); + aChildBounds.UnionRect(aChildBounds, bounds); + + // If the frame has visible overflow, then take it into account, too. + nsFrameState frameState; + f->GetFrameState(&frameState); + if (frameState & NS_FRAME_OUTSIDE_CHILDREN) { + // Get the property + nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, f); + + if (overflowArea) { + // The overflow area is in the child's coordinate space, so translate + // it into the parent's coordinate space + nsRect rect(*overflowArea); + + rect.MoveBy(bounds.x, bounds.y); + aChildBounds.UnionRect(aChildBounds, rect); + } + } + } +} + nsresult nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nscoord aContainingBlockWidth, nscoord aContainingBlockHeight, - PRBool& aWasHandled) + PRBool& aWasHandled, + nsRect& aChildBounds) { - // Initialize the OUT paremeter + // Initialize the OUT paremeters aWasHandled = PR_FALSE; + aChildBounds.SetRect(0, 0, 0, 0); // See if the reflow command is targeted at us nsIFrame* targetFrame; @@ -204,6 +306,9 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin // Indicate we handled the reflow command aWasHandled = PR_TRUE; + + // Calculate the total child bounds + CalculateChildBounds(aPresContext, aChildBounds); } } else { @@ -226,6 +331,9 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin // because it has a view if it changes size the view manager will // damage the dirty area aWasHandled = PR_TRUE; + + // Calculate the total child bounds + CalculateChildBounds(aPresContext, aChildBounds); } } @@ -272,7 +380,6 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat kidReflowState.reason = eReflowReason_Initial; } - // XXX TROY // Send the WillReflow() notification and position the frame aKidFrame->WillReflow(aPresContext); aKidFrame->MoveTo(aPresContext, @@ -382,49 +489,22 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat // Size and position the view and set its opacity, visibility, content // transparency, and clip nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame, kidView, - &kidDesiredSize.mCombinedArea); + &kidDesiredSize.mOverflowArea); aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); - return rv; -} -nsresult -nsAbsoluteContainingBlock::GetPositionedInfo(const nsIFrame* aDelegatingFrame, - nscoord& aXMost, - nscoord& aYMost) const -{ - aXMost = aYMost = 0; - for (nsIFrame* f = mAbsoluteFrames.FirstChild(); nsnull != f; f->GetNextSibling(&f)) { - // Get the frame's x-most and y-most. This is for its flowed content only - nsRect rect; - f->GetRect(rect); + // If the frame has visible overflow, then store it as a property on the + // frame. This allows us to be able to recover it without having to reflow + // the frame + nsFrameState kidFrameState; + aKidFrame->GetFrameState(&kidFrameState); + if (kidFrameState & NS_FRAME_OUTSIDE_CHILDREN) { + // Get the property (creating a rect struct if necessary) + nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, aKidFrame, PR_TRUE); - if (rect.XMost() > aXMost) { - aXMost = rect.XMost(); - } - if (rect.YMost() > aYMost) { - aYMost = rect.YMost(); - } - - // If the child frame is also an area frame, then take into account its child - // absolutely positioned elements - nsIAreaFrame* areaFrame; - if (NS_SUCCEEDED(f->QueryInterface(kAreaFrameIID, (void**)&areaFrame))) { - nscoord xMost, yMost; - - areaFrame->GetPositionedInfo(xMost, yMost); - // Convert to our coordinate space - xMost += rect.x; - yMost += rect.y; - - if (xMost > aXMost) { - aXMost = xMost; - } - if (yMost > aYMost) { - aYMost = yMost; - } + if (overflowArea) { + *overflowArea = kidDesiredSize.mOverflowArea; } } - return NS_OK; + return rv; } - diff --git a/layout/html/base/src/nsAbsoluteContainingBlock.h b/layout/html/base/src/nsAbsoluteContainingBlock.h index 434c23a9c4f2..fcffdb8ca28c 100644 --- a/layout/html/base/src/nsAbsoluteContainingBlock.h +++ b/layout/html/base/src/nsAbsoluteContainingBlock.h @@ -71,31 +71,35 @@ public: // Called by the delegating frame after it has done its reflow first. This // function will reflow any absolutely positioned child frames that need to // be reflowed, e.g., because the absolutely positioned child frame has - // 'auto' for an offset, or a percentage based width or height + // 'auto' for an offset, or a percentage based width or height. + // Returns (in the local coordinate space) the bounding rect of the absolutely + // positioned child elements taking into account their overflow area (if it + // is visible) nsresult Reflow(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nscoord aContainingBlockWidth, - nscoord aContainingBlockHeight); + nscoord aContainingBlockHeight, + nsRect& aChildBounds); // Called only for a reflow reason of eReflowReason_Incremental. The // aWasHandled return value indicates whether the reflow command was // handled (i.e., the reflow command involved an absolutely positioned - // child element), or whether the caller should handle it + // child element), or whether the caller should handle it. + // Returns (in the local coordinate space) the bounding rect of the absolutely + // positioned child elements taking into account their overflow area (if it + // is visible). This is only set if the reflow command was handled nsresult IncrementalReflow(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nscoord aContainingBlockWidth, nscoord aContainingBlockHeight, - PRBool& aWasHandled); + PRBool& aWasHandled, + nsRect& aChildBounds); void DestroyFrames(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext); - nsresult GetPositionedInfo(const nsIFrame* aDelegatingFrame, - nscoord& aXMost, - nscoord& aYMost) const; - protected: nsresult ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, nsIPresContext* aPresContext, @@ -106,6 +110,8 @@ protected: PRBool aInitialReflow, nsReflowStatus& aStatus); + void CalculateChildBounds(nsIPresContext* aPresContext, nsRect& aChildBounds); + protected: nsFrameList mAbsoluteFrames; // additional named child list }; diff --git a/layout/html/base/src/nsAreaFrame.cpp b/layout/html/base/src/nsAreaFrame.cpp index bff647cc27d7..942e131d64f4 100644 --- a/layout/html/base/src/nsAreaFrame.cpp +++ b/layout/html/base/src/nsAreaFrame.cpp @@ -59,23 +59,6 @@ nsAreaFrame::nsAreaFrame() { } -///////////////////////////////////////////////////////////////////////////// -// nsISupports - -NS_IMETHODIMP -nsAreaFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) -{ - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - } - if (aIID.Equals(kIAreaFrameIID)) { - nsIAreaFrame* tmp = (nsIAreaFrame*)this; - *aInstancePtr = (void*)tmp; - return NS_OK; - } - return nsBlockFrame::QueryInterface(aIID, aInstancePtr); -} - ///////////////////////////////////////////////////////////////////////////// // nsIFrame @@ -186,32 +169,6 @@ nsAreaFrame::FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const return nsBlockFrame::FirstChild(aListName, aFirstChild); } -// Return the x-most and y-most for the child absolutely positioned -// elements -NS_IMETHODIMP -nsAreaFrame::GetPositionedInfo(nscoord& aXMost, nscoord& aYMost) const -{ - nsresult rv = mAbsoluteContainer.GetPositionedInfo(this, aXMost, aYMost); - - // If we have child frames that stick outside of our box, and they should - // be visible, then include them too so the total size is correct - if (mState & NS_FRAME_OUTSIDE_CHILDREN) { - const nsStyleDisplay* display = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - - if (NS_STYLE_OVERFLOW_VISIBLE == display->mOverflow) { - if (mCombinedArea.XMost() > aXMost) { - aXMost = mCombinedArea.XMost(); - } - if (mCombinedArea.YMost() > aYMost) { - aYMost = mCombinedArea.YMost(); - } - } - } - - return rv; -} - static void CalculateContainingBlock(const nsHTMLReflowState& aReflowState, nscoord aFrameWidth, @@ -244,7 +201,7 @@ CalculateContainingBlock(const nsHTMLReflowState& aReflowState, NS_IMETHODIMP nsAreaFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { @@ -262,31 +219,55 @@ nsAreaFrame::Reflow(nsIPresContext* aPresContext, nscoord containingBlockWidth; nscoord containingBlockHeight; PRBool handled; + nsRect childBounds; CalculateContainingBlock(aReflowState, mRect.width, mRect.height, containingBlockWidth, containingBlockHeight); mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, containingBlockWidth, containingBlockHeight, - handled); + handled, childBounds); // If the incremental reflow command was handled by the absolute positioning // code, then we're all done if (handled) { - // Just return our current size as our desired size - aDesiredSize.width = mRect.width; - aDesiredSize.height = mRect.height; - aDesiredSize.ascent = mRect.height; - aDesiredSize.descent = 0; + // Just return our current size as our desired size. + // XXX We need to know the overflow area for the flowed content, and + // we don't have a way to get that currently so for the time being pretend + // a resize reflow occured +#if 0 + aMetrics.width = mRect.width; + aMetrics.height = mRect.height; + aMetrics.ascent = mRect.height; + aMetrics.descent = 0; // Whether or not we're complete hasn't changed aStatus = (nsnull != mNextInFlow) ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE; +#else + nsHTMLReflowState reflowState(aReflowState); + reflowState.reason = eReflowReason_Resize; + reflowState.reflowCommand = nsnull; + rv = nsBlockFrame::Reflow(aPresContext, aMetrics, reflowState, aStatus); +#endif + + // Factor the absolutely positioned child bounds into the overflow area + aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds); + + // Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly + if ((aMetrics.mOverflowArea.x < 0) || + (aMetrics.mOverflowArea.y < 0) || + (aMetrics.mOverflowArea.XMost() > aMetrics.width) || + (aMetrics.mOverflowArea.YMost() > aMetrics.height)) { + mState |= NS_FRAME_OUTSIDE_CHILDREN; + } else { + mState &= ~NS_FRAME_OUTSIDE_CHILDREN; + } return rv; } } // Let the block frame do its reflow first - rv = nsBlockFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + rv = nsBlockFrame::Reflow(aPresContext, aMetrics, aReflowState, aStatus); // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed, e.g., elements with a percentage @@ -294,28 +275,37 @@ nsAreaFrame::Reflow(nsIPresContext* aPresContext, if (NS_SUCCEEDED(rv)) { nscoord containingBlockWidth; nscoord containingBlockHeight; + nsRect childBounds; - CalculateContainingBlock(aReflowState, aDesiredSize.width, aDesiredSize.height, + CalculateContainingBlock(aReflowState, aMetrics.width, aMetrics.height, containingBlockWidth, containingBlockHeight); rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, - containingBlockWidth, containingBlockHeight); + containingBlockWidth, containingBlockHeight, + childBounds); + + // Factor the absolutely positioned child bounds into the overflow area + aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds); + + // Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly + if ((aMetrics.mOverflowArea.x < 0) || + (aMetrics.mOverflowArea.y < 0) || + (aMetrics.mOverflowArea.XMost() > aMetrics.width) || + (aMetrics.mOverflowArea.YMost() > aMetrics.height)) { + mState |= NS_FRAME_OUTSIDE_CHILDREN; + } else { + mState &= ~NS_FRAME_OUTSIDE_CHILDREN; + } } #ifdef NOISY_MAX_ELEMENT_SIZE ListTag(stdout); printf(": maxElementSize=%d,%d desiredSize=%d,%d\n", - aDesiredSize.maxElementSize ? aDesiredSize.maxElementSize->width : 0, - aDesiredSize.maxElementSize ? aDesiredSize.maxElementSize->height : 0, - aDesiredSize.width, aDesiredSize.height); + aMetrics.maxElementSize ? aMetrics.maxElementSize->width : 0, + aMetrics.maxElementSize ? aMetrics.maxElementSize->height : 0, + aMetrics.width, aMetrics.height); #endif - // If we have children that stick outside our box, then remember the - // combined area, because we'll need it later when sizing our view - if (mState & NS_FRAME_OUTSIDE_CHILDREN) { - mCombinedArea = aDesiredSize.mCombinedArea; - } - return rv; } diff --git a/layout/html/base/src/nsAreaFrame.h b/layout/html/base/src/nsAreaFrame.h index 1f4c4b1cbc0e..b291dfab938b 100644 --- a/layout/html/base/src/nsAreaFrame.h +++ b/layout/html/base/src/nsAreaFrame.h @@ -24,7 +24,6 @@ #include "nsBlockFrame.h" #include "nsVoidArray.h" -#include "nsIAreaFrame.h" #include "nsAbsoluteContainingBlock.h" class nsSpaceManager; @@ -44,14 +43,11 @@ struct nsStylePosition; * * @see nsLayoutAtoms::absoluteList */ -class nsAreaFrame : public nsBlockFrame, public nsIAreaFrame +class nsAreaFrame : public nsBlockFrame { public: friend nsresult NS_NewAreaFrame(nsIPresShell* aPresShell, nsIFrame** aResult, PRUint32 aFlags); - // nsISupports - NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); - // nsIFrame NS_IMETHOD Destroy(nsIPresContext* aPresContext); @@ -94,15 +90,11 @@ public: NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; #endif - // nsIAreaFrame - NS_IMETHOD GetPositionedInfo(nscoord& aXMost, nscoord& aYMost) const; - protected: nsAreaFrame(); private: nsAbsoluteContainingBlock mAbsoluteContainer; - nsRect mCombinedArea; }; #endif /* nsAreaFrame_h___ */ diff --git a/layout/html/base/src/nsBlockFrame.cpp b/layout/html/base/src/nsBlockFrame.cpp index d19ad6af826e..777aecf1345d 100644 --- a/layout/html/base/src/nsBlockFrame.cpp +++ b/layout/html/base/src/nsBlockFrame.cpp @@ -1511,7 +1511,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, // children, make sure its big enough to include those that stick // outside the box. if (NS_FRAME_OUTSIDE_CHILDREN & mState) { - nscoord xMost = aMetrics.mCombinedArea.XMost(); + nscoord xMost = aMetrics.mOverflowArea.XMost(); if (xMost > aMetrics.width) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1519,7 +1519,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, #endif aMetrics.width = xMost; } - nscoord yMost = aMetrics.mCombinedArea.YMost(); + nscoord yMost = aMetrics.mOverflowArea.YMost(); if (yMost > aMetrics.height) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1622,10 +1622,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, aMetrics.mCarriedOutBottomMargin); if (mState & NS_FRAME_OUTSIDE_CHILDREN) { printf(" combinedArea={%d,%d,%d,%d}", - aMetrics.mCombinedArea.x, - aMetrics.mCombinedArea.y, - aMetrics.mCombinedArea.width, - aMetrics.mCombinedArea.height); + aMetrics.mOverflowArea.x, + aMetrics.mOverflowArea.y, + aMetrics.mOverflowArea.width, + aMetrics.mOverflowArea.height); } if (aMetrics.maxElementSize) { printf(" maxElementSize=%d,%d", @@ -1969,14 +1969,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, // If the combined area of our children exceeds our bounding box // then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it. - aMetrics.mCombinedArea.x = xa; - aMetrics.mCombinedArea.y = ya; - aMetrics.mCombinedArea.width = xb - xa; - aMetrics.mCombinedArea.height = yb - ya; - if ((aMetrics.mCombinedArea.x < 0) || - (aMetrics.mCombinedArea.y < 0) || - (aMetrics.mCombinedArea.XMost() > aMetrics.width) || - (aMetrics.mCombinedArea.YMost() > aMetrics.height)) { + aMetrics.mOverflowArea.x = xa; + aMetrics.mOverflowArea.y = ya; + aMetrics.mOverflowArea.width = xb - xa; + aMetrics.mOverflowArea.height = yb - ya; + if ((aMetrics.mOverflowArea.x < 0) || + (aMetrics.mOverflowArea.y < 0) || + (aMetrics.mOverflowArea.XMost() > aMetrics.width) || + (aMetrics.mOverflowArea.YMost() > aMetrics.height)) { mState |= NS_FRAME_OUTSIDE_CHILDREN; } else { @@ -2000,6 +2000,7 @@ nsBlockFrame::PrepareChildIncrementalReflow(nsBlockReflowState& aState) // XXX Huh, that's not true anymore. We do cache the width component of // the max-element-size... if (aState.mComputeMaxElementSize) { + printf("BLOCK: marking all child frames dirty...\n"); return PrepareResizeReflow(aState); } @@ -4875,7 +4876,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, aMarginResult.left = m.left; const nsHTMLReflowMetrics& metrics = brc.GetMetrics(); - aCombinedRect = metrics.mCombinedArea; + aCombinedRect = metrics.mOverflowArea; // Set the rect, make sure the view is properly sized and positioned, // and tell the frame we're done reflowing it floater->SizeTo(aState.mPresContext, metrics.width, metrics.height); @@ -4883,7 +4884,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, floater->GetView(aState.mPresContext, &view); if (view) { nsContainerFrame::SyncFrameViewAfterReflow(aState.mPresContext, floater, view, - &metrics.mCombinedArea, + &metrics.mOverflowArea, NS_FRAME_NO_MOVE_VIEW); } floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED); diff --git a/layout/html/base/src/nsBlockReflowContext.cpp b/layout/html/base/src/nsBlockReflowContext.cpp index 103938ae0ade..cb406b64e70a 100644 --- a/layout/html/base/src/nsBlockReflowContext.cpp +++ b/layout/html/base/src/nsBlockReflowContext.cpp @@ -317,11 +317,11 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame, aFrame->GetFrameState(&state); if (0 == (NS_FRAME_OUTSIDE_CHILDREN & state)) { - // Provide combined area for child that doesn't have any - mMetrics.mCombinedArea.x = 0; - mMetrics.mCombinedArea.y = 0; - mMetrics.mCombinedArea.width = mMetrics.width; - mMetrics.mCombinedArea.height = mMetrics.height; + // Provide overflow area for child that doesn't have any + mMetrics.mOverflowArea.x = 0; + mMetrics.mOverflowArea.y = 0; + mMetrics.mOverflowArea.width = mMetrics.width; + mMetrics.mOverflowArea.height = mMetrics.height; } // Now that frame has been reflowed at least one time make sure that @@ -376,8 +376,8 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, nscoord x = mX; nscoord y = mY; // When deciding whether it's an empty paragraph we also need to take into - // account the combined area - if ((0 == mMetrics.height) && (0 == mMetrics.mCombinedArea.height)) { + // account the overflow area + if ((0 == mMetrics.height) && (0 == mMetrics.mOverflowArea.height)) { if (IsHTMLParagraph(mFrame)) { // Special "feature" for HTML compatability - empty paragraphs // collapse into nothingness, including their margins. Signal @@ -432,7 +432,7 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, // Retain combined area information in case we contain a floater // and nothing else. - aCombinedRect = mMetrics.mCombinedArea; + aCombinedRect = mMetrics.mOverflowArea; aCombinedRect.x += x; aCombinedRect.y += y; } @@ -549,10 +549,10 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, // Compute combined-rect in callers coordinate system. The value // returned in the reflow metrics is relative to the child // frame. - aCombinedRect.x = mMetrics.mCombinedArea.x + x; - aCombinedRect.y = mMetrics.mCombinedArea.y + y; - aCombinedRect.width = mMetrics.mCombinedArea.width; - aCombinedRect.height = mMetrics.mCombinedArea.height; + aCombinedRect.x = mMetrics.mOverflowArea.x + x; + aCombinedRect.y = mMetrics.mOverflowArea.y + y; + aCombinedRect.width = mMetrics.mOverflowArea.width; + aCombinedRect.height = mMetrics.mOverflowArea.height; // Now place the frame and complete the reflow process nsContainerFrame::FinishReflowChild(mFrame, mPresContext, mMetrics, x, y, 0); diff --git a/layout/html/base/src/nsBlockReflowState.cpp b/layout/html/base/src/nsBlockReflowState.cpp index d19ad6af826e..777aecf1345d 100644 --- a/layout/html/base/src/nsBlockReflowState.cpp +++ b/layout/html/base/src/nsBlockReflowState.cpp @@ -1511,7 +1511,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, // children, make sure its big enough to include those that stick // outside the box. if (NS_FRAME_OUTSIDE_CHILDREN & mState) { - nscoord xMost = aMetrics.mCombinedArea.XMost(); + nscoord xMost = aMetrics.mOverflowArea.XMost(); if (xMost > aMetrics.width) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1519,7 +1519,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, #endif aMetrics.width = xMost; } - nscoord yMost = aMetrics.mCombinedArea.YMost(); + nscoord yMost = aMetrics.mOverflowArea.YMost(); if (yMost > aMetrics.height) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1622,10 +1622,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, aMetrics.mCarriedOutBottomMargin); if (mState & NS_FRAME_OUTSIDE_CHILDREN) { printf(" combinedArea={%d,%d,%d,%d}", - aMetrics.mCombinedArea.x, - aMetrics.mCombinedArea.y, - aMetrics.mCombinedArea.width, - aMetrics.mCombinedArea.height); + aMetrics.mOverflowArea.x, + aMetrics.mOverflowArea.y, + aMetrics.mOverflowArea.width, + aMetrics.mOverflowArea.height); } if (aMetrics.maxElementSize) { printf(" maxElementSize=%d,%d", @@ -1969,14 +1969,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, // If the combined area of our children exceeds our bounding box // then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it. - aMetrics.mCombinedArea.x = xa; - aMetrics.mCombinedArea.y = ya; - aMetrics.mCombinedArea.width = xb - xa; - aMetrics.mCombinedArea.height = yb - ya; - if ((aMetrics.mCombinedArea.x < 0) || - (aMetrics.mCombinedArea.y < 0) || - (aMetrics.mCombinedArea.XMost() > aMetrics.width) || - (aMetrics.mCombinedArea.YMost() > aMetrics.height)) { + aMetrics.mOverflowArea.x = xa; + aMetrics.mOverflowArea.y = ya; + aMetrics.mOverflowArea.width = xb - xa; + aMetrics.mOverflowArea.height = yb - ya; + if ((aMetrics.mOverflowArea.x < 0) || + (aMetrics.mOverflowArea.y < 0) || + (aMetrics.mOverflowArea.XMost() > aMetrics.width) || + (aMetrics.mOverflowArea.YMost() > aMetrics.height)) { mState |= NS_FRAME_OUTSIDE_CHILDREN; } else { @@ -2000,6 +2000,7 @@ nsBlockFrame::PrepareChildIncrementalReflow(nsBlockReflowState& aState) // XXX Huh, that's not true anymore. We do cache the width component of // the max-element-size... if (aState.mComputeMaxElementSize) { + printf("BLOCK: marking all child frames dirty...\n"); return PrepareResizeReflow(aState); } @@ -4875,7 +4876,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, aMarginResult.left = m.left; const nsHTMLReflowMetrics& metrics = brc.GetMetrics(); - aCombinedRect = metrics.mCombinedArea; + aCombinedRect = metrics.mOverflowArea; // Set the rect, make sure the view is properly sized and positioned, // and tell the frame we're done reflowing it floater->SizeTo(aState.mPresContext, metrics.width, metrics.height); @@ -4883,7 +4884,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, floater->GetView(aState.mPresContext, &view); if (view) { nsContainerFrame::SyncFrameViewAfterReflow(aState.mPresContext, floater, view, - &metrics.mCombinedArea, + &metrics.mOverflowArea, NS_FRAME_NO_MOVE_VIEW); } floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED); diff --git a/layout/html/base/src/nsBlockReflowState.h b/layout/html/base/src/nsBlockReflowState.h index d19ad6af826e..777aecf1345d 100644 --- a/layout/html/base/src/nsBlockReflowState.h +++ b/layout/html/base/src/nsBlockReflowState.h @@ -1511,7 +1511,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, // children, make sure its big enough to include those that stick // outside the box. if (NS_FRAME_OUTSIDE_CHILDREN & mState) { - nscoord xMost = aMetrics.mCombinedArea.XMost(); + nscoord xMost = aMetrics.mOverflowArea.XMost(); if (xMost > aMetrics.width) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1519,7 +1519,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, #endif aMetrics.width = xMost; } - nscoord yMost = aMetrics.mCombinedArea.YMost(); + nscoord yMost = aMetrics.mOverflowArea.YMost(); if (yMost > aMetrics.height) { #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -1622,10 +1622,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, aMetrics.mCarriedOutBottomMargin); if (mState & NS_FRAME_OUTSIDE_CHILDREN) { printf(" combinedArea={%d,%d,%d,%d}", - aMetrics.mCombinedArea.x, - aMetrics.mCombinedArea.y, - aMetrics.mCombinedArea.width, - aMetrics.mCombinedArea.height); + aMetrics.mOverflowArea.x, + aMetrics.mOverflowArea.y, + aMetrics.mOverflowArea.width, + aMetrics.mOverflowArea.height); } if (aMetrics.maxElementSize) { printf(" maxElementSize=%d,%d", @@ -1969,14 +1969,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, // If the combined area of our children exceeds our bounding box // then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it. - aMetrics.mCombinedArea.x = xa; - aMetrics.mCombinedArea.y = ya; - aMetrics.mCombinedArea.width = xb - xa; - aMetrics.mCombinedArea.height = yb - ya; - if ((aMetrics.mCombinedArea.x < 0) || - (aMetrics.mCombinedArea.y < 0) || - (aMetrics.mCombinedArea.XMost() > aMetrics.width) || - (aMetrics.mCombinedArea.YMost() > aMetrics.height)) { + aMetrics.mOverflowArea.x = xa; + aMetrics.mOverflowArea.y = ya; + aMetrics.mOverflowArea.width = xb - xa; + aMetrics.mOverflowArea.height = yb - ya; + if ((aMetrics.mOverflowArea.x < 0) || + (aMetrics.mOverflowArea.y < 0) || + (aMetrics.mOverflowArea.XMost() > aMetrics.width) || + (aMetrics.mOverflowArea.YMost() > aMetrics.height)) { mState |= NS_FRAME_OUTSIDE_CHILDREN; } else { @@ -2000,6 +2000,7 @@ nsBlockFrame::PrepareChildIncrementalReflow(nsBlockReflowState& aState) // XXX Huh, that's not true anymore. We do cache the width component of // the max-element-size... if (aState.mComputeMaxElementSize) { + printf("BLOCK: marking all child frames dirty...\n"); return PrepareResizeReflow(aState); } @@ -4875,7 +4876,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, aMarginResult.left = m.left; const nsHTMLReflowMetrics& metrics = brc.GetMetrics(); - aCombinedRect = metrics.mCombinedArea; + aCombinedRect = metrics.mOverflowArea; // Set the rect, make sure the view is properly sized and positioned, // and tell the frame we're done reflowing it floater->SizeTo(aState.mPresContext, metrics.width, metrics.height); @@ -4883,7 +4884,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState, floater->GetView(aState.mPresContext, &view); if (view) { nsContainerFrame::SyncFrameViewAfterReflow(aState.mPresContext, floater, view, - &metrics.mCombinedArea, + &metrics.mOverflowArea, NS_FRAME_NO_MOVE_VIEW); } floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED); diff --git a/layout/html/base/src/nsContainerFrame.cpp b/layout/html/base/src/nsContainerFrame.cpp index ccf3222940ac..7db54d6150f7 100644 --- a/layout/html/base/src/nsContainerFrame.cpp +++ b/layout/html/base/src/nsContainerFrame.cpp @@ -718,7 +718,7 @@ nsContainerFrame::FinishReflowChild(nsIFrame* aKidFrame, // Make sure the frame's view is properly sized and positioned and has // things like opacity correct SyncFrameViewAfterReflow(aPresContext, aKidFrame, view, - &aDesiredSize.mCombinedArea, + &aDesiredSize.mOverflowArea, aFlags); } else if (0 == (aFlags & NS_FRAME_NO_MOVE_CHILD_VIEWS)) { diff --git a/layout/html/base/src/nsFrame.cpp b/layout/html/base/src/nsFrame.cpp index 771d4c60b949..4b3c8a181542 100644 --- a/layout/html/base/src/nsFrame.cpp +++ b/layout/html/base/src/nsFrame.cpp @@ -1567,10 +1567,10 @@ nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState, aMetrics.ascent = 0; aMetrics.descent = 0; aMetrics.mCarriedOutBottomMargin = 0; - aMetrics.mCombinedArea.x = 0; - aMetrics.mCombinedArea.y = 0; - aMetrics.mCombinedArea.width = 0; - aMetrics.mCombinedArea.height = 0; + aMetrics.mOverflowArea.x = 0; + aMetrics.mOverflowArea.y = 0; + aMetrics.mOverflowArea.width = 0; + aMetrics.mOverflowArea.height = 0; if (aMetrics.maxElementSize) { aMetrics.maxElementSize->width = 0; aMetrics.maxElementSize->height = 0; diff --git a/layout/html/base/src/nsGfxScrollFrame.cpp b/layout/html/base/src/nsGfxScrollFrame.cpp index 79e00a712146..8719d89d8df0 100644 --- a/layout/html/base/src/nsGfxScrollFrame.cpp +++ b/layout/html/base/src/nsGfxScrollFrame.cpp @@ -34,7 +34,6 @@ #include "nsCSSRendering.h" #include "nsIScrollableView.h" #include "nsWidgetsCID.h" -#include "nsIAreaFrame.h" #include "nsGfxScrollFrame.h" #include "nsLayoutAtoms.h" #include "nsIXMLContent.h" @@ -54,7 +53,6 @@ static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID); -static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); static NS_DEFINE_IID(kIAnonymousContentCreatorIID, NS_IANONYMOUS_CONTENT_CREATOR_IID); @@ -893,23 +891,8 @@ nsGfxScrollFrameInner::CalculateChildTotalSize(nsIFrame* aKidFrame, nsFrameState kidState; aKidFrame->GetFrameState(&kidState); if (NS_FRAME_OUTSIDE_CHILDREN & kidState) { - aKidReflowMetrics.width = aKidReflowMetrics.mCombinedArea.width; - aKidReflowMetrics.height = aKidReflowMetrics.mCombinedArea.height; - } - - // If it's an area frame, then get the total size which includes the - // space taken up by absolutely positioned child elements - nsIAreaFrame* areaFrame; - if (NS_SUCCEEDED(aKidFrame->QueryInterface(kAreaFrameIID, (void**)&areaFrame))) { - nscoord xMost, yMost; - - areaFrame->GetPositionedInfo(xMost, yMost); - if (xMost > aKidReflowMetrics.width) { - aKidReflowMetrics.width = xMost; - } - if (yMost > aKidReflowMetrics.height) { - aKidReflowMetrics.height = yMost; - } + aKidReflowMetrics.width = aKidReflowMetrics.mOverflowArea.width; + aKidReflowMetrics.height = aKidReflowMetrics.mOverflowArea.height; } return NS_OK; diff --git a/layout/html/base/src/nsHTMLFrame.cpp b/layout/html/base/src/nsHTMLFrame.cpp index e78033ea415b..e3d62879b6c7 100644 --- a/layout/html/base/src/nsHTMLFrame.cpp +++ b/layout/html/base/src/nsHTMLFrame.cpp @@ -41,12 +41,10 @@ #include "nsIEventStateManager.h" #include "nsIDeviceContext.h" #include "nsIScrollableView.h" -#include "nsIAreaFrame.h" #include "nsLayoutAtoms.h" #include "nsIPresShell.h" // Interface IDs -static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID); static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); @@ -345,36 +343,16 @@ RootFrame::Reflow(nsIPresContext* aPresContext, nscoord paddingEdgeX = kidDesiredSize.width - border.right; nscoord paddingEdgeY = kidDesiredSize.height - border.bottom; - if (kidDesiredSize.mCombinedArea.XMost() > paddingEdgeX) { - kidDesiredSize.width = kidDesiredSize.mCombinedArea.XMost() + + if (kidDesiredSize.mOverflowArea.XMost() > paddingEdgeX) { + kidDesiredSize.width = kidDesiredSize.mOverflowArea.XMost() + border.right; } - if (kidDesiredSize.mCombinedArea.YMost() > paddingEdgeY) { - kidDesiredSize.height = kidDesiredSize.mCombinedArea.YMost() + + if (kidDesiredSize.mOverflowArea.YMost() > paddingEdgeY) { + kidDesiredSize.height = kidDesiredSize.mOverflowArea.YMost() + border.bottom; } } - // XXX It would be nice if this were also part of the reflow metrics... - nsIAreaFrame* areaFrame; - if (NS_SUCCEEDED(kidFrame->QueryInterface(kAreaFrameIID, (void**)&areaFrame))) { - // Get the x-most and y-most of the absolutely positioned children - nscoord positionedXMost, positionedYMost; - areaFrame->GetPositionedInfo(positionedXMost, positionedYMost); - - // The background covers the content area and padding area, so check - // for children sticking outside the padding edge - nscoord paddingEdgeX = kidDesiredSize.width - border.right; - nscoord paddingEdgeY = kidDesiredSize.height - border.bottom; - - if (positionedXMost > paddingEdgeX) { - kidDesiredSize.width = positionedXMost + border.right; - } - if (positionedYMost > paddingEdgeY) { - kidDesiredSize.height = positionedYMost + border.bottom; - } - } - // If our height is fixed, then make sure the child frame plus its top and // bottom margin is at least that high as well... if (NS_AUTOHEIGHT != aReflowState.mComputedHeight) { diff --git a/layout/html/base/src/nsHTMLIIDs.cpp b/layout/html/base/src/nsHTMLIIDs.cpp index cbe4fb8a3d3a..9662ae92d106 100644 --- a/layout/html/base/src/nsHTMLIIDs.cpp +++ b/layout/html/base/src/nsHTMLIIDs.cpp @@ -23,10 +23,8 @@ #include "nsIHTMLContent.h" #include "nsIPageSequenceFrame.h" #include "nsITextContent.h" -#include "nsIAreaFrame.h" const nsIID kIHTMLContentIID = NS_IHTMLCONTENT_IID; const nsIID kIPageSequenceFrameIID = NS_IPAGESEQUENCEFRAME_IID; const nsIID kIStyledContentIID = NS_ISTYLEDCONTENT_IID; const nsIID kITextContentIID = NS_ITEXT_CONTENT_IID; -const nsIID kIAreaFrameIID = NS_IAREAFRAME_IID; diff --git a/layout/html/base/src/nsIAreaFrame.h b/layout/html/base/src/nsIAreaFrame.h deleted file mode 100644 index 10a13303b86e..000000000000 --- a/layout/html/base/src/nsIAreaFrame.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * The contents of this file are subject to the Netscape Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - */ -#ifndef nsIAreaFrame_h___ -#define nsIAreaFrame_h___ - -#include "nsIFrame.h" - -// 7327a0a0-bc8d-11d1-8539-00a02468fab6 -#define NS_IAREAFRAME_IID \ - { 0xa6cf90de, 0x15b3, 0x11d2, {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} - -/** - * An interface for managing anchored items. Note that this interface is not - * an nsISupports interface, and therefore you cannot QueryInterface() back - */ -class nsIAreaFrame -{ -public: - /** - * Returns the x-most and y-most for the child absoolutely positioned - * elements - */ - NS_IMETHOD GetPositionedInfo(nscoord& aXMost, nscoord& aYMost) const = 0; -}; - -#endif /* nsIAreaFrame_h___ */ diff --git a/layout/html/base/src/nsInlineFrame.cpp b/layout/html/base/src/nsInlineFrame.cpp index f6b68a5e592d..326470af89b4 100644 --- a/layout/html/base/src/nsInlineFrame.cpp +++ b/layout/html/base/src/nsInlineFrame.cpp @@ -461,12 +461,12 @@ nsInlineFrame::ReflowFrames(nsIPresContext* aPresContext, } } - // For now our combined area is zero. The real value will be + // For now our overflow area is zero. The real value will be // computed during vertical alignment of the line we are on. - aMetrics.mCombinedArea.x = 0; - aMetrics.mCombinedArea.y = 0; - aMetrics.mCombinedArea.width = aMetrics.width; - aMetrics.mCombinedArea.height = aMetrics.height; + aMetrics.mOverflowArea.x = 0; + aMetrics.mOverflowArea.y = 0; + aMetrics.mOverflowArea.width = aMetrics.width; + aMetrics.mOverflowArea.height = aMetrics.height; #ifdef NOISY_FINAL_SIZE ListTag(stdout); @@ -973,12 +973,13 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext, if (eReflowReason_Incremental == aReflowState.reason) { // Give the absolute positioning code a chance to handle it PRBool handled; + nsRect childBounds; nscoord containingBlockWidth = -1; nscoord containingBlockHeight = -1; mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, containingBlockWidth, containingBlockHeight, - handled); + handled, childBounds); // If the incremental reflow command was handled by the absolute positioning // code, then we're all done @@ -989,7 +990,25 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowState reflowState(aReflowState); reflowState.reason = eReflowReason_Resize; reflowState.reflowCommand = nsnull; - return nsInlineFrame::Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + rv = nsInlineFrame::Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + + // XXX Although this seems like the correct thing to do the line layout + // code seems to reset the NS_FRAME_OUTSIDE_CHILDREN and so it is ignored +#if 0 + // Factor the absolutely positioned child bounds into the overflow area + aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds); + + // Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly + if ((aDesiredSize.mOverflowArea.x < 0) || + (aDesiredSize.mOverflowArea.y < 0) || + (aDesiredSize.mOverflowArea.XMost() > aDesiredSize.width) || + (aDesiredSize.mOverflowArea.YMost() > aDesiredSize.height)) { + mState |= NS_FRAME_OUTSIDE_CHILDREN; + } else { + mState &= ~NS_FRAME_OUTSIDE_CHILDREN; + } +#endif + return rv; } } @@ -1001,9 +1020,28 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext, if (NS_SUCCEEDED(rv)) { nscoord containingBlockWidth = -1; nscoord containingBlockHeight = -1; + nsRect childBounds; rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, - containingBlockWidth, containingBlockHeight); + containingBlockWidth, containingBlockHeight, + childBounds); + + // XXX Although this seems like the correct thing to do the line layout + // code seems to reset the NS_FRAME_OUTSIDE_CHILDREN and so it is ignored +#if 0 + // Factor the absolutely positioned child bounds into the overflow area + aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds); + + // Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly + if ((aDesiredSize.mOverflowArea.x < 0) || + (aDesiredSize.mOverflowArea.y < 0) || + (aDesiredSize.mOverflowArea.XMost() > aDesiredSize.width) || + (aDesiredSize.mOverflowArea.YMost() > aDesiredSize.height)) { + mState |= NS_FRAME_OUTSIDE_CHILDREN; + } else { + mState &= ~NS_FRAME_OUTSIDE_CHILDREN; + } +#endif } return rv; diff --git a/layout/html/base/src/nsLineLayout.cpp b/layout/html/base/src/nsLineLayout.cpp index b2c9ef2bbb4d..dd28f41c7cfb 100644 --- a/layout/html/base/src/nsLineLayout.cpp +++ b/layout/html/base/src/nsLineLayout.cpp @@ -1062,7 +1062,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, aFrame->GetFrameState(&state); if (NS_FRAME_OUTSIDE_CHILDREN & state) { - pfd->mCombinedArea = metrics.mCombinedArea; + pfd->mCombinedArea = metrics.mOverflowArea; } else { pfd->mCombinedArea.x = 0; @@ -1480,7 +1480,7 @@ nsLineLayout::AddBulletFrame(nsIFrame* aFrame, // Note: y value will be updated during vertical alignment aFrame->GetRect(pfd->mBounds); - pfd->mCombinedArea = aMetrics.mCombinedArea; + pfd->mCombinedArea = aMetrics.mOverflowArea; if (mComputeMaxElementSize) { pfd->mMaxElementSize.SizeTo(aMetrics.width, aMetrics.height); } diff --git a/layout/html/base/src/nsScrollFrame.cpp b/layout/html/base/src/nsScrollFrame.cpp index a62959815eda..c80f9319f80f 100644 --- a/layout/html/base/src/nsScrollFrame.cpp +++ b/layout/html/base/src/nsScrollFrame.cpp @@ -34,7 +34,6 @@ #include "nsCSSRendering.h" #include "nsIScrollableView.h" #include "nsWidgetsCID.h" -#include "nsIAreaFrame.h" #include "nsScrollFrame.h" #include "nsLayoutAtoms.h" #include "nsIWebShell.h" @@ -50,7 +49,6 @@ static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID); -static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); //---------------------------------------------------------------------- @@ -437,23 +435,8 @@ nsScrollFrame::CalculateChildTotalSize(nsIFrame* aKidFrame, nsFrameState kidState; aKidFrame->GetFrameState(&kidState); if (NS_FRAME_OUTSIDE_CHILDREN & kidState) { - aKidReflowMetrics.width = aKidReflowMetrics.mCombinedArea.width; - aKidReflowMetrics.height = aKidReflowMetrics.mCombinedArea.height; - } - - // If it's an area frame, then get the total size which includes the - // space taken up by absolutely positioned child elements - nsIAreaFrame* areaFrame; - if (NS_SUCCEEDED(aKidFrame->QueryInterface(kAreaFrameIID, (void**)&areaFrame))) { - nscoord xMost, yMost; - - areaFrame->GetPositionedInfo(xMost, yMost); - if (xMost > aKidReflowMetrics.width) { - aKidReflowMetrics.width = xMost; - } - if (yMost > aKidReflowMetrics.height) { - aKidReflowMetrics.height = yMost; - } + aKidReflowMetrics.width = aKidReflowMetrics.mOverflowArea.width; + aKidReflowMetrics.height = aKidReflowMetrics.mOverflowArea.height; } return NS_OK; diff --git a/layout/html/base/src/nsScrollPortFrame.cpp b/layout/html/base/src/nsScrollPortFrame.cpp index f9f8de5f8b3f..7d8c8ad3b3cc 100644 --- a/layout/html/base/src/nsScrollPortFrame.cpp +++ b/layout/html/base/src/nsScrollPortFrame.cpp @@ -34,7 +34,6 @@ #include "nsCSSRendering.h" #include "nsIScrollableView.h" #include "nsWidgetsCID.h" -#include "nsIAreaFrame.h" #include "nsScrollPortFrame.h" #include "nsLayoutAtoms.h" #include "nsIBox.h" @@ -58,7 +57,6 @@ static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID); -static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); //---------------------------------------------------------------------- @@ -311,23 +309,8 @@ nsScrollPortFrame::CalculateChildTotalSize(nsIFrame* aKidFrame, nsFrameState kidState; aKidFrame->GetFrameState(&kidState); if (NS_FRAME_OUTSIDE_CHILDREN & kidState) { - aKidReflowMetrics.width = aKidReflowMetrics.mCombinedArea.width; - aKidReflowMetrics.height = aKidReflowMetrics.mCombinedArea.height; - } - - // If it's an area frame, then get the total size which includes the - // space taken up by absolutely positioned child elements - nsIAreaFrame* areaFrame; - if (NS_SUCCEEDED(aKidFrame->QueryInterface(kAreaFrameIID, (void**)&areaFrame))) { - nscoord xMost, yMost; - - areaFrame->GetPositionedInfo(xMost, yMost); - if (xMost > aKidReflowMetrics.width) { - aKidReflowMetrics.width = xMost; - } - if (yMost > aKidReflowMetrics.height) { - aKidReflowMetrics.height = yMost; - } + aKidReflowMetrics.width = aKidReflowMetrics.mOverflowArea.width; + aKidReflowMetrics.height = aKidReflowMetrics.mOverflowArea.height; } return NS_OK; diff --git a/layout/html/base/src/nsSelectsAreaFrame.cpp b/layout/html/base/src/nsSelectsAreaFrame.cpp index fd4ed94424e4..28c9b6338c6d 100644 --- a/layout/html/base/src/nsSelectsAreaFrame.cpp +++ b/layout/html/base/src/nsSelectsAreaFrame.cpp @@ -23,9 +23,6 @@ #include "nsCOMPtr.h" #include "nsIDOMHTMLOptionElement.h" #include "nsIContent.h" -#include "nsIAreaFrame.h" - -static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID); nsresult NS_NewSelectsAreaFrame(nsIPresShell* aShell, nsIFrame** aNewFrame, PRUint32 aFlags) diff --git a/layout/html/base/src/nsViewportFrame.cpp b/layout/html/base/src/nsViewportFrame.cpp index 22045b584b3b..83ac155d6ff2 100644 --- a/layout/html/base/src/nsViewportFrame.cpp +++ b/layout/html/base/src/nsViewportFrame.cpp @@ -375,7 +375,7 @@ ViewportFrame::ReflowFixedFrame(nsIPresContext* aPresContext, // Size and position the view and set its opacity, visibility, content // transparency, and clip nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame, kidView, - &kidDesiredSize.mCombinedArea); + &kidDesiredSize.mOverflowArea); aKidFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); return rv; } diff --git a/layout/xul/base/src/nsBoxFrame.cpp b/layout/xul/base/src/nsBoxFrame.cpp index 5164794cdd1b..7829825582c1 100644 --- a/layout/xul/base/src/nsBoxFrame.cpp +++ b/layout/xul/base/src/nsBoxFrame.cpp @@ -1130,8 +1130,8 @@ nsBoxFrame::FlowChildAt(nsIFrame* childFrame, // printf("width: %d, height: %d\n", desiredSize.mCombinedArea.width, desiredSize.mCombinedArea.height); if (kidState & NS_FRAME_OUTSIDE_CHILDREN) { - desiredSize.width = desiredSize.mCombinedArea.width; - desiredSize.height = desiredSize.mCombinedArea.height; + desiredSize.width = desiredSize.mOverflowArea.width; + desiredSize.height = desiredSize.mOverflowArea.height; }