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:
parent
08ac70912c
commit
b45820e80c
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -358,6 +358,7 @@ private:
|
||||
|
||||
nsSize mMaxElementSize;
|
||||
nscoord mInnerTableMaximumWidth;
|
||||
nscoord mPriorAvailWidth;
|
||||
|
||||
#ifdef DEBUG_TABLE_REFLOW_TIMING
|
||||
public:
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -358,6 +358,7 @@ private:
|
||||
|
||||
nsSize mMaxElementSize;
|
||||
nscoord mInnerTableMaximumWidth;
|
||||
nscoord mPriorAvailWidth;
|
||||
|
||||
#ifdef DEBUG_TABLE_REFLOW_TIMING
|
||||
public:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user