fixed nsbeta2+ bugs 42138 35772 37657 38157 40283 35964

r=waterson, rods
This commit is contained in:
buster%netscape.com 2000-06-14 23:15:59 +00:00
Родитель d01d8617f8
Коммит 683cb37e34
12 изменённых файлов: 362 добавлений и 210 удалений

Просмотреть файл

@ -165,7 +165,13 @@ InitDebugFlags()
#endif
//#define FIX_BUG_38157 needs review before it can be enabled
#define FIX_BUG_38157
#define FIX_BUG_37657
// add in a sanity check for absurdly deep frame trees. See bug 42138
// can't just use IsFrameTreeTooDeep() because that method has side effects we don't want
static PRInt32 gRenumberListDepthCounter;
#define MAX_DEPTH_FOR_LIST_RENUMBERING 200 // 200 open displayable tags is pretty unrealistic
//----------------------------------------------------------------------
@ -4263,21 +4269,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
// the available width is the smaller of the widths given by:
// a) the space manager, accounting for floaters impacting this line
// b) the parent frame's computed width
// part 1 of a possible fix for 38157
#ifdef FIX_BUG_38157
const nsMargin& margin = aState.Margin();
nscoord availContentWidth = aState.mReflowState.availableWidth;
if (NS_UNCONSTRAINEDSIZE != availContentWidth) {
availContentWidth -= (borderPadding.left + borderPadding.right) +
(margin.left + margin.right);
}
nscoord availWidth = PR_MIN(aState.mAvailSpaceRect.width, availContentWidth);
#else
nscoord availWidth = aState.mAvailSpaceRect.width;
#endif
nscoord availHeight;
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
availHeight = NS_UNCONSTRAINEDSIZE;
@ -4446,6 +4438,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
// Send post-reflow notification
aState.mPrevChild = aFrame;
/* XXX
This is where we need to add logic to handle some odd behavior.
For one thing, we should usually place at least one thing next
to a left floater, even when that floater takes up all the width on a line.
see bug 22496
*/
// Process the child frames reflow status. There are 5 cases:
// complete, not-complete, break-before, break-after-complete,
// break-after-not-complete. There are two situations: we are a
@ -6999,6 +6998,7 @@ nsBlockFrame::FrameStartsCounterScope(nsIFrame* aFrame)
void
nsBlockFrame::RenumberLists(nsIPresContext* aPresContext)
{
gRenumberListDepthCounter = 0; // reset the sanity check counter
if (!FrameStartsCounterScope(this)) {
// If this frame doesn't start a counter scope then we don't need
// to renumber child list items.
@ -7090,6 +7090,11 @@ nsBlockFrame::RenumberListsFor(nsIPresContext* aPresContext,
nsIFrame* aKid,
PRInt32* aOrdinal)
{
// add in a sanity check for absurdly deep frame trees. See bug 42138
gRenumberListDepthCounter++;
if (MAX_DEPTH_FOR_LIST_RENUMBERING < gRenumberListDepthCounter)
return PR_FALSE;
PRBool kidRenumberedABullet = PR_FALSE;
// If the frame is a list-item and the frame implements our

Просмотреть файл

@ -31,6 +31,9 @@
#include "nsHTMLContainerFrame.h"
#include "nsBlockFrame.h"
#include "nsIDOMHTMLParagraphElement.h"
#include "nsIDOMHTMLTableCellElement.h"
#include "nsIDOMHTMLBodyElement.h"
#include "nsLayoutAtoms.h"
#include "nsCOMPtr.h"
#ifdef NS_DEBUG
@ -75,6 +78,43 @@ nsBlockReflowContext::IsHTMLParagraph(nsIFrame* aFrame)
return result;
}
PRBool
nsBlockReflowContext::IsFirstSignificantChild(const nsIFrame* aParentFrame, const nsIFrame* aChildFrame) const
{
NS_ASSERTION(aParentFrame && aChildFrame, "bad args");
if (!aParentFrame || !aChildFrame) return PR_FALSE;
nsIFrame *child;
aParentFrame->FirstChild((nsIPresContext *)(&mPresContext), nsnull, &child);
while (child)
{
if (aChildFrame == child) {
return PR_TRUE; // we found aChildFrame, and we haven't yet encountered a geometrically significant frame
}
nsSize size;
child->GetSize(size);
if (size.width || size.height) {
return PR_FALSE; // we found a geometrically significant frame and it wasn't aChildFrame
}
child->GetNextSibling(&child);
}
return PR_FALSE; //aChildFrame is not in the default child list of aParentFrame
}
PRBool IsCollapsingBlockParentFrame(const nsIFrame* aFrame)
{
if (!aFrame) return PR_FALSE;
nsCOMPtr<nsIAtom> frameType;
aFrame->GetFrameType(getter_AddRefs(frameType));
if (frameType==nsLayoutAtoms::blockFrame ||
frameType==nsLayoutAtoms::areaFrame ||
frameType==nsLayoutAtoms::tableCellFrame ||
frameType==nsLayoutAtoms::tableCaptionFrame) {
return PR_TRUE;
}
return PR_FALSE;
}
nscoord
nsBlockReflowContext::ComputeCollapsedTopMargin(nsIPresContext* aPresContext,
nsHTMLReflowState& aRS)
@ -310,7 +350,8 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
// XXX subtract out vertical margin?
nsSize availSpace(aSpace.width, aSpace.height);
nsHTMLReflowState reflowState(mPresContext, mOuterReflowState, aFrame,
availSpace, reason);
availSpace, aSpace.width, aSpace.height);
reflowState.reason = reason;
aComputedOffsets = reflowState.mComputedOffsets;
reflowState.mLineLayout = nsnull;
if (!aIsAdjacentWithTop) {
@ -645,22 +686,38 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
nscoord y = mY;
// When deciding whether it's an empty paragraph we also need to take into
// account the overflow area
if ((0 == mMetrics.height) && (0 == mMetrics.mOverflowArea.height)) {
if ((0 == mMetrics.height) && (0 == mMetrics.mOverflowArea.height))
{
PRBool handled = PR_FALSE;
if (IsHTMLParagraph(mFrame)) {
// Special "feature" for HTML compatability - empty paragraphs
// collapse into nothingness, including their margins. Signal
// the special nature here by returning -1.
*aBottomMarginResult = -1;
// In general, we turn off this behavior due to re-interpretation of the vague HTML 4 spec.
// See bug 35772. However, we do need this behavior for <P> inside of table cells,
// floaters, and positioned elements
nsIFrame *parent;
mFrame->GetParent(&parent);
if (parent)
{
if (IsCollapsingBlockParentFrame(mFrame) &&
IsFirstSignificantChild(parent, mFrame))
{
handled = PR_TRUE;
*aBottomMarginResult = -1;
#ifdef NOISY_VERTICAL_MARGINS
printf(" ");
nsFrame::ListTag(stdout, mOuterReflowState.frame);
printf(": ");
nsFrame::ListTag(stdout, mFrame);
printf(" -- zapping top & bottom margin; y=%d spaceY=%d\n",
y, mSpace.y);
printf(" ");
nsFrame::ListTag(stdout, mOuterReflowState.frame);
printf(": ");
nsFrame::ListTag(stdout, mFrame);
printf(" -- zapping top & bottom margin; y=%d spaceY=%d\n",
y, mSpace.y);
#endif
}
}
}
else {
if (!handled)
{
// Collapse the bottom margin with the top margin that was already
// applied.
nscoord newBottomMargin = MaxMargin(collapsedBottomMargin, mTopMargin);
@ -675,19 +732,6 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
#endif
}
#if XXX
// For empty blocks we revert the y coordinate back so that the
// top margin is no longer applied.
nsBlockFrame* bf;
nsresult rv = mFrame->QueryInterface(kBlockFrameCID, (void**)&bf);
if (NS_SUCCEEDED(rv)) {
// XXX This isn't good enough. What if the floater was placed
// downward, just below another floater?
nscoord dy = mSpace.y - mY;
bf->MoveInSpaceManager(mPresContext, mOuterReflowState.mSpaceManager,
dy);
}
#endif
y = mSpace.y;
// Empty blocks do not have anything special done to them and they
@ -707,7 +751,24 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
else {
// See if the frame fit. If its the first frame then it always
// fits.
if (aForceFit || (y + mMetrics.height <= mSpace.YMost())) {
if (aForceFit || (y + mMetrics.height <= mSpace.YMost()))
{
// if it's a <P> and it's parent is special, then collapse the <P>'s top margin
if (IsHTMLParagraph(mFrame)) {
// Special "feature" for HTML compatability - a paragraph's
// top margin collapses into nothingness, inside of certain containers.
nsIFrame *parent;
mFrame->GetParent(&parent);
if (parent)
{
if (IsCollapsingBlockParentFrame(mFrame) &&
IsFirstSignificantChild(parent, mFrame))
{
y=0;
}
}
}
// Calculate the actual x-offset and left and right margin
nsBlockHorizontalAlign align;
@ -743,28 +804,6 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
// Now place the frame and complete the reflow process
nsContainerFrame::FinishReflowChild(mFrame, mPresContext, mMetrics, x, y, 0);
// XXX obsolete, i believe...
#if 0
// If the block frame ended up moving then we need to slide
// anything inside of it that impacts the space manager
// (otherwise the impacted space in the space manager will be
// out of sync with where the frames really are).
nscoord dx = x - mX;
nscoord dy = y - mY;
if ((0 != dx) || (0 != dy)) {
nsIHTMLReflow* htmlReflow;
nsresult rv;
rv = mFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow);
if (NS_SUCCEEDED(rv)) {
// If the child has any floaters that impact the space manager,
// slide them now
htmlReflow->MoveInSpaceManager(mPresContext,
mOuterReflowState.mSpaceManager,
dx, dy);
}
}
#endif
// Adjust the max-element-size in the metrics to take into
// account the margins around the block element. Note that we
// use the collapsed top and bottom margin values.

Просмотреть файл

@ -114,6 +114,12 @@ public:
static PRBool IsHTMLParagraph(nsIFrame* aFrame);
/** return PR_TRUE if aChildFrame is the first geometrically significant child of aParentFrame
* to be considered significant, a frame must have both width and height != 0
* if aChildFrame is not in the default child list of aParentFrame, we return PR_FALSE
*/
PRBool nsBlockReflowContext::IsFirstSignificantChild(const nsIFrame* aParentFrame, const nsIFrame* aChildFrame) const;
static nscoord ComputeCollapsedTopMargin(nsIPresContext* aPresContext,
nsHTMLReflowState& aRS);

Просмотреть файл

@ -165,7 +165,13 @@ InitDebugFlags()
#endif
//#define FIX_BUG_38157 needs review before it can be enabled
#define FIX_BUG_38157
#define FIX_BUG_37657
// add in a sanity check for absurdly deep frame trees. See bug 42138
// can't just use IsFrameTreeTooDeep() because that method has side effects we don't want
static PRInt32 gRenumberListDepthCounter;
#define MAX_DEPTH_FOR_LIST_RENUMBERING 200 // 200 open displayable tags is pretty unrealistic
//----------------------------------------------------------------------
@ -4263,21 +4269,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
// the available width is the smaller of the widths given by:
// a) the space manager, accounting for floaters impacting this line
// b) the parent frame's computed width
// part 1 of a possible fix for 38157
#ifdef FIX_BUG_38157
const nsMargin& margin = aState.Margin();
nscoord availContentWidth = aState.mReflowState.availableWidth;
if (NS_UNCONSTRAINEDSIZE != availContentWidth) {
availContentWidth -= (borderPadding.left + borderPadding.right) +
(margin.left + margin.right);
}
nscoord availWidth = PR_MIN(aState.mAvailSpaceRect.width, availContentWidth);
#else
nscoord availWidth = aState.mAvailSpaceRect.width;
#endif
nscoord availHeight;
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
availHeight = NS_UNCONSTRAINEDSIZE;
@ -4446,6 +4438,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
// Send post-reflow notification
aState.mPrevChild = aFrame;
/* XXX
This is where we need to add logic to handle some odd behavior.
For one thing, we should usually place at least one thing next
to a left floater, even when that floater takes up all the width on a line.
see bug 22496
*/
// Process the child frames reflow status. There are 5 cases:
// complete, not-complete, break-before, break-after-complete,
// break-after-not-complete. There are two situations: we are a
@ -6999,6 +6998,7 @@ nsBlockFrame::FrameStartsCounterScope(nsIFrame* aFrame)
void
nsBlockFrame::RenumberLists(nsIPresContext* aPresContext)
{
gRenumberListDepthCounter = 0; // reset the sanity check counter
if (!FrameStartsCounterScope(this)) {
// If this frame doesn't start a counter scope then we don't need
// to renumber child list items.
@ -7090,6 +7090,11 @@ nsBlockFrame::RenumberListsFor(nsIPresContext* aPresContext,
nsIFrame* aKid,
PRInt32* aOrdinal)
{
// add in a sanity check for absurdly deep frame trees. See bug 42138
gRenumberListDepthCounter++;
if (MAX_DEPTH_FOR_LIST_RENUMBERING < gRenumberListDepthCounter)
return PR_FALSE;
PRBool kidRenumberedABullet = PR_FALSE;
// If the frame is a list-item and the frame implements our

Просмотреть файл

@ -165,7 +165,13 @@ InitDebugFlags()
#endif
//#define FIX_BUG_38157 needs review before it can be enabled
#define FIX_BUG_38157
#define FIX_BUG_37657
// add in a sanity check for absurdly deep frame trees. See bug 42138
// can't just use IsFrameTreeTooDeep() because that method has side effects we don't want
static PRInt32 gRenumberListDepthCounter;
#define MAX_DEPTH_FOR_LIST_RENUMBERING 200 // 200 open displayable tags is pretty unrealistic
//----------------------------------------------------------------------
@ -4263,21 +4269,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
// the available width is the smaller of the widths given by:
// a) the space manager, accounting for floaters impacting this line
// b) the parent frame's computed width
// part 1 of a possible fix for 38157
#ifdef FIX_BUG_38157
const nsMargin& margin = aState.Margin();
nscoord availContentWidth = aState.mReflowState.availableWidth;
if (NS_UNCONSTRAINEDSIZE != availContentWidth) {
availContentWidth -= (borderPadding.left + borderPadding.right) +
(margin.left + margin.right);
}
nscoord availWidth = PR_MIN(aState.mAvailSpaceRect.width, availContentWidth);
#else
nscoord availWidth = aState.mAvailSpaceRect.width;
#endif
nscoord availHeight;
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
availHeight = NS_UNCONSTRAINEDSIZE;
@ -4446,6 +4438,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
// Send post-reflow notification
aState.mPrevChild = aFrame;
/* XXX
This is where we need to add logic to handle some odd behavior.
For one thing, we should usually place at least one thing next
to a left floater, even when that floater takes up all the width on a line.
see bug 22496
*/
// Process the child frames reflow status. There are 5 cases:
// complete, not-complete, break-before, break-after-complete,
// break-after-not-complete. There are two situations: we are a
@ -6999,6 +6998,7 @@ nsBlockFrame::FrameStartsCounterScope(nsIFrame* aFrame)
void
nsBlockFrame::RenumberLists(nsIPresContext* aPresContext)
{
gRenumberListDepthCounter = 0; // reset the sanity check counter
if (!FrameStartsCounterScope(this)) {
// If this frame doesn't start a counter scope then we don't need
// to renumber child list items.
@ -7090,6 +7090,11 @@ nsBlockFrame::RenumberListsFor(nsIPresContext* aPresContext,
nsIFrame* aKid,
PRInt32* aOrdinal)
{
// add in a sanity check for absurdly deep frame trees. See bug 42138
gRenumberListDepthCounter++;
if (MAX_DEPTH_FOR_LIST_RENUMBERING < gRenumberListDepthCounter)
return PR_FALSE;
PRBool kidRenumberedABullet = PR_FALSE;
// If the frame is a list-item and the frame implements our

Просмотреть файл

@ -558,19 +558,30 @@ nsLineLayout::EndSpan(nsIFrame* aFrame,
width = psd->mX - psd->mLeftEdge;
PerFrameData* pfd = psd->mFirstFrame;
while (nsnull != pfd) {
if (pfd->mBounds.height > maxHeight) maxHeight = pfd->mBounds.height;
/* there's one oddball case we need to guard against
* if we're reflowed with NS_UNCONSTRAINEDSIZE
* then the last frame will not contribute to the max element size height
* if it is a text frame that only contains whitespace
*/
if (NS_UNCONSTRAINEDSIZE != psd->mRightEdge || // it's not an unconstrained reflow
pfd->mNext || // or it's not the last frame in the span
!pfd->GetFlag(PFD_ISTEXTFRAME) || // or it's not a text frame
pfd->GetFlag(PFD_ISNONWHITESPACETEXTFRAME) // or it contains something other than whitespace
) {
if (pfd->mBounds.height > maxHeight) maxHeight = pfd->mBounds.height;
// Compute max-element-size if necessary
if (aMaxElementSize) {
nscoord mw = pfd->mMaxElementSize.width +
pfd->mMargin.left + pfd->mMargin.right;
if (maxElementWidth < mw) {
maxElementWidth = mw;
}
nscoord mh = pfd->mMaxElementSize.height +
pfd->mMargin.top + pfd->mMargin.bottom;
if (maxElementHeight < mh) {
maxElementHeight = mh;
// Compute max-element-size if necessary
if (aMaxElementSize) {
nscoord mw = pfd->mMaxElementSize.width +
pfd->mMargin.left + pfd->mMargin.right;
if (maxElementWidth < mw) {
maxElementWidth = mw;
}
nscoord mh = pfd->mMaxElementSize.height +
pfd->mMargin.top + pfd->mMargin.bottom;
if (maxElementHeight < mh) {
maxElementHeight = mh;
}
}
}
pfd = pfd->mNext;
@ -1627,8 +1638,13 @@ nsLineLayout::VerticalAlignFrames(nsLineBox* aLineBox,
if (mComputeMaxElementSize) {
nscoord mw = pfd->mMaxElementSize.width +
pfd->mMargin.left + pfd->mMargin.right;
if (maxElementWidth < mw) {
maxElementWidth = mw;
if (psd->mNoWrap) {
maxElementWidth += mw;
}
else {
if (maxElementWidth < mw) {
maxElementWidth = mw;
}
}
nscoord mh = pfd->mMaxElementSize.height +
pfd->mMargin.top + pfd->mMargin.bottom;

Просмотреть файл

@ -165,7 +165,13 @@ InitDebugFlags()
#endif
//#define FIX_BUG_38157 needs review before it can be enabled
#define FIX_BUG_38157
#define FIX_BUG_37657
// add in a sanity check for absurdly deep frame trees. See bug 42138
// can't just use IsFrameTreeTooDeep() because that method has side effects we don't want
static PRInt32 gRenumberListDepthCounter;
#define MAX_DEPTH_FOR_LIST_RENUMBERING 200 // 200 open displayable tags is pretty unrealistic
//----------------------------------------------------------------------
@ -4263,21 +4269,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
// the available width is the smaller of the widths given by:
// a) the space manager, accounting for floaters impacting this line
// b) the parent frame's computed width
// part 1 of a possible fix for 38157
#ifdef FIX_BUG_38157
const nsMargin& margin = aState.Margin();
nscoord availContentWidth = aState.mReflowState.availableWidth;
if (NS_UNCONSTRAINEDSIZE != availContentWidth) {
availContentWidth -= (borderPadding.left + borderPadding.right) +
(margin.left + margin.right);
}
nscoord availWidth = PR_MIN(aState.mAvailSpaceRect.width, availContentWidth);
#else
nscoord availWidth = aState.mAvailSpaceRect.width;
#endif
nscoord availHeight;
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
availHeight = NS_UNCONSTRAINEDSIZE;
@ -4446,6 +4438,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
// Send post-reflow notification
aState.mPrevChild = aFrame;
/* XXX
This is where we need to add logic to handle some odd behavior.
For one thing, we should usually place at least one thing next
to a left floater, even when that floater takes up all the width on a line.
see bug 22496
*/
// Process the child frames reflow status. There are 5 cases:
// complete, not-complete, break-before, break-after-complete,
// break-after-not-complete. There are two situations: we are a
@ -6999,6 +6998,7 @@ nsBlockFrame::FrameStartsCounterScope(nsIFrame* aFrame)
void
nsBlockFrame::RenumberLists(nsIPresContext* aPresContext)
{
gRenumberListDepthCounter = 0; // reset the sanity check counter
if (!FrameStartsCounterScope(this)) {
// If this frame doesn't start a counter scope then we don't need
// to renumber child list items.
@ -7090,6 +7090,11 @@ nsBlockFrame::RenumberListsFor(nsIPresContext* aPresContext,
nsIFrame* aKid,
PRInt32* aOrdinal)
{
// add in a sanity check for absurdly deep frame trees. See bug 42138
gRenumberListDepthCounter++;
if (MAX_DEPTH_FOR_LIST_RENUMBERING < gRenumberListDepthCounter)
return PR_FALSE;
PRBool kidRenumberedABullet = PR_FALSE;
// If the frame is a list-item and the frame implements our

Просмотреть файл

@ -31,6 +31,9 @@
#include "nsHTMLContainerFrame.h"
#include "nsBlockFrame.h"
#include "nsIDOMHTMLParagraphElement.h"
#include "nsIDOMHTMLTableCellElement.h"
#include "nsIDOMHTMLBodyElement.h"
#include "nsLayoutAtoms.h"
#include "nsCOMPtr.h"
#ifdef NS_DEBUG
@ -75,6 +78,43 @@ nsBlockReflowContext::IsHTMLParagraph(nsIFrame* aFrame)
return result;
}
PRBool
nsBlockReflowContext::IsFirstSignificantChild(const nsIFrame* aParentFrame, const nsIFrame* aChildFrame) const
{
NS_ASSERTION(aParentFrame && aChildFrame, "bad args");
if (!aParentFrame || !aChildFrame) return PR_FALSE;
nsIFrame *child;
aParentFrame->FirstChild((nsIPresContext *)(&mPresContext), nsnull, &child);
while (child)
{
if (aChildFrame == child) {
return PR_TRUE; // we found aChildFrame, and we haven't yet encountered a geometrically significant frame
}
nsSize size;
child->GetSize(size);
if (size.width || size.height) {
return PR_FALSE; // we found a geometrically significant frame and it wasn't aChildFrame
}
child->GetNextSibling(&child);
}
return PR_FALSE; //aChildFrame is not in the default child list of aParentFrame
}
PRBool IsCollapsingBlockParentFrame(const nsIFrame* aFrame)
{
if (!aFrame) return PR_FALSE;
nsCOMPtr<nsIAtom> frameType;
aFrame->GetFrameType(getter_AddRefs(frameType));
if (frameType==nsLayoutAtoms::blockFrame ||
frameType==nsLayoutAtoms::areaFrame ||
frameType==nsLayoutAtoms::tableCellFrame ||
frameType==nsLayoutAtoms::tableCaptionFrame) {
return PR_TRUE;
}
return PR_FALSE;
}
nscoord
nsBlockReflowContext::ComputeCollapsedTopMargin(nsIPresContext* aPresContext,
nsHTMLReflowState& aRS)
@ -310,7 +350,8 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
// XXX subtract out vertical margin?
nsSize availSpace(aSpace.width, aSpace.height);
nsHTMLReflowState reflowState(mPresContext, mOuterReflowState, aFrame,
availSpace, reason);
availSpace, aSpace.width, aSpace.height);
reflowState.reason = reason;
aComputedOffsets = reflowState.mComputedOffsets;
reflowState.mLineLayout = nsnull;
if (!aIsAdjacentWithTop) {
@ -645,22 +686,38 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
nscoord y = mY;
// When deciding whether it's an empty paragraph we also need to take into
// account the overflow area
if ((0 == mMetrics.height) && (0 == mMetrics.mOverflowArea.height)) {
if ((0 == mMetrics.height) && (0 == mMetrics.mOverflowArea.height))
{
PRBool handled = PR_FALSE;
if (IsHTMLParagraph(mFrame)) {
// Special "feature" for HTML compatability - empty paragraphs
// collapse into nothingness, including their margins. Signal
// the special nature here by returning -1.
*aBottomMarginResult = -1;
// In general, we turn off this behavior due to re-interpretation of the vague HTML 4 spec.
// See bug 35772. However, we do need this behavior for <P> inside of table cells,
// floaters, and positioned elements
nsIFrame *parent;
mFrame->GetParent(&parent);
if (parent)
{
if (IsCollapsingBlockParentFrame(mFrame) &&
IsFirstSignificantChild(parent, mFrame))
{
handled = PR_TRUE;
*aBottomMarginResult = -1;
#ifdef NOISY_VERTICAL_MARGINS
printf(" ");
nsFrame::ListTag(stdout, mOuterReflowState.frame);
printf(": ");
nsFrame::ListTag(stdout, mFrame);
printf(" -- zapping top & bottom margin; y=%d spaceY=%d\n",
y, mSpace.y);
printf(" ");
nsFrame::ListTag(stdout, mOuterReflowState.frame);
printf(": ");
nsFrame::ListTag(stdout, mFrame);
printf(" -- zapping top & bottom margin; y=%d spaceY=%d\n",
y, mSpace.y);
#endif
}
}
}
else {
if (!handled)
{
// Collapse the bottom margin with the top margin that was already
// applied.
nscoord newBottomMargin = MaxMargin(collapsedBottomMargin, mTopMargin);
@ -675,19 +732,6 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
#endif
}
#if XXX
// For empty blocks we revert the y coordinate back so that the
// top margin is no longer applied.
nsBlockFrame* bf;
nsresult rv = mFrame->QueryInterface(kBlockFrameCID, (void**)&bf);
if (NS_SUCCEEDED(rv)) {
// XXX This isn't good enough. What if the floater was placed
// downward, just below another floater?
nscoord dy = mSpace.y - mY;
bf->MoveInSpaceManager(mPresContext, mOuterReflowState.mSpaceManager,
dy);
}
#endif
y = mSpace.y;
// Empty blocks do not have anything special done to them and they
@ -707,7 +751,24 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
else {
// See if the frame fit. If its the first frame then it always
// fits.
if (aForceFit || (y + mMetrics.height <= mSpace.YMost())) {
if (aForceFit || (y + mMetrics.height <= mSpace.YMost()))
{
// if it's a <P> and it's parent is special, then collapse the <P>'s top margin
if (IsHTMLParagraph(mFrame)) {
// Special "feature" for HTML compatability - a paragraph's
// top margin collapses into nothingness, inside of certain containers.
nsIFrame *parent;
mFrame->GetParent(&parent);
if (parent)
{
if (IsCollapsingBlockParentFrame(mFrame) &&
IsFirstSignificantChild(parent, mFrame))
{
y=0;
}
}
}
// Calculate the actual x-offset and left and right margin
nsBlockHorizontalAlign align;
@ -743,28 +804,6 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
// Now place the frame and complete the reflow process
nsContainerFrame::FinishReflowChild(mFrame, mPresContext, mMetrics, x, y, 0);
// XXX obsolete, i believe...
#if 0
// If the block frame ended up moving then we need to slide
// anything inside of it that impacts the space manager
// (otherwise the impacted space in the space manager will be
// out of sync with where the frames really are).
nscoord dx = x - mX;
nscoord dy = y - mY;
if ((0 != dx) || (0 != dy)) {
nsIHTMLReflow* htmlReflow;
nsresult rv;
rv = mFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow);
if (NS_SUCCEEDED(rv)) {
// If the child has any floaters that impact the space manager,
// slide them now
htmlReflow->MoveInSpaceManager(mPresContext,
mOuterReflowState.mSpaceManager,
dx, dy);
}
}
#endif
// Adjust the max-element-size in the metrics to take into
// account the margins around the block element. Note that we
// use the collapsed top and bottom margin values.

Просмотреть файл

@ -114,6 +114,12 @@ public:
static PRBool IsHTMLParagraph(nsIFrame* aFrame);
/** return PR_TRUE if aChildFrame is the first geometrically significant child of aParentFrame
* to be considered significant, a frame must have both width and height != 0
* if aChildFrame is not in the default child list of aParentFrame, we return PR_FALSE
*/
PRBool nsBlockReflowContext::IsFirstSignificantChild(const nsIFrame* aParentFrame, const nsIFrame* aChildFrame) const;
static nscoord ComputeCollapsedTopMargin(nsIPresContext* aPresContext,
nsHTMLReflowState& aRS);

Просмотреть файл

@ -165,7 +165,13 @@ InitDebugFlags()
#endif
//#define FIX_BUG_38157 needs review before it can be enabled
#define FIX_BUG_38157
#define FIX_BUG_37657
// add in a sanity check for absurdly deep frame trees. See bug 42138
// can't just use IsFrameTreeTooDeep() because that method has side effects we don't want
static PRInt32 gRenumberListDepthCounter;
#define MAX_DEPTH_FOR_LIST_RENUMBERING 200 // 200 open displayable tags is pretty unrealistic
//----------------------------------------------------------------------
@ -4263,21 +4269,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
// the available width is the smaller of the widths given by:
// a) the space manager, accounting for floaters impacting this line
// b) the parent frame's computed width
// part 1 of a possible fix for 38157
#ifdef FIX_BUG_38157
const nsMargin& margin = aState.Margin();
nscoord availContentWidth = aState.mReflowState.availableWidth;
if (NS_UNCONSTRAINEDSIZE != availContentWidth) {
availContentWidth -= (borderPadding.left + borderPadding.right) +
(margin.left + margin.right);
}
nscoord availWidth = PR_MIN(aState.mAvailSpaceRect.width, availContentWidth);
#else
nscoord availWidth = aState.mAvailSpaceRect.width;
#endif
nscoord availHeight;
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
availHeight = NS_UNCONSTRAINEDSIZE;
@ -4446,6 +4438,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
// Send post-reflow notification
aState.mPrevChild = aFrame;
/* XXX
This is where we need to add logic to handle some odd behavior.
For one thing, we should usually place at least one thing next
to a left floater, even when that floater takes up all the width on a line.
see bug 22496
*/
// Process the child frames reflow status. There are 5 cases:
// complete, not-complete, break-before, break-after-complete,
// break-after-not-complete. There are two situations: we are a
@ -6999,6 +6998,7 @@ nsBlockFrame::FrameStartsCounterScope(nsIFrame* aFrame)
void
nsBlockFrame::RenumberLists(nsIPresContext* aPresContext)
{
gRenumberListDepthCounter = 0; // reset the sanity check counter
if (!FrameStartsCounterScope(this)) {
// If this frame doesn't start a counter scope then we don't need
// to renumber child list items.
@ -7090,6 +7090,11 @@ nsBlockFrame::RenumberListsFor(nsIPresContext* aPresContext,
nsIFrame* aKid,
PRInt32* aOrdinal)
{
// add in a sanity check for absurdly deep frame trees. See bug 42138
gRenumberListDepthCounter++;
if (MAX_DEPTH_FOR_LIST_RENUMBERING < gRenumberListDepthCounter)
return PR_FALSE;
PRBool kidRenumberedABullet = PR_FALSE;
// If the frame is a list-item and the frame implements our

Просмотреть файл

@ -165,7 +165,13 @@ InitDebugFlags()
#endif
//#define FIX_BUG_38157 needs review before it can be enabled
#define FIX_BUG_38157
#define FIX_BUG_37657
// add in a sanity check for absurdly deep frame trees. See bug 42138
// can't just use IsFrameTreeTooDeep() because that method has side effects we don't want
static PRInt32 gRenumberListDepthCounter;
#define MAX_DEPTH_FOR_LIST_RENUMBERING 200 // 200 open displayable tags is pretty unrealistic
//----------------------------------------------------------------------
@ -4263,21 +4269,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
// the available width is the smaller of the widths given by:
// a) the space manager, accounting for floaters impacting this line
// b) the parent frame's computed width
// part 1 of a possible fix for 38157
#ifdef FIX_BUG_38157
const nsMargin& margin = aState.Margin();
nscoord availContentWidth = aState.mReflowState.availableWidth;
if (NS_UNCONSTRAINEDSIZE != availContentWidth) {
availContentWidth -= (borderPadding.left + borderPadding.right) +
(margin.left + margin.right);
}
nscoord availWidth = PR_MIN(aState.mAvailSpaceRect.width, availContentWidth);
#else
nscoord availWidth = aState.mAvailSpaceRect.width;
#endif
nscoord availHeight;
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
availHeight = NS_UNCONSTRAINEDSIZE;
@ -4446,6 +4438,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
// Send post-reflow notification
aState.mPrevChild = aFrame;
/* XXX
This is where we need to add logic to handle some odd behavior.
For one thing, we should usually place at least one thing next
to a left floater, even when that floater takes up all the width on a line.
see bug 22496
*/
// Process the child frames reflow status. There are 5 cases:
// complete, not-complete, break-before, break-after-complete,
// break-after-not-complete. There are two situations: we are a
@ -6999,6 +6998,7 @@ nsBlockFrame::FrameStartsCounterScope(nsIFrame* aFrame)
void
nsBlockFrame::RenumberLists(nsIPresContext* aPresContext)
{
gRenumberListDepthCounter = 0; // reset the sanity check counter
if (!FrameStartsCounterScope(this)) {
// If this frame doesn't start a counter scope then we don't need
// to renumber child list items.
@ -7090,6 +7090,11 @@ nsBlockFrame::RenumberListsFor(nsIPresContext* aPresContext,
nsIFrame* aKid,
PRInt32* aOrdinal)
{
// add in a sanity check for absurdly deep frame trees. See bug 42138
gRenumberListDepthCounter++;
if (MAX_DEPTH_FOR_LIST_RENUMBERING < gRenumberListDepthCounter)
return PR_FALSE;
PRBool kidRenumberedABullet = PR_FALSE;
// If the frame is a list-item and the frame implements our

Просмотреть файл

@ -558,19 +558,30 @@ nsLineLayout::EndSpan(nsIFrame* aFrame,
width = psd->mX - psd->mLeftEdge;
PerFrameData* pfd = psd->mFirstFrame;
while (nsnull != pfd) {
if (pfd->mBounds.height > maxHeight) maxHeight = pfd->mBounds.height;
/* there's one oddball case we need to guard against
* if we're reflowed with NS_UNCONSTRAINEDSIZE
* then the last frame will not contribute to the max element size height
* if it is a text frame that only contains whitespace
*/
if (NS_UNCONSTRAINEDSIZE != psd->mRightEdge || // it's not an unconstrained reflow
pfd->mNext || // or it's not the last frame in the span
!pfd->GetFlag(PFD_ISTEXTFRAME) || // or it's not a text frame
pfd->GetFlag(PFD_ISNONWHITESPACETEXTFRAME) // or it contains something other than whitespace
) {
if (pfd->mBounds.height > maxHeight) maxHeight = pfd->mBounds.height;
// Compute max-element-size if necessary
if (aMaxElementSize) {
nscoord mw = pfd->mMaxElementSize.width +
pfd->mMargin.left + pfd->mMargin.right;
if (maxElementWidth < mw) {
maxElementWidth = mw;
}
nscoord mh = pfd->mMaxElementSize.height +
pfd->mMargin.top + pfd->mMargin.bottom;
if (maxElementHeight < mh) {
maxElementHeight = mh;
// Compute max-element-size if necessary
if (aMaxElementSize) {
nscoord mw = pfd->mMaxElementSize.width +
pfd->mMargin.left + pfd->mMargin.right;
if (maxElementWidth < mw) {
maxElementWidth = mw;
}
nscoord mh = pfd->mMaxElementSize.height +
pfd->mMargin.top + pfd->mMargin.bottom;
if (maxElementHeight < mh) {
maxElementHeight = mh;
}
}
}
pfd = pfd->mNext;
@ -1627,8 +1638,13 @@ nsLineLayout::VerticalAlignFrames(nsLineBox* aLineBox,
if (mComputeMaxElementSize) {
nscoord mw = pfd->mMaxElementSize.width +
pfd->mMargin.left + pfd->mMargin.right;
if (maxElementWidth < mw) {
maxElementWidth = mw;
if (psd->mNoWrap) {
maxElementWidth += mw;
}
else {
if (maxElementWidth < mw) {
maxElementWidth = mw;
}
}
nscoord mh = pfd->mMaxElementSize.height +
pfd->mMargin.top + pfd->mMargin.bottom;