bug 67861 - don't rebalance table to calculate max width; cache last available width in outer table; improved debug reflow timing; sr=attinasi, r=peterl

git-svn-id: svn://10.0.0.236/trunk@86475 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
karnaze%netscape.com 2001-02-07 04:31:38 +00:00
parent 08ac70912c
commit b45820e80c
13 changed files with 235 additions and 197 deletions

View File

@ -1069,12 +1069,29 @@ BasicTableLayoutStrategy::ReduceOverSpecifiedPctCols(nscoord aExcess)
}
}
#ifdef DEBUG_TABLE_REFLOW_TIMING
nscoord WrapupAssignPctColumnWidths(nsTableFrame* aTableFrame,
const nsHTMLReflowState& aReflowState,
nscoord aValue)
{
nsTableFrame::DebugTimePctCols(*aTableFrame, (nsHTMLReflowState&)aReflowState, PR_FALSE);
return aValue;
}
#else
inline nscoord WrapupAssignPctColumnWidths(nsTableFrame* aTableFrame,
const nsHTMLReflowState& aReflowState,
nscoord aValue)
{
return aValue;
}
#endif
// Determine percentage col widths for each col frame
nscoord
BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState aReflowState,
nscoord aBasisIn,
PRBool aTableIsAutoWidth,
float aPixelToTwips)
BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflowState,
nscoord aBasisIn,
PRBool aTableIsAutoWidth,
float aPixelToTwips)
{
#ifdef DEBUG_TABLE_REFLOW_TIMING
nsTableFrame::DebugTimePctCols(*mTableFrame, (nsHTMLReflowState&)aReflowState, PR_TRUE);
@ -1088,7 +1105,8 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState aReflowS
nscoord basis; // basis to use for percentage based calculations
if (!aTableIsAutoWidth) {
if (NS_UNCONSTRAINEDSIZE == aBasisIn) {
return 0; // don't do the calculations on unconstrained basis
// don't do the calculations on unconstrained basis
return WrapupAssignPctColumnWidths(mTableFrame, aReflowState, 0);
}
basis = aBasisIn;
}
@ -1179,11 +1197,11 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState aReflowS
delete [] rawPctValues; // destroy the raw pct values
// If there are no pct cells or cols, there is nothing to do.
if ((0 == numPerCols) || (0.0f == perTotal)) {
return 0;
return WrapupAssignPctColumnWidths(mTableFrame, aReflowState, 0);
}
// If there is only one col and it is % based, it won't affect anything
if ((1 == numCols) && (numCols == numPerCols)) {
return 0;
return WrapupAssignPctColumnWidths(mTableFrame, aReflowState, 0);
}
// compute a basis considering total percentages and the desired width of everything else
@ -1379,10 +1397,7 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState aReflowS
ReduceOverSpecifiedPctCols(NSToCoordRound(((float)(colPctTotal - 100)) * 0.01f * (float)basis));
}
#ifdef DEBUG_TABLE_REFLOW_TIMING
nsTableFrame::DebugTimePctCols(*mTableFrame, (nsHTMLReflowState&)aReflowState, PR_FALSE);
#endif
return basis;
return WrapupAssignPctColumnWidths(mTableFrame, aReflowState, basis);
}
nscoord BasicTableLayoutStrategy::GetTableMinWidth() const

View File

@ -139,10 +139,10 @@ protected:
PRInt32& aLimitType,
float aPixelToTwips);
nscoord AssignPctColumnWidths(const nsHTMLReflowState aReflowState,
nscoord aBasis,
PRBool aTableIsAutoWidth,
float aPixelToTwips);
nscoord AssignPctColumnWidths(const nsHTMLReflowState& aReflowState,
nscoord aBasis,
PRBool aTableIsAutoWidth,
float aPixelToTwips);
void ReduceOverSpecifiedPctCols(nscoord aExcess);

View File

@ -24,7 +24,7 @@ DEPTH=..\..\..\..
LIBRARY_NAME=raptorhtmltable_s
MODULE=raptor
DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN
DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN -DoffDEBUG_TABLE_REFLOW_TIMING -DoffDEBUG_TABLE_REFLOW_TIMING_DETAIL
CPPSRCS= nsCellMap.cpp \
nsTableCellFrame.cpp \

View File

@ -653,41 +653,23 @@ PRInt32 nsTableCellFrame::GetColSpan()
return colSpan;
}
#define PROBABLY_TOO_LARGE 1000000
static
void DebugCheckChildSize(nsIFrame* aChild,
nsHTMLReflowMetrics& aMet,
nsSize& aAvailSize,
PRBool aIsPass2Reflow)
{
/* approved for commenting out by rickg
if (aMet.width > aAvailSize.width) {
nsAutoString tmp;
aChild->GetFrameName(tmp);
printf("WARNING: cell ");
fputs(tmp, stdout);
printf(" content has desired width %d given avail width %d\n",
aMet.width, aAvailSize.width);
}
*/
if (aIsPass2Reflow) {
if ((aMet.width < 0) || (aMet.width > 60000)) {
if ((aMet.width < 0) || (aMet.width > PROBABLY_TOO_LARGE)) {
printf("WARNING: cell content %p has large width %d \n", aChild, aMet.width);
}
if ((aMet.height < 0) || (aMet.height > 60000)) {
printf("WARNING: cell content %p has large height %d \n", aChild, aMet.height);
}
}
if (aMet.maxElementSize) {
nscoord tmp = aMet.maxElementSize->width;
if ((tmp < 0) || (tmp > 60000)) {
if ((tmp < 0) || (tmp > PROBABLY_TOO_LARGE)) {
printf("WARNING: cell content %p has large max element width %d \n", aChild, tmp);
}
tmp = aMet.maxElementSize->height;
if ((tmp < 0) || (tmp > 60000)) {
printf("WARNING: cell content %p has large max element height %d \n", aChild, tmp);
}
}
}

View File

@ -1769,10 +1769,6 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
}
}
else if (!IsMaximumWidthValid()) {
// Initialize the strategy and have it compute the natural size of
// the table
mTableLayoutStrategy->Initialize(aPresContext, nsnull, NS_UNCONSTRAINEDSIZE, aReflowState);
// Ask the strategy for the natural width of the content area
aDesiredSize.mMaximumWidth = mTableLayoutStrategy->GetTableMaxWidth(aReflowState);
@ -1785,17 +1781,9 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.mMaximumWidth += aReflowState.mComputedPadding.left +
aReflowState.mComputedPadding.right;
// XXX to see if this is necessary
SetPreferredWidth(aDesiredSize.mMaximumWidth); // cache the value
// Initializing the table layout strategy assigns preliminary column
// widths. We can't leave the column widths this way, and so we need to
// balance the column widths to get them back to what we had previously.
// XXX It would be nice to have a cleaner way to calculate the updated
// maximum width
BalanceColumnWidths(aPresContext, aReflowState,
nsSize(aReflowState.availableWidth, aReflowState.availableHeight),
aDesiredSize.maxElementSize);
// Now the maximum width is valid
mBits.mMaximumWidthValid = PR_TRUE;
} else {
aDesiredSize.mMaximumWidth = GetPreferredWidth();
@ -4844,6 +4832,7 @@ void nsTableFrame::DebugReflow(nsIFrame* aFrame,
nsHTMLReflowMetrics* aMetrics,
nsReflowStatus aStatus)
{
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
// get the parent timer
const nsHTMLReflowState* parentRS = aState.parentReflowState;
nsReflowTimer* parentTimer = nsnull;
@ -4852,12 +4841,14 @@ void nsTableFrame::DebugReflow(nsIFrame* aFrame,
if (parentTimer) break;
parentRS = parentRS->parentReflowState;
}
#endif
// get the the frame summary timer
nsCOMPtr<nsIAtom> frameType = nsnull;
aFrame->GetFrameType(getter_AddRefs(frameType));
nsReflowTimer* frameTimer = GetFrameTimer(aFrame, frameType.get());
if (!frameTimer) {NS_ASSERTION(PR_FALSE, "no frame timer");return;}
if (!aMetrics) { // start
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
// create the reflow timer
nsReflowTimer* timer = new nsReflowTimer(aFrame);
// create the aux table timers if they don't exist
@ -4876,10 +4867,12 @@ void nsTableFrame::DebugReflow(nsIFrame* aFrame,
if (parentTimer) {
parentTimer->mChildren.AppendElement(timer);
}
#endif
// start the frame summary timer
frameTimer->Start();
}
else {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
// stop the reflow timer
nsReflowTimer* timer = (nsReflowTimer *)aState.mDebugHook;
if (timer) {
@ -4894,12 +4887,15 @@ void nsTableFrame::DebugReflow(nsIFrame* aFrame,
}
else {NS_ASSERTION(PR_FALSE, "bad DebugTimeReflow");return;}
// stop the frame summary timer
#endif
frameTimer->Stop();
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
if (!parentTimer) {
// print out all of the reflow timers
DebugReflowPrint(*timer, 0, PR_FALSE);
timer->Destroy();
}
#endif
}
}
@ -4909,11 +4905,15 @@ void nsTableFrame::DebugTimeNonPctCols(nsTableFrame& aFrame,
{
nsReflowTimer* timer = (nsReflowTimer*)aState.mDebugHook;
if (aStart) {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->Start();
#endif
aFrame.mTimer->mNextSibling->Start();
}
else {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->Stop();
#endif
aFrame.mTimer->mNextSibling->Stop();
}
}
@ -4924,11 +4924,15 @@ void nsTableFrame::DebugTimeNonPctColspans(nsTableFrame& aFrame,
{
nsReflowTimer* timer = (nsReflowTimer*)aState.mDebugHook;
if (aStart) {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->mNextSibling->Start();
#endif
aFrame.mTimer->mNextSibling->mNextSibling->Start();
}
else {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->mNextSibling->Stop();
#endif
aFrame.mTimer->mNextSibling->mNextSibling->Stop();
}
}
@ -4939,11 +4943,15 @@ void nsTableFrame::DebugTimePctCols(nsTableFrame& aFrame,
{
nsReflowTimer* timer = (nsReflowTimer*)aState.mDebugHook;
if (aStart) {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->mNextSibling->mNextSibling->Start();
#endif
aFrame.mTimer->mNextSibling->mNextSibling->mNextSibling->Start();
}
else {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->mNextSibling->mNextSibling->Stop();
#endif
aFrame.mTimer->mNextSibling->mNextSibling->mNextSibling->Stop();
}
}

View File

@ -95,6 +95,7 @@ NS_IMPL_RELEASE_INHERITED(nsTableOuterFrame, nsHTMLContainerFrame)
nsTableOuterFrame::nsTableOuterFrame()
{
mPriorAvailWidth = 0;
#ifdef DEBUG_TABLE_REFLOW_TIMING
mTimer = new nsReflowTimer(this);
#endif
@ -1440,64 +1441,75 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext,
mMinCaptionWidth = maxElementSize.width;
}
}
// At this point, we must have an inner table frame, and we might have a caption
NS_ASSERTION(mFrames.NotEmpty() && mInnerTableFrame, "incomplete children");
nsSize innerSize;
nsMargin innerMargin, innerMarginNoAuto, innerPadding;
// First reflow the inner table
nsHTMLReflowMetrics innerMet(aDesiredSize.maxElementSize);
rv = OuterReflowChild(aPresContext, mInnerTableFrame, aOuterRS, innerMet,
nsnull, innerSize, innerMargin, innerMarginNoAuto,
innerPadding, aOuterRS.reason, aStatus);
if (NS_FAILED(rv)) return rv;
if (NS_UNCONSTRAINEDSIZE == aOuterRS.availableWidth) {
// Remember the inner table's maximum width
mInnerTableMaximumWidth = innerMet.width;
if ((eReflowReason_Resize == aOuterRS.reason) &&
(aOuterRS.availableWidth == mPriorAvailWidth) &&
!mPrevInFlow) {
// don't do much if we are resize reflowed exactly like last time
nsRect rect;
GetRect(rect);
aDesiredSize.width = rect.width;
aDesiredSize.height = rect.height;
aStatus = NS_FRAME_COMPLETE;
}
else {
// At this point, we must have an inner table frame, and we might have a caption
NS_ASSERTION(mFrames.NotEmpty() && mInnerTableFrame, "incomplete children");
nsSize innerSize;
nsMargin innerMargin, innerMarginNoAuto, innerPadding;
nsPoint innerOrigin(0,0);
nsMargin captionMargin(0,0,0,0), captionMarginNoAuto(0,0,0,0), ignorePadding;
nsSize captionSize(0,0);
nsSize containSize = GetContainingBlockSize(aOuterRS);
// Now that we know the table width we can reflow the caption, and
// place the caption and the inner table
if (mCaptionFrame) {
// reflow the caption
nscoord availWidth = GetCaptionAvailWidth(aPresContext, mCaptionFrame, aOuterRS,
&innerSize.width, &innerMarginNoAuto);
nsHTMLReflowMetrics captionMet(nsnull);
nsReflowStatus capStatus; // don't let the caption cause incomplete
rv = OuterReflowChild(aPresContext, mCaptionFrame, aOuterRS, captionMet,
&availWidth, captionSize, captionMargin, captionMarginNoAuto,
ignorePadding, aOuterRS.reason, capStatus);
// First reflow the inner table
nsHTMLReflowMetrics innerMet(aDesiredSize.maxElementSize);
rv = OuterReflowChild(aPresContext, mInnerTableFrame, aOuterRS, innerMet,
nsnull, innerSize, innerMargin, innerMarginNoAuto,
innerPadding, aOuterRS.reason, aStatus);
if (NS_FAILED(rv)) return rv;
nsPoint captionOrigin;
if (NS_UNCONSTRAINEDSIZE == aOuterRS.availableWidth) {
// Remember the inner table's maximum width
mInnerTableMaximumWidth = innerMet.width;
}
GetCaptionOrigin(aPresContext, captionSide, containSize, innerSize,
innerMargin, captionSize, captionMargin, captionOrigin);
FinishReflowChild(mCaptionFrame, aPresContext, captionMet,
captionOrigin.x, captionOrigin.y, 0);
nsPoint innerOrigin(0,0);
nsMargin captionMargin(0,0,0,0), captionMarginNoAuto(0,0,0,0), ignorePadding;
nsSize captionSize(0,0);
nsSize containSize = GetContainingBlockSize(aOuterRS);
GetInnerOrigin(aPresContext, captionSide, containSize, captionSize,
// Now that we know the table width we can reflow the caption, and
// place the caption and the inner table
if (mCaptionFrame) {
// reflow the caption
nscoord availWidth = GetCaptionAvailWidth(aPresContext, mCaptionFrame, aOuterRS,
&innerSize.width, &innerMarginNoAuto);
nsHTMLReflowMetrics captionMet(nsnull);
nsReflowStatus capStatus; // don't let the caption cause incomplete
rv = OuterReflowChild(aPresContext, mCaptionFrame, aOuterRS, captionMet,
&availWidth, captionSize, captionMargin, captionMarginNoAuto,
ignorePadding, aOuterRS.reason, capStatus);
if (NS_FAILED(rv)) return rv;
nsPoint captionOrigin;
GetCaptionOrigin(aPresContext, captionSide, containSize, innerSize,
innerMargin, captionSize, captionMargin, captionOrigin);
FinishReflowChild(mCaptionFrame, aPresContext, captionMet,
captionOrigin.x, captionOrigin.y, 0);
GetInnerOrigin(aPresContext, captionSide, containSize, captionSize,
captionMargin, innerSize, innerMargin, innerOrigin);
// XXX If the height is constrained then we need to check whether the inner table still fits...
}
else {
GetInnerOrigin(aPresContext, captionSide, containSize, captionSize,
captionMargin, innerSize, innerMargin, innerOrigin);
}
// XXX If the height is constrained then we need to check whether the inner table still fits...
}
else {
GetInnerOrigin(aPresContext, captionSide, containSize, captionSize,
captionMargin, innerSize, innerMargin, innerOrigin);
FinishReflowChild(mInnerTableFrame, aPresContext, innerMet,
innerOrigin.x, innerOrigin.y, 0);
UpdateReflowMetrics(captionSide, aDesiredSize, innerMargin, innerMarginNoAuto,
innerPadding, captionMargin, captionMarginNoAuto);
}
FinishReflowChild(mInnerTableFrame, aPresContext, innerMet,
innerOrigin.x, innerOrigin.y, 0);
UpdateReflowMetrics(captionSide, aDesiredSize, innerMargin, innerMarginNoAuto,
innerPadding, captionMargin, captionMarginNoAuto);
}
// Return our desired rect
@ -1511,6 +1523,7 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.mMaximumWidth = ((nsTableFrame*)mInnerTableFrame)->GetPreferredWidth();
}
}
mPriorAvailWidth = aOuterRS.availableWidth;
#if defined DEBUG_TABLE_REFLOW | DEBUG_TABLE_REFLOW_TIMING
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aOuterRS, &aDesiredSize, aStatus);

View File

@ -358,6 +358,7 @@ private:
nsSize mMaxElementSize;
nscoord mInnerTableMaximumWidth;
nscoord mPriorAvailWidth;
#ifdef DEBUG_TABLE_REFLOW_TIMING
public:

View File

@ -1069,12 +1069,29 @@ BasicTableLayoutStrategy::ReduceOverSpecifiedPctCols(nscoord aExcess)
}
}
#ifdef DEBUG_TABLE_REFLOW_TIMING
nscoord WrapupAssignPctColumnWidths(nsTableFrame* aTableFrame,
const nsHTMLReflowState& aReflowState,
nscoord aValue)
{
nsTableFrame::DebugTimePctCols(*aTableFrame, (nsHTMLReflowState&)aReflowState, PR_FALSE);
return aValue;
}
#else
inline nscoord WrapupAssignPctColumnWidths(nsTableFrame* aTableFrame,
const nsHTMLReflowState& aReflowState,
nscoord aValue)
{
return aValue;
}
#endif
// Determine percentage col widths for each col frame
nscoord
BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState aReflowState,
nscoord aBasisIn,
PRBool aTableIsAutoWidth,
float aPixelToTwips)
BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflowState,
nscoord aBasisIn,
PRBool aTableIsAutoWidth,
float aPixelToTwips)
{
#ifdef DEBUG_TABLE_REFLOW_TIMING
nsTableFrame::DebugTimePctCols(*mTableFrame, (nsHTMLReflowState&)aReflowState, PR_TRUE);
@ -1088,7 +1105,8 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState aReflowS
nscoord basis; // basis to use for percentage based calculations
if (!aTableIsAutoWidth) {
if (NS_UNCONSTRAINEDSIZE == aBasisIn) {
return 0; // don't do the calculations on unconstrained basis
// don't do the calculations on unconstrained basis
return WrapupAssignPctColumnWidths(mTableFrame, aReflowState, 0);
}
basis = aBasisIn;
}
@ -1179,11 +1197,11 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState aReflowS
delete [] rawPctValues; // destroy the raw pct values
// If there are no pct cells or cols, there is nothing to do.
if ((0 == numPerCols) || (0.0f == perTotal)) {
return 0;
return WrapupAssignPctColumnWidths(mTableFrame, aReflowState, 0);
}
// If there is only one col and it is % based, it won't affect anything
if ((1 == numCols) && (numCols == numPerCols)) {
return 0;
return WrapupAssignPctColumnWidths(mTableFrame, aReflowState, 0);
}
// compute a basis considering total percentages and the desired width of everything else
@ -1379,10 +1397,7 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState aReflowS
ReduceOverSpecifiedPctCols(NSToCoordRound(((float)(colPctTotal - 100)) * 0.01f * (float)basis));
}
#ifdef DEBUG_TABLE_REFLOW_TIMING
nsTableFrame::DebugTimePctCols(*mTableFrame, (nsHTMLReflowState&)aReflowState, PR_FALSE);
#endif
return basis;
return WrapupAssignPctColumnWidths(mTableFrame, aReflowState, basis);
}
nscoord BasicTableLayoutStrategy::GetTableMinWidth() const

View File

@ -139,10 +139,10 @@ protected:
PRInt32& aLimitType,
float aPixelToTwips);
nscoord AssignPctColumnWidths(const nsHTMLReflowState aReflowState,
nscoord aBasis,
PRBool aTableIsAutoWidth,
float aPixelToTwips);
nscoord AssignPctColumnWidths(const nsHTMLReflowState& aReflowState,
nscoord aBasis,
PRBool aTableIsAutoWidth,
float aPixelToTwips);
void ReduceOverSpecifiedPctCols(nscoord aExcess);

View File

@ -653,41 +653,23 @@ PRInt32 nsTableCellFrame::GetColSpan()
return colSpan;
}
#define PROBABLY_TOO_LARGE 1000000
static
void DebugCheckChildSize(nsIFrame* aChild,
nsHTMLReflowMetrics& aMet,
nsSize& aAvailSize,
PRBool aIsPass2Reflow)
{
/* approved for commenting out by rickg
if (aMet.width > aAvailSize.width) {
nsAutoString tmp;
aChild->GetFrameName(tmp);
printf("WARNING: cell ");
fputs(tmp, stdout);
printf(" content has desired width %d given avail width %d\n",
aMet.width, aAvailSize.width);
}
*/
if (aIsPass2Reflow) {
if ((aMet.width < 0) || (aMet.width > 60000)) {
if ((aMet.width < 0) || (aMet.width > PROBABLY_TOO_LARGE)) {
printf("WARNING: cell content %p has large width %d \n", aChild, aMet.width);
}
if ((aMet.height < 0) || (aMet.height > 60000)) {
printf("WARNING: cell content %p has large height %d \n", aChild, aMet.height);
}
}
if (aMet.maxElementSize) {
nscoord tmp = aMet.maxElementSize->width;
if ((tmp < 0) || (tmp > 60000)) {
if ((tmp < 0) || (tmp > PROBABLY_TOO_LARGE)) {
printf("WARNING: cell content %p has large max element width %d \n", aChild, tmp);
}
tmp = aMet.maxElementSize->height;
if ((tmp < 0) || (tmp > 60000)) {
printf("WARNING: cell content %p has large max element height %d \n", aChild, tmp);
}
}
}

View File

@ -1769,10 +1769,6 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
}
}
else if (!IsMaximumWidthValid()) {
// Initialize the strategy and have it compute the natural size of
// the table
mTableLayoutStrategy->Initialize(aPresContext, nsnull, NS_UNCONSTRAINEDSIZE, aReflowState);
// Ask the strategy for the natural width of the content area
aDesiredSize.mMaximumWidth = mTableLayoutStrategy->GetTableMaxWidth(aReflowState);
@ -1785,17 +1781,9 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.mMaximumWidth += aReflowState.mComputedPadding.left +
aReflowState.mComputedPadding.right;
// XXX to see if this is necessary
SetPreferredWidth(aDesiredSize.mMaximumWidth); // cache the value
// Initializing the table layout strategy assigns preliminary column
// widths. We can't leave the column widths this way, and so we need to
// balance the column widths to get them back to what we had previously.
// XXX It would be nice to have a cleaner way to calculate the updated
// maximum width
BalanceColumnWidths(aPresContext, aReflowState,
nsSize(aReflowState.availableWidth, aReflowState.availableHeight),
aDesiredSize.maxElementSize);
// Now the maximum width is valid
mBits.mMaximumWidthValid = PR_TRUE;
} else {
aDesiredSize.mMaximumWidth = GetPreferredWidth();
@ -4844,6 +4832,7 @@ void nsTableFrame::DebugReflow(nsIFrame* aFrame,
nsHTMLReflowMetrics* aMetrics,
nsReflowStatus aStatus)
{
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
// get the parent timer
const nsHTMLReflowState* parentRS = aState.parentReflowState;
nsReflowTimer* parentTimer = nsnull;
@ -4852,12 +4841,14 @@ void nsTableFrame::DebugReflow(nsIFrame* aFrame,
if (parentTimer) break;
parentRS = parentRS->parentReflowState;
}
#endif
// get the the frame summary timer
nsCOMPtr<nsIAtom> frameType = nsnull;
aFrame->GetFrameType(getter_AddRefs(frameType));
nsReflowTimer* frameTimer = GetFrameTimer(aFrame, frameType.get());
if (!frameTimer) {NS_ASSERTION(PR_FALSE, "no frame timer");return;}
if (!aMetrics) { // start
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
// create the reflow timer
nsReflowTimer* timer = new nsReflowTimer(aFrame);
// create the aux table timers if they don't exist
@ -4876,10 +4867,12 @@ void nsTableFrame::DebugReflow(nsIFrame* aFrame,
if (parentTimer) {
parentTimer->mChildren.AppendElement(timer);
}
#endif
// start the frame summary timer
frameTimer->Start();
}
else {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
// stop the reflow timer
nsReflowTimer* timer = (nsReflowTimer *)aState.mDebugHook;
if (timer) {
@ -4894,12 +4887,15 @@ void nsTableFrame::DebugReflow(nsIFrame* aFrame,
}
else {NS_ASSERTION(PR_FALSE, "bad DebugTimeReflow");return;}
// stop the frame summary timer
#endif
frameTimer->Stop();
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
if (!parentTimer) {
// print out all of the reflow timers
DebugReflowPrint(*timer, 0, PR_FALSE);
timer->Destroy();
}
#endif
}
}
@ -4909,11 +4905,15 @@ void nsTableFrame::DebugTimeNonPctCols(nsTableFrame& aFrame,
{
nsReflowTimer* timer = (nsReflowTimer*)aState.mDebugHook;
if (aStart) {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->Start();
#endif
aFrame.mTimer->mNextSibling->Start();
}
else {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->Stop();
#endif
aFrame.mTimer->mNextSibling->Stop();
}
}
@ -4924,11 +4924,15 @@ void nsTableFrame::DebugTimeNonPctColspans(nsTableFrame& aFrame,
{
nsReflowTimer* timer = (nsReflowTimer*)aState.mDebugHook;
if (aStart) {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->mNextSibling->Start();
#endif
aFrame.mTimer->mNextSibling->mNextSibling->Start();
}
else {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->mNextSibling->Stop();
#endif
aFrame.mTimer->mNextSibling->mNextSibling->Stop();
}
}
@ -4939,11 +4943,15 @@ void nsTableFrame::DebugTimePctCols(nsTableFrame& aFrame,
{
nsReflowTimer* timer = (nsReflowTimer*)aState.mDebugHook;
if (aStart) {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->mNextSibling->mNextSibling->Start();
#endif
aFrame.mTimer->mNextSibling->mNextSibling->mNextSibling->Start();
}
else {
#ifdef DEBUG_TABLE_REFLOW_TIMING_DETAIL
timer->mNextSibling->mNextSibling->mNextSibling->Stop();
#endif
aFrame.mTimer->mNextSibling->mNextSibling->mNextSibling->Stop();
}
}

View File

@ -95,6 +95,7 @@ NS_IMPL_RELEASE_INHERITED(nsTableOuterFrame, nsHTMLContainerFrame)
nsTableOuterFrame::nsTableOuterFrame()
{
mPriorAvailWidth = 0;
#ifdef DEBUG_TABLE_REFLOW_TIMING
mTimer = new nsReflowTimer(this);
#endif
@ -1440,64 +1441,75 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext,
mMinCaptionWidth = maxElementSize.width;
}
}
// At this point, we must have an inner table frame, and we might have a caption
NS_ASSERTION(mFrames.NotEmpty() && mInnerTableFrame, "incomplete children");
nsSize innerSize;
nsMargin innerMargin, innerMarginNoAuto, innerPadding;
// First reflow the inner table
nsHTMLReflowMetrics innerMet(aDesiredSize.maxElementSize);
rv = OuterReflowChild(aPresContext, mInnerTableFrame, aOuterRS, innerMet,
nsnull, innerSize, innerMargin, innerMarginNoAuto,
innerPadding, aOuterRS.reason, aStatus);
if (NS_FAILED(rv)) return rv;
if (NS_UNCONSTRAINEDSIZE == aOuterRS.availableWidth) {
// Remember the inner table's maximum width
mInnerTableMaximumWidth = innerMet.width;
if ((eReflowReason_Resize == aOuterRS.reason) &&
(aOuterRS.availableWidth == mPriorAvailWidth) &&
!mPrevInFlow) {
// don't do much if we are resize reflowed exactly like last time
nsRect rect;
GetRect(rect);
aDesiredSize.width = rect.width;
aDesiredSize.height = rect.height;
aStatus = NS_FRAME_COMPLETE;
}
else {
// At this point, we must have an inner table frame, and we might have a caption
NS_ASSERTION(mFrames.NotEmpty() && mInnerTableFrame, "incomplete children");
nsSize innerSize;
nsMargin innerMargin, innerMarginNoAuto, innerPadding;
nsPoint innerOrigin(0,0);
nsMargin captionMargin(0,0,0,0), captionMarginNoAuto(0,0,0,0), ignorePadding;
nsSize captionSize(0,0);
nsSize containSize = GetContainingBlockSize(aOuterRS);
// Now that we know the table width we can reflow the caption, and
// place the caption and the inner table
if (mCaptionFrame) {
// reflow the caption
nscoord availWidth = GetCaptionAvailWidth(aPresContext, mCaptionFrame, aOuterRS,
&innerSize.width, &innerMarginNoAuto);
nsHTMLReflowMetrics captionMet(nsnull);
nsReflowStatus capStatus; // don't let the caption cause incomplete
rv = OuterReflowChild(aPresContext, mCaptionFrame, aOuterRS, captionMet,
&availWidth, captionSize, captionMargin, captionMarginNoAuto,
ignorePadding, aOuterRS.reason, capStatus);
// First reflow the inner table
nsHTMLReflowMetrics innerMet(aDesiredSize.maxElementSize);
rv = OuterReflowChild(aPresContext, mInnerTableFrame, aOuterRS, innerMet,
nsnull, innerSize, innerMargin, innerMarginNoAuto,
innerPadding, aOuterRS.reason, aStatus);
if (NS_FAILED(rv)) return rv;
nsPoint captionOrigin;
if (NS_UNCONSTRAINEDSIZE == aOuterRS.availableWidth) {
// Remember the inner table's maximum width
mInnerTableMaximumWidth = innerMet.width;
}
GetCaptionOrigin(aPresContext, captionSide, containSize, innerSize,
innerMargin, captionSize, captionMargin, captionOrigin);
FinishReflowChild(mCaptionFrame, aPresContext, captionMet,
captionOrigin.x, captionOrigin.y, 0);
nsPoint innerOrigin(0,0);
nsMargin captionMargin(0,0,0,0), captionMarginNoAuto(0,0,0,0), ignorePadding;
nsSize captionSize(0,0);
nsSize containSize = GetContainingBlockSize(aOuterRS);
GetInnerOrigin(aPresContext, captionSide, containSize, captionSize,
// Now that we know the table width we can reflow the caption, and
// place the caption and the inner table
if (mCaptionFrame) {
// reflow the caption
nscoord availWidth = GetCaptionAvailWidth(aPresContext, mCaptionFrame, aOuterRS,
&innerSize.width, &innerMarginNoAuto);
nsHTMLReflowMetrics captionMet(nsnull);
nsReflowStatus capStatus; // don't let the caption cause incomplete
rv = OuterReflowChild(aPresContext, mCaptionFrame, aOuterRS, captionMet,
&availWidth, captionSize, captionMargin, captionMarginNoAuto,
ignorePadding, aOuterRS.reason, capStatus);
if (NS_FAILED(rv)) return rv;
nsPoint captionOrigin;
GetCaptionOrigin(aPresContext, captionSide, containSize, innerSize,
innerMargin, captionSize, captionMargin, captionOrigin);
FinishReflowChild(mCaptionFrame, aPresContext, captionMet,
captionOrigin.x, captionOrigin.y, 0);
GetInnerOrigin(aPresContext, captionSide, containSize, captionSize,
captionMargin, innerSize, innerMargin, innerOrigin);
// XXX If the height is constrained then we need to check whether the inner table still fits...
}
else {
GetInnerOrigin(aPresContext, captionSide, containSize, captionSize,
captionMargin, innerSize, innerMargin, innerOrigin);
}
// XXX If the height is constrained then we need to check whether the inner table still fits...
}
else {
GetInnerOrigin(aPresContext, captionSide, containSize, captionSize,
captionMargin, innerSize, innerMargin, innerOrigin);
FinishReflowChild(mInnerTableFrame, aPresContext, innerMet,
innerOrigin.x, innerOrigin.y, 0);
UpdateReflowMetrics(captionSide, aDesiredSize, innerMargin, innerMarginNoAuto,
innerPadding, captionMargin, captionMarginNoAuto);
}
FinishReflowChild(mInnerTableFrame, aPresContext, innerMet,
innerOrigin.x, innerOrigin.y, 0);
UpdateReflowMetrics(captionSide, aDesiredSize, innerMargin, innerMarginNoAuto,
innerPadding, captionMargin, captionMarginNoAuto);
}
// Return our desired rect
@ -1511,6 +1523,7 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.mMaximumWidth = ((nsTableFrame*)mInnerTableFrame)->GetPreferredWidth();
}
}
mPriorAvailWidth = aOuterRS.availableWidth;
#if defined DEBUG_TABLE_REFLOW | DEBUG_TABLE_REFLOW_TIMING
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aOuterRS, &aDesiredSize, aStatus);

View File

@ -358,6 +358,7 @@ private:
nsSize mMaxElementSize;
nscoord mInnerTableMaximumWidth;
nscoord mPriorAvailWidth;
#ifdef DEBUG_TABLE_REFLOW_TIMING
public: