From d76ca7e7fd7f0861d1dcd511eb95db38ba90219d Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Tue, 22 Dec 1998 03:49:04 +0000 Subject: [PATCH] Fix for bug #1942. Also made it so we respect 'width' and 'height' properties specified on the HTML element git-svn-id: svn://10.0.0.236/trunk@16798 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/generic/nsHTMLFrame.cpp | 145 +++++++++--------- .../html/base/src/nsFrameReflowState.cpp | 8 - mozilla/layout/html/base/src/nsHTMLFrame.cpp | 145 +++++++++--------- 3 files changed, 142 insertions(+), 156 deletions(-) diff --git a/mozilla/layout/generic/nsHTMLFrame.cpp b/mozilla/layout/generic/nsHTMLFrame.cpp index b126f03a0b5..481ed370680 100644 --- a/mozilla/layout/generic/nsHTMLFrame.cpp +++ b/mozilla/layout/generic/nsHTMLFrame.cpp @@ -42,6 +42,16 @@ static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID); static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); +/** + * Root frame class. + * + * The root frame is the parent frame for the document element's frame. + * It only supports having a single child frame which must be one of the + * following: + * - scroll frame + * - area frame + * - page sequence frame + */ class RootFrame : public nsHTMLContainerFrame { public: NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, @@ -94,113 +104,100 @@ RootFrame::Reflow(nsIPresContext& aPresContext, nsReflowStatus& aStatus) { NS_FRAME_TRACE_REFLOW_IN("RootFrame::Reflow"); + NS_PRECONDITION(nsnull == aDesiredSize.maxElementSize, "unexpected request"); + // Initialize OUT parameter aStatus = NS_FRAME_COMPLETE; - // XXX Copy the reflow state so that we can change the - // reason in cases where we're inserting and deleting - // frames from the root. Troy may want to reconstruct - // this routine. - nsHTMLReflowState reflowState(aReflowState); - if (eReflowReason_Incremental == reflowState.reason) { + PRBool isChildInitialReflow = PR_FALSE; + + // Check for an incremental reflow + if (eReflowReason_Incremental == aReflowState.reason) { // See if we're the target frame nsIFrame* targetFrame; - reflowState.reflowCommand->GetTarget(targetFrame); + aReflowState.reflowCommand->GetTarget(targetFrame); if (this == targetFrame) { nsIReflowCommand::ReflowType reflowType; nsIFrame* childFrame; // Get the reflow type - reflowState.reflowCommand->GetType(reflowType); + aReflowState.reflowCommand->GetType(reflowType); if ((nsIReflowCommand::FrameAppended == reflowType) || (nsIReflowCommand::FrameInserted == reflowType)) { + + NS_ASSERTION(nsnull == mFirstChild, "only one child frame allowed"); + // Insert the frame into the child list - reflowState.reflowCommand->GetChildFrame(childFrame); - if (nsnull == mFirstChild) { - mFirstChild = childFrame; - } else { - nsIFrame* lastChild = LastFrame(mFirstChild); - lastChild->SetNextSibling(childFrame); - } - // XXX This is wrong. Only the new child should be reflowed - // with this reason. The rest should just be resized. - reflowState.reason = eReflowReason_Initial; + aReflowState.reflowCommand->GetChildFrame(childFrame); + mFirstChild = childFrame; + + // It's the child frame's initial reflow + isChildInitialReflow = PR_TRUE; + } else if (nsIReflowCommand::FrameRemoved == reflowType) { nsIFrame* deletedFrame; // Get the child frame we should delete - reflowState.reflowCommand->GetChildFrame(deletedFrame); + aReflowState.reflowCommand->GetChildFrame(deletedFrame); + NS_ASSERTION(deletedFrame == mFirstChild, "not a child frame"); // Remove it from the child list if (deletedFrame == mFirstChild) { - deletedFrame->GetNextSibling(mFirstChild); - } else { - nsIFrame* prevSibling = nsnull; - nsIFrame* f; - for (f = mFirstChild; nsnull != f; f->GetNextSibling(f)) { - if (f == deletedFrame) { - break; - } + mFirstChild = nsnull; - prevSibling = f; - } + // Damage the area occupied by the deleted frame + nsRect damageRect; + deletedFrame->GetRect(damageRect); + Invalidate(damageRect, PR_FALSE); - if (nsnull != f) { - nsIFrame* nextSibling; - - f->GetNextSibling(nextSibling); - NS_ASSERTION(nsnull != prevSibling, "null pointer"); - prevSibling->SetNextSibling(nextSibling); - } + // Delete the frame + deletedFrame->DeleteFrame(aPresContext); } - deletedFrame->SetNextSibling(nsnull); - - // Delete the frame - deletedFrame->DeleteFrame(aPresContext); - reflowState.reason = eReflowReason_Resize; } } else { nsIFrame* nextFrame; // Get the next frame in the reflow chain - reflowState.reflowCommand->GetNext(nextFrame); + aReflowState.reflowCommand->GetNext(nextFrame); NS_ASSERTION(nextFrame == mFirstChild, "unexpected next reflow command frame"); } } - // Reflow our child frame + // Reflow our one and only child frame if (nsnull != mFirstChild) { - // Compute how much space to reserve for our border and padding - nsMargin borderPadding; - nsHTMLReflowState::ComputeBorderPaddingFor(this, nsnull, - borderPadding); + // Note: the root frame does not have border or padding... // Compute the margins around the child frame - nsMargin childMargins; - nsHTMLReflowState::ComputeMarginFor(mFirstChild, &aReflowState, - childMargins); + nsMargin childMargin; + nsHTMLReflowState::ComputeMarginFor(mFirstChild, &aReflowState, childMargin); - nscoord top = borderPadding.top + childMargins.top; - nscoord bottom = borderPadding.bottom + childMargins.bottom; - nscoord left = borderPadding.left + childMargins.left; - nscoord right = borderPadding.right + childMargins.right; - - nsSize kidMaxSize(reflowState.maxSize); - kidMaxSize.width -= left + right; - kidMaxSize.height -= top + bottom; + // Compute the child frame's available space + nsSize kidMaxSize(aReflowState.maxSize.width - childMargin.left - childMargin.right, + aReflowState.maxSize.height - childMargin.top - childMargin.bottom); nsHTMLReflowMetrics desiredSize(nsnull); // We must pass in that the available height is unconstrained, because // constrained is only for when we're paginated... - nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, reflowState, + nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, nsSize(kidMaxSize.width, NS_UNCONSTRAINEDSIZE)); - // XXX HACK - kidReflowState.widthConstraint = eHTMLFrameConstraint_Fixed; - kidReflowState.minWidth = kidMaxSize.width; - kidReflowState.heightConstraint = eHTMLFrameConstraint_Fixed; - kidReflowState.minHeight = kidMaxSize.height; - nsIHTMLReflow* htmlReflow; + if (isChildInitialReflow) { + kidReflowState.reason = eReflowReason_Initial; + kidReflowState.reflowCommand = nsnull; + } + // For a width or height that's 'auto', make the frame as big as the + // available space + if (eHTMLFrameConstraint_FixedContent != kidReflowState.widthConstraint) { + kidReflowState.widthConstraint = eHTMLFrameConstraint_Fixed; + kidReflowState.minWidth = kidMaxSize.width; + } + if (eHTMLFrameConstraint_FixedContent != kidReflowState.heightConstraint) { + kidReflowState.heightConstraint = eHTMLFrameConstraint_Fixed; + kidReflowState.minHeight = kidMaxSize.height; + } + + // Reflow the frame + nsIHTMLReflow* htmlReflow; if (NS_OK == mFirstChild->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { ReflowChild(mFirstChild, aPresContext, desiredSize, kidReflowState, aStatus); @@ -208,13 +205,13 @@ RootFrame::Reflow(nsIPresContext& aPresContext, // fixed make sure it's at least as big as we told it. This // handles the case where the child ignores the reflow state // constraints - if (desiredSize.width < kidMaxSize.width) { - desiredSize.width = kidMaxSize.width; + if (desiredSize.width < kidReflowState.minWidth) { + desiredSize.width = kidReflowState.minWidth; } - if (desiredSize.height < kidMaxSize.height) { - desiredSize.height = kidMaxSize.height; + if (desiredSize.height < kidReflowState.minHeight) { + desiredSize.height = kidReflowState.minHeight; } - nsRect rect(left, top, desiredSize.width, desiredSize.height); + nsRect rect(childMargin.left, childMargin.top, desiredSize.width, desiredSize.height); mFirstChild->SetRect(rect); // XXX We should resolve the details of who/when DidReflow() @@ -223,15 +220,15 @@ RootFrame::Reflow(nsIPresContext& aPresContext, } // If this is a resize reflow then do a repaint - if (eReflowReason_Resize == reflowState.reason) { - nsRect damageRect(0, 0, reflowState.maxSize.width, reflowState.maxSize.height); + if (eReflowReason_Resize == aReflowState.reason) { + nsRect damageRect(0, 0, aReflowState.maxSize.width, aReflowState.maxSize.height); Invalidate(damageRect, PR_FALSE); } } // Return the max size as our desired size - aDesiredSize.width = reflowState.maxSize.width; - aDesiredSize.height = reflowState.maxSize.height; + aDesiredSize.width = aReflowState.maxSize.width; + aDesiredSize.height = aReflowState.maxSize.height; aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; diff --git a/mozilla/layout/html/base/src/nsFrameReflowState.cpp b/mozilla/layout/html/base/src/nsFrameReflowState.cpp index 1d2abdd572c..8e3360397e4 100644 --- a/mozilla/layout/html/base/src/nsFrameReflowState.cpp +++ b/mozilla/layout/html/base/src/nsFrameReflowState.cpp @@ -287,21 +287,13 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) if (width > 0) { // XXX If the size constraint is a fixed content width then we also // need to set the max width as well, but then we bust tables... -#if 0 - minWidth = maxSize.width = width; -#else minWidth = width; -#endif widthConstraint = eHTMLFrameConstraint_FixedContent; } if (height > 0) { // XXX If the size constraint is a fixed content width then we also // need to set the max height as well... -#if 0 - minHeight = maxSize.height = height; -#else minHeight = height; -#endif heightConstraint = eHTMLFrameConstraint_FixedContent; } } diff --git a/mozilla/layout/html/base/src/nsHTMLFrame.cpp b/mozilla/layout/html/base/src/nsHTMLFrame.cpp index b126f03a0b5..481ed370680 100644 --- a/mozilla/layout/html/base/src/nsHTMLFrame.cpp +++ b/mozilla/layout/html/base/src/nsHTMLFrame.cpp @@ -42,6 +42,16 @@ static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID); static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); +/** + * Root frame class. + * + * The root frame is the parent frame for the document element's frame. + * It only supports having a single child frame which must be one of the + * following: + * - scroll frame + * - area frame + * - page sequence frame + */ class RootFrame : public nsHTMLContainerFrame { public: NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, @@ -94,113 +104,100 @@ RootFrame::Reflow(nsIPresContext& aPresContext, nsReflowStatus& aStatus) { NS_FRAME_TRACE_REFLOW_IN("RootFrame::Reflow"); + NS_PRECONDITION(nsnull == aDesiredSize.maxElementSize, "unexpected request"); + // Initialize OUT parameter aStatus = NS_FRAME_COMPLETE; - // XXX Copy the reflow state so that we can change the - // reason in cases where we're inserting and deleting - // frames from the root. Troy may want to reconstruct - // this routine. - nsHTMLReflowState reflowState(aReflowState); - if (eReflowReason_Incremental == reflowState.reason) { + PRBool isChildInitialReflow = PR_FALSE; + + // Check for an incremental reflow + if (eReflowReason_Incremental == aReflowState.reason) { // See if we're the target frame nsIFrame* targetFrame; - reflowState.reflowCommand->GetTarget(targetFrame); + aReflowState.reflowCommand->GetTarget(targetFrame); if (this == targetFrame) { nsIReflowCommand::ReflowType reflowType; nsIFrame* childFrame; // Get the reflow type - reflowState.reflowCommand->GetType(reflowType); + aReflowState.reflowCommand->GetType(reflowType); if ((nsIReflowCommand::FrameAppended == reflowType) || (nsIReflowCommand::FrameInserted == reflowType)) { + + NS_ASSERTION(nsnull == mFirstChild, "only one child frame allowed"); + // Insert the frame into the child list - reflowState.reflowCommand->GetChildFrame(childFrame); - if (nsnull == mFirstChild) { - mFirstChild = childFrame; - } else { - nsIFrame* lastChild = LastFrame(mFirstChild); - lastChild->SetNextSibling(childFrame); - } - // XXX This is wrong. Only the new child should be reflowed - // with this reason. The rest should just be resized. - reflowState.reason = eReflowReason_Initial; + aReflowState.reflowCommand->GetChildFrame(childFrame); + mFirstChild = childFrame; + + // It's the child frame's initial reflow + isChildInitialReflow = PR_TRUE; + } else if (nsIReflowCommand::FrameRemoved == reflowType) { nsIFrame* deletedFrame; // Get the child frame we should delete - reflowState.reflowCommand->GetChildFrame(deletedFrame); + aReflowState.reflowCommand->GetChildFrame(deletedFrame); + NS_ASSERTION(deletedFrame == mFirstChild, "not a child frame"); // Remove it from the child list if (deletedFrame == mFirstChild) { - deletedFrame->GetNextSibling(mFirstChild); - } else { - nsIFrame* prevSibling = nsnull; - nsIFrame* f; - for (f = mFirstChild; nsnull != f; f->GetNextSibling(f)) { - if (f == deletedFrame) { - break; - } + mFirstChild = nsnull; - prevSibling = f; - } + // Damage the area occupied by the deleted frame + nsRect damageRect; + deletedFrame->GetRect(damageRect); + Invalidate(damageRect, PR_FALSE); - if (nsnull != f) { - nsIFrame* nextSibling; - - f->GetNextSibling(nextSibling); - NS_ASSERTION(nsnull != prevSibling, "null pointer"); - prevSibling->SetNextSibling(nextSibling); - } + // Delete the frame + deletedFrame->DeleteFrame(aPresContext); } - deletedFrame->SetNextSibling(nsnull); - - // Delete the frame - deletedFrame->DeleteFrame(aPresContext); - reflowState.reason = eReflowReason_Resize; } } else { nsIFrame* nextFrame; // Get the next frame in the reflow chain - reflowState.reflowCommand->GetNext(nextFrame); + aReflowState.reflowCommand->GetNext(nextFrame); NS_ASSERTION(nextFrame == mFirstChild, "unexpected next reflow command frame"); } } - // Reflow our child frame + // Reflow our one and only child frame if (nsnull != mFirstChild) { - // Compute how much space to reserve for our border and padding - nsMargin borderPadding; - nsHTMLReflowState::ComputeBorderPaddingFor(this, nsnull, - borderPadding); + // Note: the root frame does not have border or padding... // Compute the margins around the child frame - nsMargin childMargins; - nsHTMLReflowState::ComputeMarginFor(mFirstChild, &aReflowState, - childMargins); + nsMargin childMargin; + nsHTMLReflowState::ComputeMarginFor(mFirstChild, &aReflowState, childMargin); - nscoord top = borderPadding.top + childMargins.top; - nscoord bottom = borderPadding.bottom + childMargins.bottom; - nscoord left = borderPadding.left + childMargins.left; - nscoord right = borderPadding.right + childMargins.right; - - nsSize kidMaxSize(reflowState.maxSize); - kidMaxSize.width -= left + right; - kidMaxSize.height -= top + bottom; + // Compute the child frame's available space + nsSize kidMaxSize(aReflowState.maxSize.width - childMargin.left - childMargin.right, + aReflowState.maxSize.height - childMargin.top - childMargin.bottom); nsHTMLReflowMetrics desiredSize(nsnull); // We must pass in that the available height is unconstrained, because // constrained is only for when we're paginated... - nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, reflowState, + nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, nsSize(kidMaxSize.width, NS_UNCONSTRAINEDSIZE)); - // XXX HACK - kidReflowState.widthConstraint = eHTMLFrameConstraint_Fixed; - kidReflowState.minWidth = kidMaxSize.width; - kidReflowState.heightConstraint = eHTMLFrameConstraint_Fixed; - kidReflowState.minHeight = kidMaxSize.height; - nsIHTMLReflow* htmlReflow; + if (isChildInitialReflow) { + kidReflowState.reason = eReflowReason_Initial; + kidReflowState.reflowCommand = nsnull; + } + // For a width or height that's 'auto', make the frame as big as the + // available space + if (eHTMLFrameConstraint_FixedContent != kidReflowState.widthConstraint) { + kidReflowState.widthConstraint = eHTMLFrameConstraint_Fixed; + kidReflowState.minWidth = kidMaxSize.width; + } + if (eHTMLFrameConstraint_FixedContent != kidReflowState.heightConstraint) { + kidReflowState.heightConstraint = eHTMLFrameConstraint_Fixed; + kidReflowState.minHeight = kidMaxSize.height; + } + + // Reflow the frame + nsIHTMLReflow* htmlReflow; if (NS_OK == mFirstChild->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { ReflowChild(mFirstChild, aPresContext, desiredSize, kidReflowState, aStatus); @@ -208,13 +205,13 @@ RootFrame::Reflow(nsIPresContext& aPresContext, // fixed make sure it's at least as big as we told it. This // handles the case where the child ignores the reflow state // constraints - if (desiredSize.width < kidMaxSize.width) { - desiredSize.width = kidMaxSize.width; + if (desiredSize.width < kidReflowState.minWidth) { + desiredSize.width = kidReflowState.minWidth; } - if (desiredSize.height < kidMaxSize.height) { - desiredSize.height = kidMaxSize.height; + if (desiredSize.height < kidReflowState.minHeight) { + desiredSize.height = kidReflowState.minHeight; } - nsRect rect(left, top, desiredSize.width, desiredSize.height); + nsRect rect(childMargin.left, childMargin.top, desiredSize.width, desiredSize.height); mFirstChild->SetRect(rect); // XXX We should resolve the details of who/when DidReflow() @@ -223,15 +220,15 @@ RootFrame::Reflow(nsIPresContext& aPresContext, } // If this is a resize reflow then do a repaint - if (eReflowReason_Resize == reflowState.reason) { - nsRect damageRect(0, 0, reflowState.maxSize.width, reflowState.maxSize.height); + if (eReflowReason_Resize == aReflowState.reason) { + nsRect damageRect(0, 0, aReflowState.maxSize.width, aReflowState.maxSize.height); Invalidate(damageRect, PR_FALSE); } } // Return the max size as our desired size - aDesiredSize.width = reflowState.maxSize.width; - aDesiredSize.height = reflowState.maxSize.height; + aDesiredSize.width = aReflowState.maxSize.width; + aDesiredSize.height = aReflowState.maxSize.height; aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0;