Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.

git-svn-id: svn://10.0.0.236/trunk@216738 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dbaron%dbaron.org
2006-12-08 05:38:33 +00:00
parent 1a1de382fe
commit 1ca9f3f372
201 changed files with 8730 additions and 18257 deletions

View File

@@ -50,7 +50,6 @@
#include "nsAbsoluteContainingBlock.h"
#include "nsLayoutAtoms.h"
#include "nsCSSAnonBoxes.h"
#include "nsReflowPath.h"
#include "nsAutoPtr.h"
#include "nsFrameManager.h"
#ifdef ACCESSIBILITY
@@ -211,7 +210,11 @@ nsInlineFrame::AppendFrames(nsIAtom* aListName,
#ifdef IBMBIDI
if (nsnull == aListName)
#endif
ReflowDirtyChild(GetPresContext()->PresShell(), nsnull);
{
AddStateBits(NS_FRAME_IS_DIRTY);
GetPresContext()->PresShell()->
FrameNeedsReflow(this, nsIPresShell::eTreeChange);
}
}
return NS_OK;
}
@@ -241,7 +244,9 @@ nsInlineFrame::InsertFrames(nsIAtom* aListName,
if (nsnull == aListName)
#endif
// Ask the parent frame to reflow me.
ReflowDirtyChild(GetPresContext()->PresShell(), nsnull);
AddStateBits(NS_FRAME_IS_DIRTY);
GetPresContext()->PresShell()->
FrameNeedsReflow(this, nsIPresShell::eTreeChange);
}
return NS_OK;
}
@@ -296,7 +301,9 @@ nsInlineFrame::RemoveFrame(nsIAtom* aListName,
if (generateReflowCommand) {
// Ask the parent frame to reflow me.
ReflowDirtyChild(GetPresContext()->PresShell(), nsnull);
AddStateBits(NS_FRAME_IS_DIRTY);
GetPresContext()->PresShell()->
FrameNeedsReflow(this, nsIPresShell::eTreeChange);
}
}
@@ -324,13 +331,37 @@ nsInlineFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
//////////////////////////////////////////////////////////////////////
// Reflow methods
/* virtual */ void
nsInlineFrame::AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
nsIFrame::InlineMinWidthData *aData)
{
DoInlineIntrinsicWidth(aRenderingContext, aData, nsLayoutUtils::MIN_WIDTH);
}
/* virtual */ void
nsInlineFrame::AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
nsIFrame::InlinePrefWidthData *aData)
{
DoInlineIntrinsicWidth(aRenderingContext, aData, nsLayoutUtils::PREF_WIDTH);
}
/* virtual */ nsSize
nsInlineFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
nsSize aCBSize, nscoord aAvailableWidth,
nsSize aMargin, nsSize aBorder, nsSize aPadding,
PRBool aShrinkWrap)
{
// Inlines and text don't compute size before reflow.
return nsSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
}
NS_IMETHODIMP
nsInlineFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aMetrics,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
DO_GLOBAL_REFLOW_COUNT("nsInlineFrame", aReflowState.reason);
DO_GLOBAL_REFLOW_COUNT("nsInlineFrame");
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
if (nsnull == aReflowState.mLineLayout) {
return NS_ERROR_INVALID_ARG;
@@ -349,7 +380,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
nsHTMLContainerFrame::ReparentFrameViewList(aPresContext, prevOverflowFrames,
prevInFlow, this);
if (aReflowState.reason == eReflowReason_Initial) {
if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
// If it's the initial reflow, then our child list must be empty, so
// just set the child list rather than calling InsertFrame(). This avoids
// having to get the last child frame in the list.
@@ -370,7 +401,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
// It's also possible that we have an overflow list for ourselves
#ifdef DEBUG
if (aReflowState.reason == eReflowReason_Initial) {
if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
// If it's our initial reflow, then we should not have an overflow list.
// However, add an assertion in case we get reflowed more than once with
// the initial reflow reason
@@ -378,7 +409,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
NS_ASSERTION(!overflowFrames, "overflow list is not empty for initial reflow");
}
#endif
if (aReflowState.reason != eReflowReason_Initial) {
if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE);
if (overflowFrames) {
NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
@@ -429,36 +460,11 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
return rv;
}
NS_IMETHODIMP
nsInlineFrame::CanContinueTextRun(PRBool& aContinueTextRun) const
/* virtual */ PRBool
nsInlineFrame::CanContinueTextRun() const
{
// We can continue a text run through an inline frame
aContinueTextRun = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsInlineFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild)
{
// The inline container frame does not handle the reflow
// request. It passes it up to its parent container.
// If you don't already have dirty children,
if (!(mState & NS_FRAME_HAS_DIRTY_CHILDREN)) {
if (mParent) {
// Record that you are dirty and have dirty children
mState |= NS_FRAME_IS_DIRTY;
mState |= NS_FRAME_HAS_DIRTY_CHILDREN;
// Pass the reflow request up to the parent
mParent->ReflowDirtyChild(aPresShell, this);
}
else {
NS_ERROR("No parent to pass the reflow request up to.");
}
}
return NS_OK;
return PR_TRUE;
}
nsresult
@@ -571,8 +577,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
// that are empty we force to empty so that things like collapsed
// whitespace in an inline element don't affect the line-height.
nsSize size;
lineLayout->EndSpan(this, size,
aMetrics.mComputeMEW ? &aMetrics.mMaxElementWidth : nsnull);
lineLayout->EndSpan(this, size);
if ((0 == size.height) && (0 == size.width) &&
((nsnull != GetPrevInFlow()) || (nsnull != GetNextInFlow()))) {
// This is a continuation of a previous inline. Therefore make
@@ -581,9 +586,6 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
aMetrics.height = 0;
aMetrics.ascent = 0;
aMetrics.descent = 0;
if (aMetrics.mComputeMEW) {
aMetrics.mMaxElementWidth = 0;
}
}
else {
// Compute final width
@@ -633,9 +635,6 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
ListTag(stdout);
printf(": metrics=%d,%d ascent=%d descent=%d\n",
aMetrics.width, aMetrics.height, aMetrics.ascent, aMetrics.descent);
if (aMetrics.mComputeMEW) {
printf(" maxElementWidth %d\n", aMetrics.mMaxElementWidth);
}
#endif
return rv;
@@ -652,7 +651,7 @@ void MarkPercentAwareFrame(nsPresContext *aPresContext,
nsInlineFrame *aInline,
nsIFrame *aFrame)
{
if (aFrame->GetStateBits() & NS_FRAME_REPLACED_ELEMENT)
if (aFrame->IsFrameOfType(nsIFrame::eReplaced))
{ // aFrame is a replaced element, check it's style
if (nsLineLayout::IsPercentageAwareReplacedElement(aPresContext, aFrame)) {
SetContainsPercentAwareChild(aInline);
@@ -1190,20 +1189,13 @@ nsPositionedInlineFrame::Reflow(nsPresContext* aPresContext,
nscoord containingBlockHeight =
aDesiredSize.height - computedBorder.TopBottom();
// Do any incremental reflows ... would be nice to merge with
// the reflows below but that would be more work, and more risky
if (eReflowReason_Incremental == aReflowState.reason) {
mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState,
containingBlockWidth,
containingBlockHeight);
}
// Factor the absolutely positioned child bounds into the overflow area
// Don't include this frame's bounds, nor its inline descendants' bounds,
// and don't store the overflow property.
// That will all be done by nsLineLayout::RelativePositionFrames.
rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState,
containingBlockWidth, containingBlockHeight,
PR_TRUE, PR_TRUE, // XXX could be optimized
&aDesiredSize.mOverflowArea);
}