diff --git a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp
index 6627d57e0b7..7712953e951 100644
--- a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp
+++ b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp
@@ -217,14 +217,15 @@ PRBool BasicTableLayoutStrategy::IsFixedWidth(const nsStylePosition* aStylePosit
}
-BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame)
+BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame, PRBool aIsNavQuirks)
{
NS_ASSERTION(nsnull != aFrame, "bad frame arg");
- mTableFrame = aFrame;
- mMinTableWidth = 0;
- mMaxTableWidth = 0;
- mFixedTableWidth = 0;
+ mTableFrame = aFrame;
+ mMinTableWidth = 0;
+ mMaxTableWidth = 0;
+ mFixedTableWidth = 0;
+ mIsNavQuirksMode = aIsNavQuirks;
}
BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
@@ -416,9 +417,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
nscoord effectiveMaxColumnWidth = 0; // max col width ignoring cells with colspans
nscoord specifiedFixedColWidth = 0; // the width of the column if given stylistically (or via cell Width attribute)
// only applicable if haveColWidth==PR_TRUE
- PRBool haveColWidth = PR_FALSE; // if true, the column has a width either from HTML width attribute,
- // from a style rule on the column,
- // or from a width attr/style on a cell that has colspan==1
+
horPadding[colIndex] = 0;
// Get column information
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colIndex);
@@ -433,7 +432,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
// Get fixed column width if it has one
if (eStyleUnit_Coord == colPosition->mWidth.GetUnit()) {
- haveColWidth = PR_TRUE;
+ colFrame->SetHasConstrainedWidth(PR_TRUE);
specifiedFixedColWidth = colPosition->mWidth.GetCoordValue();
horPadding[colIndex] = CalcHorizontalPadding(colIndex);
specifiedFixedColWidth += horPadding[colIndex];
@@ -489,7 +488,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
rowIndex, colSpan, cellMinSize.width, cellMinSize.height,
cellDesiredSize.width, cellDesiredSize.height);
- if (PR_TRUE == haveColWidth) {
+ if (colFrame->HasConstrainedWidth()) {
// This col has a specified coord fixed width, so set the min and max width to the larger of
// (specified width, largest max_element_size of the cells in the column)
// factoring in the min width of the prior cells (stored in minColWidth)
@@ -594,13 +593,13 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
} // end for (rowIndex = 0; rowIndex < numRows; rowIndex++)
// adjust the "fixed" width for content that is too wide
- if (haveColWidth && (effectiveMinColumnWidth > specifiedFixedColWidth)) {
+ if (colFrame->HasConstrainedWidth() && (effectiveMinColumnWidth > specifiedFixedColWidth)) {
specifiedFixedColWidth = effectiveMinColumnWidth;
}
// do all the global bookkeeping, factoring in margins
nscoord colInset = mTableFrame->GetCellSpacingX();
// keep a running total of the amount of space taken up by all fixed-width columns
- if ((PR_TRUE == haveColWidth) &&
+ if ((colFrame->HasConstrainedWidth()) &&
(nsTableColFrame::eWIDTH_SOURCE_CELL == colFrame->GetWidthSource())) {
mFixedTableWidth += specifiedFixedColWidth + colInset;
if (0 == colIndex) {
@@ -616,7 +615,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
colFrame->SetEffectiveMaxColWidth(effectiveMaxColumnWidth);
// this is the default, the real adjustment happens below where we deal with colspans
colFrame->SetAdjustedMinColWidth(effectiveMinColumnWidth);
- if ((PR_TRUE == haveColWidth) &&
+ if ((colFrame->HasConstrainedWidth()) &&
(nsTableColFrame::eWIDTH_SOURCE_CELL_WITH_SPAN!=colFrame->GetWidthSource())) {
mTableFrame->SetColumnWidth(colIndex, specifiedFixedColWidth);
}
@@ -1740,9 +1739,7 @@ PRBool BasicTableLayoutStrategy::
if (PR_FALSE == IsFixedWidth(colPosition, colTableStyle)) {
// compute the spanning cell's contribution to the column min width
nscoord spanCellMinWidth;
- PRBool needsExtraMinWidth = PR_FALSE;
- //if (spanInfo->effectiveMinWidthOfSpannedColscellMinWidth)
- // needsExtraMinWidth = PR_TRUE;
+ PRBool needsExtraMinWidth = (spanInfo->effectiveMinWidthOfSpannedCols < spanInfo->cellMinWidth);
if (PR_TRUE == needsExtraMinWidth) {
if (0 != spanInfo->effectiveMinWidthOfSpannedCols) {
spanCellMinWidth = (spanInfo->cellMinWidth * colFrame->GetEffectiveMinColWidth()) /
@@ -1951,7 +1948,7 @@ PRBool BasicTableLayoutStrategy::
colIndex, mTableFrame->GetColumnWidth(colIndex), aAvailWidth, colInset);
}
else if (PR_TRUE==isAutoWidth) { // column's width is determined by its content, done in post-processing
- mTableFrame->SetColumnWidth(colIndex, minColWidth); // reserve the column's min width
+ mTableFrame->SetColumnWidth(colIndex, minColWidth); // reserve the column's min width
atLeastOneAutoWidthColumn = PR_TRUE;
}
else if (-1 != specifiedProportionColumnWidth) {
@@ -2080,36 +2077,200 @@ PRBool BasicTableLayoutStrategy::
}
struct nsColInfo {
- nsColInfo(nsTableColFrame* aColFrame,
- PRInt32 aColIndex,
- PRInt32 aColWidth,
- float aMaximizeFactor)
- : mColFrame(aColFrame), mColIndex(aColIndex), mColWidth(aColWidth),
- mMaximizeFactor(aMaximizeFactor)
- {}
- nsTableColFrame* mColFrame;
- PRInt32 mColIndex;
- PRInt32 mColWidth;
- float mMaximizeFactor;
+ nsColInfo(nsTableColFrame* aFrame,
+ PRInt32 aIndex,
+ PRInt32 aMinWidth,
+ PRInt32 aWidth,
+ PRInt32 aMaxEffWidth,
+ PRInt32 aMaxWidth)
+ : mFrame(aFrame), mIndex(aIndex), mMinWidth(aMinWidth),
+ mWidth(aWidth), mMaxEffWidth(aMaxEffWidth), mMaxWidth(aMaxWidth), mWeight(0)
+ {}
+ nsTableColFrame* mFrame;
+ PRInt32 mIndex;
+ PRInt32 mMinWidth;
+ PRInt32 mWidth;
+ PRInt32 mMaxEffWidth;
+ PRInt32 mMaxWidth;
+ float mWeight;
};
void
-DistributeRemainingSpaceCleanup(PRInt32 aNumItems, nsColInfo** aInfoArray)
+DRS_Wrapup(nsTableFrame* aTableFrame,
+ PRInt32 aNumItems,
+ nsColInfo** aColInfo)
{
for (int i = 0; i < aNumItems; i++) {
- delete aInfoArray[i];
+ aTableFrame->SetColumnWidth(aColInfo[i]->mIndex, aColInfo[i]->mWidth);
+ delete aColInfo[i];
+ }
+ delete [] aColInfo;
+}
+
+void
+DRS_Increase(PRInt32 aNumAutoCols,
+ nsColInfo** aColInfo,
+ PRInt32 aDivisor,
+ PRBool aDontGoOverMax,
+ PRInt32& aAvailWidth)
+{
+ for (PRInt32 i = 0; i < aNumAutoCols; i++) {
+ if ((aAvailWidth <= 0) || (aDivisor <= 0)) {
+ break;
+ }
+ //float percent = ((float)aColInfo[i]->mMaxEffWidth) / (float)aDivisor;
+ float percent = ((float)aColInfo[i]->mMaxWidth) / (float)aDivisor;
+ //aDivisor -= aColInfo[i]->mWidth;
+ aDivisor -= aColInfo[i]->mMaxWidth;
+ nscoord addition = PR_MIN(aAvailWidth, NSToCoordRound(((float)(aAvailWidth)) * percent));
+ if (aDontGoOverMax) {
+ addition = PR_MIN(addition, aColInfo[i]->mMaxWidth - aColInfo[i]->mWidth);
+ }
+ // don't let the total additions exceed what is available
+ if (i == aNumAutoCols - 1) {
+ addition = PR_MIN(addition, aAvailWidth);
+ }
+ aColInfo[i]->mWidth += addition;
+ aAvailWidth -= addition;
+ }
+}
+
+void
+DRS_Decrease(PRInt32 aNumAutoCols,
+ nsColInfo** aColInfo,
+ PRInt32 aDivisor,
+ PRInt32& aExcess)
+{
+ for (PRInt32 i = 0; i < aNumAutoCols; i++) {
+ if ((aExcess <= 0) || (aDivisor <= 0)) {
+ break;
+ }
+ //float percent = ((float)aColInfo[i]->mMaxEffWidth) / (float)aDivisor;
+ float percent = ((float)aColInfo[i]->mMaxWidth) / (float)aDivisor;
+ //aDivisor -= aColInfo[i]->mWidth;
+ aDivisor -= aColInfo[i]->mMaxWidth;
+ nscoord reduction = PR_MIN(aExcess, NSToCoordRound(((float)(aExcess)) * percent));
+ // don't go over the col min
+ reduction = PR_MIN(reduction, aColInfo[i]->mWidth - aColInfo[i]->mMinWidth);
+ // don't let the total reductions exceed what is available
+ if (i == aNumAutoCols - 1) {
+ reduction = PR_MIN(reduction, aExcess);
+ }
+ aColInfo[i]->mWidth -= reduction;
+ aExcess -= reduction;
+ }
+}
+
+
+void
+DSR_Sort(nsColInfo** aColInfo, PRInt32 aNumCols)
+{
+ // sort the cols based on the Weight
+ for (PRInt32 j = aNumCols - 1; j > 0; j--) {
+ for (PRInt32 i = 0; i < j; i++) {
+ if (aColInfo[i]->mWeight < aColInfo[i+1]->mWeight) { // swap them
+ nsColInfo* save = aColInfo[i];
+ aColInfo[i] = aColInfo[i+1];
+ aColInfo[i+1] = save;
+ }
+ }
}
- delete [] aInfoArray;
}
// Take the remaining space in the table and distribute it to the auto-width cols
-// in the table. If a col reaches its desired width, stop at that width unless all
-// other cols have reached their desired widths.
+// in the table.
+void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecifiedWidth,
+ nscoord& aComputedTableWidth,
+ PRBool aTableIsAutoWidth)
+{
+ // availWidth is the difference between the total available width and the
+ // amount of space already assigned.
+ nscoord availWidth = PR_MAX(aTableSpecifiedWidth - aComputedTableWidth, 0);
+ TDBG_SDD(" aTableSpecifiedWidth specified as %d, availWidth is = %d\n", aTableSpecifiedWidth, availWidth);
+ if ((0 == availWidth) || (aTableSpecifiedWidth <= 0)) {
+ return;
+ }
-// This algorithm has been reworked from the orignal to fix bugs (e.g. bug 6184)
-// and remove the recursion. For auto width tables it uses colFrame->GetMaxColSize()
-// instead of GetMaxEffectiveColSize, so for some auto width tables with colspans
-// it claculates more like IE5 than Nav4.5, which appears to be more reasonable.
+ // Get the auto width cols. Only they get adjusted.
+ PRInt32 numAutoCols = 0;
+ PRInt32* autoCols = nsnull;
+ mTableFrame->GetColumnsByType(eStyleUnit_Auto, numAutoCols, autoCols);
+ if (0 == numAutoCols) {
+ return;
+ }
+ nsColInfo** colInfo = new nsColInfo*[numAutoCols];
+
+ nscoord totalDivisor = 0;
+ nscoord totalAutoWidthGiven = 0;
+ PRInt32 i;
+
+ // start out by giving each col its max effective width (or adj width if it is greater)
+ // for standard mode and its min width for nav quirks mode
+ for (i = 0; i < numAutoCols; i++) {
+ PRInt32 colIndex = autoCols[i];
+ nsTableColFrame* colFrame = mTableFrame->GetColFrame(autoCols[i]);
+ nscoord origWidth = mTableFrame->GetColumnWidth(autoCols[i]);
+ nscoord minWidth = PR_MAX(colFrame->GetAdjustedMinColWidth(), origWidth);
+ nscoord maxEffWidth = PR_MAX(colFrame->GetEffectiveMaxColWidth(), minWidth);
+ nscoord maxWidth = colFrame->GetMaxColWidth();
+ nscoord startWidth = (mIsNavQuirksMode) ? minWidth : maxWidth;
+ colInfo[i] = new nsColInfo(colFrame, autoCols[i], minWidth, startWidth, maxEffWidth, maxWidth);
+// totalDivisor += maxEffWidth;
+ totalDivisor += maxWidth;
+ totalAutoWidthGiven += startWidth - origWidth;
+ }
+
+ availWidth = aTableSpecifiedWidth - aComputedTableWidth - totalAutoWidthGiven;
+
+ if (availWidth >= 0) { // have more space to allocate
+ for (i = 0; i < numAutoCols; i++) {
+ // the weight here is a relative metric for determining when cols reach their max.
+ // A col with a larger weight will reach its max before one with a smaller value.
+ nscoord delta = colInfo[i]->mMaxWidth - colInfo[i]->mWidth;
+ colInfo[i]->mWeight = (delta <= 0)
+ ? 1000000 // cols which have already reached their max get a large value
+ : ((float)colInfo[i]->mMaxWidth) / ((float)delta);
+ }
+
+ // sort the cols based on the weight so that in one pass cols with higher
+ // weights will get their max earlier than ones with lower weights
+ // This is an innefficient bubble sort, but unless there are an unlikely
+ // large number of cols, it is not an issue.
+ DSR_Sort(colInfo, numAutoCols);
+
+ // compute the proportion to be added to each column, don't go beyond the col's
+ // max. This algorithm assumes that the Weight works as stated above
+ DRS_Increase(numAutoCols, colInfo, totalDivisor, PR_TRUE, availWidth);
+ // if every col got its max and there is more to go, allocate a 2nd time
+ if (!aTableIsAutoWidth && (availWidth > 0)) {
+ DRS_Increase(numAutoCols, colInfo, totalDivisor, PR_FALSE, availWidth);
+ }
+ aComputedTableWidth = aTableSpecifiedWidth - availWidth;
+ }
+ else { // reduce each col width if appropriate
+ for (i = 0; i < numAutoCols; i++) {
+ // the weight here is a relative metric for determining when cols reach their min.
+ // A col with a larger weight will reach its min before one with a smaller value.
+ nscoord delta = colInfo[i]->mWidth - colInfo[i]->mMinWidth;
+ colInfo[i]->mWeight = (delta <= 0)
+ ? 1000000 // cols which have already reached their min get a large value
+ : ((float)colInfo[i]->mWidth) / ((float)delta);
+ }
+
+ // sort the cols based on the Weight
+ DSR_Sort(colInfo, numAutoCols);
+
+ // compute the proportion to be subtracted from each column, don't go beyond
+ // the col's min. This algorithm assumes that the Weight works as stated above
+ PRInt32 totalExcessGiven = -availWidth;
+ DRS_Decrease(numAutoCols, colInfo, totalDivisor, totalExcessGiven);
+ aComputedTableWidth = aTableSpecifiedWidth + totalExcessGiven;
+ }
+ DRS_Wrapup(mTableFrame, numAutoCols, colInfo);
+ TDBG_WIDTHS4("at end of DistributeRemainingSpace: ",PR_FALSE,PR_FALSE);
+}
+
+#if 0
void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecifiedWidth,
nscoord& aComputedTableWidth,
PRBool aTableIsAutoWidth)
@@ -2141,21 +2302,19 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecified
PRInt32 colIndex = autoColumns[i];
nsTableColFrame* colFrame = mTableFrame->GetColFrame(autoColumns[i]);
nscoord startingColWidth = mTableFrame->GetColumnWidth(colIndex);
- nscoord maxColWidth = (PR_FALSE == aTableIsAutoWidth)
- ? colFrame->GetEffectiveMaxColWidth() : colFrame->GetMaxColWidth();
- if ((PR_FALSE == aTableIsAutoWidth) || (startingColWidth < maxColWidth)) {
- if (0 == maxColWidth)
- maxColWidth = startingColWidth;
- totalResizeColWidth += maxColWidth;
- // the maximizeFactor is a relative metric for determining when cols reach their max.
- // A col with a smaller value will reach its max before one with a larger value.
- nscoord delta = maxColWidth - startingColWidth;
- float maximizeFactor = (0 == delta)
- ? 1000000 : ((float)maxColWidth) / ((float)(maxColWidth - startingColWidth));
- resizeCols[numResizeCols] = new nsColInfo(colFrame, colIndex, startingColWidth,
- maximizeFactor);
- numResizeCols++;
- }
+ nscoord maxColWidth = colFrame->GetMaxColWidth();
+ if (0 == maxColWidth)
+ maxColWidth = startingColWidth;
+ totalResizeColWidth += maxColWidth;
+ // the maximizeFactor is a relative metric for determining when cols reach their max.
+ // A col with a smaller value will reach its max before one with a larger value.
+ nscoord delta = maxColWidth - startingColWidth;
+ float maximizeFactor = (0 >= delta)
+ ? 1000000 // cols which have already reached their max get a large value
+ : ((float)maxColWidth) / ((float)(maxColWidth - startingColWidth));
+ resizeCols[numResizeCols] = new nsColInfo(colFrame, colIndex, startingColWidth,
+ maximizeFactor);
+ numResizeCols++;
}
if (totalResizeColWidth <= 0) {
NS_ASSERTION(PR_TRUE, "need to handle this case");
@@ -2187,10 +2346,7 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecified
}
nsTableColFrame* colFrame = resizeCols[i]->mColFrame;
nscoord startingColWidth = resizeCols[i]->mColWidth;
- nscoord maxColWidth = (PR_FALSE == aTableIsAutoWidth)
- ? colFrame->GetEffectiveMaxColWidth() : colFrame->GetMaxColWidth();
- // if we actually have room to distribute, do it here
- // otherwise, the auto columns already are set to their minimum
+ nscoord maxColWidth = colFrame->GetMaxColWidth();
float percent = ((float)maxColWidth) / (float)totalResizeColWidthRemaining;
nscoord delta = PR_MIN(availWidth, NSToCoordRound(((float)(availWidth)) * percent));
// don't go over the col max right now
@@ -2214,7 +2370,7 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecified
}
nsTableColFrame* colFrame = resizeCols[i]->mColFrame;
nscoord startingColWidth = resizeCols[i]->mColWidth;
- nscoord maxColWidth = colFrame->GetEffectiveMaxColWidth();
+ nscoord maxColWidth = colFrame->GetMaxColWidth();
// if we actually have room to distribute, do it here
float percent = ((float)maxColWidth) / (float)totalResizeColWidth;
nscoord delta = PR_MIN(availWidth, NSToCoordRound(((float)(availWidth)) * percent));
@@ -2229,6 +2385,7 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecified
DistributeRemainingSpaceCleanup(numResizeCols, resizeCols);
TDBG_WIDTHS4("at end of DistributeRemainingSpace: ",PR_FALSE,PR_FALSE);
}
+#endif
void BasicTableLayoutStrategy::AdjustTableThatIsTooWide(nscoord aComputedWidth,
nscoord aTableWidth,
diff --git a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h
index 121c4baafd5..375d82ae4fc 100644
--- a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h
+++ b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h
@@ -80,7 +80,8 @@ public:
/** Public constructor.
* @paran aFrame the table frame for which this delegate will do layout
*/
- BasicTableLayoutStrategy(nsTableFrame *aFrame);
+ BasicTableLayoutStrategy(nsTableFrame *aFrame,
+ PRBool aIsNavQuirksMode = PR_TRUE);
/** destructor */
virtual ~BasicTableLayoutStrategy();
@@ -288,6 +289,7 @@ protected:
nscoord mMinTableWidth; // the smallest size for the table
nscoord mMaxTableWidth; // the "natural" size for the table, if unconstrained
nscoord mFixedTableWidth; // the amount of space taken up by fixed-width columns
+ PRBool mIsNavQuirksMode;
};
diff --git a/mozilla/layout/html/table/src/nsTableColFrame.h b/mozilla/layout/html/table/src/nsTableColFrame.h
index 704088a0ece..876b321160d 100644
--- a/mozilla/layout/html/table/src/nsTableColFrame.h
+++ b/mozilla/layout/html/table/src/nsTableColFrame.h
@@ -79,9 +79,17 @@ public:
nscoord GetEffectiveMinColWidth();
void SetEffectiveMinColWidth(nscoord aMinColWidth);
+ // return the min width for this column after provisions for col spans have
+ // been included. The adj min width is >= the min width.
nscoord GetAdjustedMinColWidth();
void SetAdjustedMinColWidth(nscoord aMinColWidth);
+ // Return true if the column has a width either from HTML width attribute,
+ // from a style rule on the column, from a width attr/style on a cell
+ // that has colspan==1.
+ PRBool HasConstrainedWidth();
+ void SetHasConstrainedWidth(PRBool aIsConstrained);
+
PRInt32 GetWidthSource();
void SetWidthSource(PRInt32 aMinColWidth);
@@ -106,6 +114,8 @@ protected:
nscoord mMinAdjustedColWidth;
+ PRBool mHasConstrainedWidth;
+
PRInt32 mWidthSource;
};
@@ -150,6 +160,12 @@ inline void nsTableColFrame::SetEffectiveMinColWidth(nscoord aMinEffectiveColWid
inline nscoord nsTableColFrame::GetAdjustedMinColWidth()
{ return mMinAdjustedColWidth; }
+inline PRBool nsTableColFrame::HasConstrainedWidth()
+{ return mHasConstrainedWidth; }
+
+inline void nsTableColFrame::SetHasConstrainedWidth(PRBool aIsConstrained)
+{ mHasConstrainedWidth = aIsConstrained; }
+
inline void nsTableColFrame::SetAdjustedMinColWidth(nscoord aMinAdjustedColWidth)
{ mMinAdjustedColWidth = aMinAdjustedColWidth; }
diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp
index 97b62c57bfd..2511a145cbf 100644
--- a/mozilla/layout/html/table/src/nsTableFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableFrame.cpp
@@ -3965,10 +3965,12 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext& aPresContext,
// based on the compatibility mode, create a table layout strategy
if (nsnull==mTableLayoutStrategy)
{
+ nsCompatibility mode;
+ aPresContext.GetCompatibilityMode(&mode);
if (PR_FALSE==RequiresPass1Layout())
mTableLayoutStrategy = new FixedTableLayoutStrategy(this);
else
- mTableLayoutStrategy = new BasicTableLayoutStrategy(this);
+ mTableLayoutStrategy = new BasicTableLayoutStrategy(this, eCompatibility_NavQuirks == mode);
mTableLayoutStrategy->Initialize(aMaxElementSize, GetColCount());
mColumnWidthsValid=PR_TRUE;
}
diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
index 72840825e02..86234b517e6 100644
--- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
@@ -524,6 +524,13 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState)
{
if (gsDebug) printf("TRGF CalculateRowHeights begin\n");
+ nsTableFrame *tableFrame=nsnull;
+ nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
+ if (NS_FAILED(rv) || nsnull==tableFrame)
+ return;
+ // all table cells have the same top and bottom margins, namely cellSpacingY
+ nscoord cellSpacingY = tableFrame->GetCellSpacingY();
+
// iterate children and for each row get its height
PRInt32 numRows;
GetRowCount(numRows);
@@ -549,22 +556,24 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
// get the height of the tallest cell in the row (excluding cells that span rows)
+ // XXX GetChildMaxTopMargin and GetChildMaxBottomMargin should be removed/simplified because
+ // according to CSS, all table cells must have the same top/bottom and left/right margins.
nscoord maxCellHeight = ((nsTableRowFrame*)rowFrame)->GetTallestChild();
nscoord maxCellTopMargin = ((nsTableRowFrame*)rowFrame)->GetChildMaxTopMargin();
nscoord maxCellBottomMargin = ((nsTableRowFrame*)rowFrame)->GetChildMaxBottomMargin();
nscoord maxRowHeight = maxCellHeight + maxCellTopMargin + maxCellBottomMargin;
- if (gsDebug) printf("TRGF CalcRowH: for row %d(%p), maxCellH=%d, maxCTopMargin=%d, maxCBM=%d\n",
- rowIndex + startRowIndex, rowFrame, maxCellHeight, maxCellTopMargin, maxCellBottomMargin);
+ // only the top row has a top margin. Other rows start at the bottom of the prev row's bottom margin.
+ if (gsDebug) printf("TRGF CalcRowH: for row %d(%p), maxCellH=%d, spacingY=%d, d\n",
+ rowIndex + startRowIndex, rowFrame, maxCellHeight, cellSpacingY);
if (gsDebug) printf(" rowHeight=%d\n", maxRowHeight);
// save the row height for pass 2 below
rowHeights[rowIndex] = maxRowHeight;
- // Update top and bottom inner margin if applicable
rowIndex++;
}
// Get the next row
rowFrame->GetNextSibling(&rowFrame);
- }
+ }
/* Step 2: Now account for cells that span rows.
* A spanning cell's height is the sum of the heights of the rows it spans,
@@ -582,11 +591,6 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
* 1. optimization, if (PR_TRUE==atLeastOneRowSpanningCell) ... otherwise skip this step entirely
* we can get this info trivially from the cell map
*/
- nsTableFrame *tableFrame=nsnull;
- nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
- if (NS_FAILED(rv) || nsnull==tableFrame)
- return;
- nscoord cellSpacingY = tableFrame->GetCellSpacingY();
PRInt32 rowGroupHeight;
for (PRInt32 counter=0; counter<2; counter++)
@@ -622,22 +626,18 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
for (i = 0; i < rowSpan; i++) {
heightOfRowsSpanned += rowHeights[rowIndex + i];
}
- // need to reduce by cell spacing, twice that if it is the top row
- heightOfRowsSpanned -= cellSpacingY;
- if (0 == rowIndex) {
- heightOfRowsSpanned -= cellSpacingY;
- }
-
- if (gsDebug) printf("TRGF CalcRowH: heightOfRowsSpanned=%d\n", heightOfRowsSpanned);
+ // the avail height needs to reduce by top and bottom margins
+ nscoord availHeightOfRowsSpanned = heightOfRowsSpanned - cellSpacingY - cellSpacingY;
+ if (gsDebug) printf("TRGF CalcRowH: availHeightOfRowsSpanned=%d\n", availHeightOfRowsSpanned);
/* if the cell height fits in the rows, expand the spanning cell's height and slap it in */
nsSize cellFrameSize;
cellFrame->GetSize(cellFrameSize);
- if (heightOfRowsSpanned > cellFrameSize.height)
+ if (availHeightOfRowsSpanned > cellFrameSize.height)
{
if (gsDebug) printf("TRGF CalcRowH: spanning cell fits in rows spanned, had h=%d, expanded to %d\n",
- cellFrameSize.height, heightOfRowsSpanned);
- cellFrame->SizeTo(cellFrameSize.width, heightOfRowsSpanned);
+ cellFrameSize.height, availHeightOfRowsSpanned);
+ cellFrame->SizeTo(cellFrameSize.width, availHeightOfRowsSpanned);
// Realign cell content based on new height
((nsTableCellFrame*)cellFrame)->VerticallyAlignChild();
}
@@ -646,20 +646,25 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
*/
else
{
- PRInt32 excessHeight = cellFrameSize.height - heightOfRowsSpanned;
+ PRInt32 excessHeight = cellFrameSize.height - availHeightOfRowsSpanned;
if (gsDebug) printf("TRGF CalcRowH: excessHeight=%d\n", excessHeight);
// for every row starting at the row with the spanning cell...
nsTableRowFrame *rowFrameToBeResized = (nsTableRowFrame *)rowFrame;
PRInt32 *excessForRow = new PRInt32[numRows];
nsCRT::memset (excessForRow, 0, numRows*sizeof(PRInt32));
- for (i = rowIndex; i < numRows; i++)
- {
+ nscoord excessAllocated = 0;
+ for (i = rowIndex; i < numRows; i++) {
if (gsDebug) printf("TRGF CalcRowH: for row index=%d\n", i);
// if the row is within the spanned range, resize the row
- if (i < (rowIndex + rowSpan))
- {
+ if (i < (rowIndex + rowSpan)) {
+ //float percent = ((float)rowHeights[i]) / ((float)availHeightOfRowsSpanned);
+ //excessForRow[i] = NSToCoordRound(((float)(excessHeight)) * percent);
float percent = ((float)rowHeights[i]) / ((float)heightOfRowsSpanned);
- excessForRow[i] = NSToCoordRound(((float)(excessHeight)) * percent);
+ // give rows their percentage, except the last row gets the remainder
+ excessForRow[i] = ((i - 1) == (rowIndex + rowSpan))
+ ? excessHeight - excessAllocated
+ : NSToCoordRound(((float)(excessHeight)) * percent);
+ excessAllocated += excessForRow[i];
if (gsDebug) printf("TRGF CalcRowH: for row %d, excessHeight=%d from percent %f\n",
i, excessForRow[i], percent);
// update the row height
diff --git a/mozilla/layout/tables/BasicTableLayoutStrategy.cpp b/mozilla/layout/tables/BasicTableLayoutStrategy.cpp
index 6627d57e0b7..7712953e951 100644
--- a/mozilla/layout/tables/BasicTableLayoutStrategy.cpp
+++ b/mozilla/layout/tables/BasicTableLayoutStrategy.cpp
@@ -217,14 +217,15 @@ PRBool BasicTableLayoutStrategy::IsFixedWidth(const nsStylePosition* aStylePosit
}
-BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame)
+BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame, PRBool aIsNavQuirks)
{
NS_ASSERTION(nsnull != aFrame, "bad frame arg");
- mTableFrame = aFrame;
- mMinTableWidth = 0;
- mMaxTableWidth = 0;
- mFixedTableWidth = 0;
+ mTableFrame = aFrame;
+ mMinTableWidth = 0;
+ mMaxTableWidth = 0;
+ mFixedTableWidth = 0;
+ mIsNavQuirksMode = aIsNavQuirks;
}
BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
@@ -416,9 +417,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
nscoord effectiveMaxColumnWidth = 0; // max col width ignoring cells with colspans
nscoord specifiedFixedColWidth = 0; // the width of the column if given stylistically (or via cell Width attribute)
// only applicable if haveColWidth==PR_TRUE
- PRBool haveColWidth = PR_FALSE; // if true, the column has a width either from HTML width attribute,
- // from a style rule on the column,
- // or from a width attr/style on a cell that has colspan==1
+
horPadding[colIndex] = 0;
// Get column information
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colIndex);
@@ -433,7 +432,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
// Get fixed column width if it has one
if (eStyleUnit_Coord == colPosition->mWidth.GetUnit()) {
- haveColWidth = PR_TRUE;
+ colFrame->SetHasConstrainedWidth(PR_TRUE);
specifiedFixedColWidth = colPosition->mWidth.GetCoordValue();
horPadding[colIndex] = CalcHorizontalPadding(colIndex);
specifiedFixedColWidth += horPadding[colIndex];
@@ -489,7 +488,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
rowIndex, colSpan, cellMinSize.width, cellMinSize.height,
cellDesiredSize.width, cellDesiredSize.height);
- if (PR_TRUE == haveColWidth) {
+ if (colFrame->HasConstrainedWidth()) {
// This col has a specified coord fixed width, so set the min and max width to the larger of
// (specified width, largest max_element_size of the cells in the column)
// factoring in the min width of the prior cells (stored in minColWidth)
@@ -594,13 +593,13 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
} // end for (rowIndex = 0; rowIndex < numRows; rowIndex++)
// adjust the "fixed" width for content that is too wide
- if (haveColWidth && (effectiveMinColumnWidth > specifiedFixedColWidth)) {
+ if (colFrame->HasConstrainedWidth() && (effectiveMinColumnWidth > specifiedFixedColWidth)) {
specifiedFixedColWidth = effectiveMinColumnWidth;
}
// do all the global bookkeeping, factoring in margins
nscoord colInset = mTableFrame->GetCellSpacingX();
// keep a running total of the amount of space taken up by all fixed-width columns
- if ((PR_TRUE == haveColWidth) &&
+ if ((colFrame->HasConstrainedWidth()) &&
(nsTableColFrame::eWIDTH_SOURCE_CELL == colFrame->GetWidthSource())) {
mFixedTableWidth += specifiedFixedColWidth + colInset;
if (0 == colIndex) {
@@ -616,7 +615,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
colFrame->SetEffectiveMaxColWidth(effectiveMaxColumnWidth);
// this is the default, the real adjustment happens below where we deal with colspans
colFrame->SetAdjustedMinColWidth(effectiveMinColumnWidth);
- if ((PR_TRUE == haveColWidth) &&
+ if ((colFrame->HasConstrainedWidth()) &&
(nsTableColFrame::eWIDTH_SOURCE_CELL_WITH_SPAN!=colFrame->GetWidthSource())) {
mTableFrame->SetColumnWidth(colIndex, specifiedFixedColWidth);
}
@@ -1740,9 +1739,7 @@ PRBool BasicTableLayoutStrategy::
if (PR_FALSE == IsFixedWidth(colPosition, colTableStyle)) {
// compute the spanning cell's contribution to the column min width
nscoord spanCellMinWidth;
- PRBool needsExtraMinWidth = PR_FALSE;
- //if (spanInfo->effectiveMinWidthOfSpannedColscellMinWidth)
- // needsExtraMinWidth = PR_TRUE;
+ PRBool needsExtraMinWidth = (spanInfo->effectiveMinWidthOfSpannedCols < spanInfo->cellMinWidth);
if (PR_TRUE == needsExtraMinWidth) {
if (0 != spanInfo->effectiveMinWidthOfSpannedCols) {
spanCellMinWidth = (spanInfo->cellMinWidth * colFrame->GetEffectiveMinColWidth()) /
@@ -1951,7 +1948,7 @@ PRBool BasicTableLayoutStrategy::
colIndex, mTableFrame->GetColumnWidth(colIndex), aAvailWidth, colInset);
}
else if (PR_TRUE==isAutoWidth) { // column's width is determined by its content, done in post-processing
- mTableFrame->SetColumnWidth(colIndex, minColWidth); // reserve the column's min width
+ mTableFrame->SetColumnWidth(colIndex, minColWidth); // reserve the column's min width
atLeastOneAutoWidthColumn = PR_TRUE;
}
else if (-1 != specifiedProportionColumnWidth) {
@@ -2080,36 +2077,200 @@ PRBool BasicTableLayoutStrategy::
}
struct nsColInfo {
- nsColInfo(nsTableColFrame* aColFrame,
- PRInt32 aColIndex,
- PRInt32 aColWidth,
- float aMaximizeFactor)
- : mColFrame(aColFrame), mColIndex(aColIndex), mColWidth(aColWidth),
- mMaximizeFactor(aMaximizeFactor)
- {}
- nsTableColFrame* mColFrame;
- PRInt32 mColIndex;
- PRInt32 mColWidth;
- float mMaximizeFactor;
+ nsColInfo(nsTableColFrame* aFrame,
+ PRInt32 aIndex,
+ PRInt32 aMinWidth,
+ PRInt32 aWidth,
+ PRInt32 aMaxEffWidth,
+ PRInt32 aMaxWidth)
+ : mFrame(aFrame), mIndex(aIndex), mMinWidth(aMinWidth),
+ mWidth(aWidth), mMaxEffWidth(aMaxEffWidth), mMaxWidth(aMaxWidth), mWeight(0)
+ {}
+ nsTableColFrame* mFrame;
+ PRInt32 mIndex;
+ PRInt32 mMinWidth;
+ PRInt32 mWidth;
+ PRInt32 mMaxEffWidth;
+ PRInt32 mMaxWidth;
+ float mWeight;
};
void
-DistributeRemainingSpaceCleanup(PRInt32 aNumItems, nsColInfo** aInfoArray)
+DRS_Wrapup(nsTableFrame* aTableFrame,
+ PRInt32 aNumItems,
+ nsColInfo** aColInfo)
{
for (int i = 0; i < aNumItems; i++) {
- delete aInfoArray[i];
+ aTableFrame->SetColumnWidth(aColInfo[i]->mIndex, aColInfo[i]->mWidth);
+ delete aColInfo[i];
+ }
+ delete [] aColInfo;
+}
+
+void
+DRS_Increase(PRInt32 aNumAutoCols,
+ nsColInfo** aColInfo,
+ PRInt32 aDivisor,
+ PRBool aDontGoOverMax,
+ PRInt32& aAvailWidth)
+{
+ for (PRInt32 i = 0; i < aNumAutoCols; i++) {
+ if ((aAvailWidth <= 0) || (aDivisor <= 0)) {
+ break;
+ }
+ //float percent = ((float)aColInfo[i]->mMaxEffWidth) / (float)aDivisor;
+ float percent = ((float)aColInfo[i]->mMaxWidth) / (float)aDivisor;
+ //aDivisor -= aColInfo[i]->mWidth;
+ aDivisor -= aColInfo[i]->mMaxWidth;
+ nscoord addition = PR_MIN(aAvailWidth, NSToCoordRound(((float)(aAvailWidth)) * percent));
+ if (aDontGoOverMax) {
+ addition = PR_MIN(addition, aColInfo[i]->mMaxWidth - aColInfo[i]->mWidth);
+ }
+ // don't let the total additions exceed what is available
+ if (i == aNumAutoCols - 1) {
+ addition = PR_MIN(addition, aAvailWidth);
+ }
+ aColInfo[i]->mWidth += addition;
+ aAvailWidth -= addition;
+ }
+}
+
+void
+DRS_Decrease(PRInt32 aNumAutoCols,
+ nsColInfo** aColInfo,
+ PRInt32 aDivisor,
+ PRInt32& aExcess)
+{
+ for (PRInt32 i = 0; i < aNumAutoCols; i++) {
+ if ((aExcess <= 0) || (aDivisor <= 0)) {
+ break;
+ }
+ //float percent = ((float)aColInfo[i]->mMaxEffWidth) / (float)aDivisor;
+ float percent = ((float)aColInfo[i]->mMaxWidth) / (float)aDivisor;
+ //aDivisor -= aColInfo[i]->mWidth;
+ aDivisor -= aColInfo[i]->mMaxWidth;
+ nscoord reduction = PR_MIN(aExcess, NSToCoordRound(((float)(aExcess)) * percent));
+ // don't go over the col min
+ reduction = PR_MIN(reduction, aColInfo[i]->mWidth - aColInfo[i]->mMinWidth);
+ // don't let the total reductions exceed what is available
+ if (i == aNumAutoCols - 1) {
+ reduction = PR_MIN(reduction, aExcess);
+ }
+ aColInfo[i]->mWidth -= reduction;
+ aExcess -= reduction;
+ }
+}
+
+
+void
+DSR_Sort(nsColInfo** aColInfo, PRInt32 aNumCols)
+{
+ // sort the cols based on the Weight
+ for (PRInt32 j = aNumCols - 1; j > 0; j--) {
+ for (PRInt32 i = 0; i < j; i++) {
+ if (aColInfo[i]->mWeight < aColInfo[i+1]->mWeight) { // swap them
+ nsColInfo* save = aColInfo[i];
+ aColInfo[i] = aColInfo[i+1];
+ aColInfo[i+1] = save;
+ }
+ }
}
- delete [] aInfoArray;
}
// Take the remaining space in the table and distribute it to the auto-width cols
-// in the table. If a col reaches its desired width, stop at that width unless all
-// other cols have reached their desired widths.
+// in the table.
+void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecifiedWidth,
+ nscoord& aComputedTableWidth,
+ PRBool aTableIsAutoWidth)
+{
+ // availWidth is the difference between the total available width and the
+ // amount of space already assigned.
+ nscoord availWidth = PR_MAX(aTableSpecifiedWidth - aComputedTableWidth, 0);
+ TDBG_SDD(" aTableSpecifiedWidth specified as %d, availWidth is = %d\n", aTableSpecifiedWidth, availWidth);
+ if ((0 == availWidth) || (aTableSpecifiedWidth <= 0)) {
+ return;
+ }
-// This algorithm has been reworked from the orignal to fix bugs (e.g. bug 6184)
-// and remove the recursion. For auto width tables it uses colFrame->GetMaxColSize()
-// instead of GetMaxEffectiveColSize, so for some auto width tables with colspans
-// it claculates more like IE5 than Nav4.5, which appears to be more reasonable.
+ // Get the auto width cols. Only they get adjusted.
+ PRInt32 numAutoCols = 0;
+ PRInt32* autoCols = nsnull;
+ mTableFrame->GetColumnsByType(eStyleUnit_Auto, numAutoCols, autoCols);
+ if (0 == numAutoCols) {
+ return;
+ }
+ nsColInfo** colInfo = new nsColInfo*[numAutoCols];
+
+ nscoord totalDivisor = 0;
+ nscoord totalAutoWidthGiven = 0;
+ PRInt32 i;
+
+ // start out by giving each col its max effective width (or adj width if it is greater)
+ // for standard mode and its min width for nav quirks mode
+ for (i = 0; i < numAutoCols; i++) {
+ PRInt32 colIndex = autoCols[i];
+ nsTableColFrame* colFrame = mTableFrame->GetColFrame(autoCols[i]);
+ nscoord origWidth = mTableFrame->GetColumnWidth(autoCols[i]);
+ nscoord minWidth = PR_MAX(colFrame->GetAdjustedMinColWidth(), origWidth);
+ nscoord maxEffWidth = PR_MAX(colFrame->GetEffectiveMaxColWidth(), minWidth);
+ nscoord maxWidth = colFrame->GetMaxColWidth();
+ nscoord startWidth = (mIsNavQuirksMode) ? minWidth : maxWidth;
+ colInfo[i] = new nsColInfo(colFrame, autoCols[i], minWidth, startWidth, maxEffWidth, maxWidth);
+// totalDivisor += maxEffWidth;
+ totalDivisor += maxWidth;
+ totalAutoWidthGiven += startWidth - origWidth;
+ }
+
+ availWidth = aTableSpecifiedWidth - aComputedTableWidth - totalAutoWidthGiven;
+
+ if (availWidth >= 0) { // have more space to allocate
+ for (i = 0; i < numAutoCols; i++) {
+ // the weight here is a relative metric for determining when cols reach their max.
+ // A col with a larger weight will reach its max before one with a smaller value.
+ nscoord delta = colInfo[i]->mMaxWidth - colInfo[i]->mWidth;
+ colInfo[i]->mWeight = (delta <= 0)
+ ? 1000000 // cols which have already reached their max get a large value
+ : ((float)colInfo[i]->mMaxWidth) / ((float)delta);
+ }
+
+ // sort the cols based on the weight so that in one pass cols with higher
+ // weights will get their max earlier than ones with lower weights
+ // This is an innefficient bubble sort, but unless there are an unlikely
+ // large number of cols, it is not an issue.
+ DSR_Sort(colInfo, numAutoCols);
+
+ // compute the proportion to be added to each column, don't go beyond the col's
+ // max. This algorithm assumes that the Weight works as stated above
+ DRS_Increase(numAutoCols, colInfo, totalDivisor, PR_TRUE, availWidth);
+ // if every col got its max and there is more to go, allocate a 2nd time
+ if (!aTableIsAutoWidth && (availWidth > 0)) {
+ DRS_Increase(numAutoCols, colInfo, totalDivisor, PR_FALSE, availWidth);
+ }
+ aComputedTableWidth = aTableSpecifiedWidth - availWidth;
+ }
+ else { // reduce each col width if appropriate
+ for (i = 0; i < numAutoCols; i++) {
+ // the weight here is a relative metric for determining when cols reach their min.
+ // A col with a larger weight will reach its min before one with a smaller value.
+ nscoord delta = colInfo[i]->mWidth - colInfo[i]->mMinWidth;
+ colInfo[i]->mWeight = (delta <= 0)
+ ? 1000000 // cols which have already reached their min get a large value
+ : ((float)colInfo[i]->mWidth) / ((float)delta);
+ }
+
+ // sort the cols based on the Weight
+ DSR_Sort(colInfo, numAutoCols);
+
+ // compute the proportion to be subtracted from each column, don't go beyond
+ // the col's min. This algorithm assumes that the Weight works as stated above
+ PRInt32 totalExcessGiven = -availWidth;
+ DRS_Decrease(numAutoCols, colInfo, totalDivisor, totalExcessGiven);
+ aComputedTableWidth = aTableSpecifiedWidth + totalExcessGiven;
+ }
+ DRS_Wrapup(mTableFrame, numAutoCols, colInfo);
+ TDBG_WIDTHS4("at end of DistributeRemainingSpace: ",PR_FALSE,PR_FALSE);
+}
+
+#if 0
void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecifiedWidth,
nscoord& aComputedTableWidth,
PRBool aTableIsAutoWidth)
@@ -2141,21 +2302,19 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecified
PRInt32 colIndex = autoColumns[i];
nsTableColFrame* colFrame = mTableFrame->GetColFrame(autoColumns[i]);
nscoord startingColWidth = mTableFrame->GetColumnWidth(colIndex);
- nscoord maxColWidth = (PR_FALSE == aTableIsAutoWidth)
- ? colFrame->GetEffectiveMaxColWidth() : colFrame->GetMaxColWidth();
- if ((PR_FALSE == aTableIsAutoWidth) || (startingColWidth < maxColWidth)) {
- if (0 == maxColWidth)
- maxColWidth = startingColWidth;
- totalResizeColWidth += maxColWidth;
- // the maximizeFactor is a relative metric for determining when cols reach their max.
- // A col with a smaller value will reach its max before one with a larger value.
- nscoord delta = maxColWidth - startingColWidth;
- float maximizeFactor = (0 == delta)
- ? 1000000 : ((float)maxColWidth) / ((float)(maxColWidth - startingColWidth));
- resizeCols[numResizeCols] = new nsColInfo(colFrame, colIndex, startingColWidth,
- maximizeFactor);
- numResizeCols++;
- }
+ nscoord maxColWidth = colFrame->GetMaxColWidth();
+ if (0 == maxColWidth)
+ maxColWidth = startingColWidth;
+ totalResizeColWidth += maxColWidth;
+ // the maximizeFactor is a relative metric for determining when cols reach their max.
+ // A col with a smaller value will reach its max before one with a larger value.
+ nscoord delta = maxColWidth - startingColWidth;
+ float maximizeFactor = (0 >= delta)
+ ? 1000000 // cols which have already reached their max get a large value
+ : ((float)maxColWidth) / ((float)(maxColWidth - startingColWidth));
+ resizeCols[numResizeCols] = new nsColInfo(colFrame, colIndex, startingColWidth,
+ maximizeFactor);
+ numResizeCols++;
}
if (totalResizeColWidth <= 0) {
NS_ASSERTION(PR_TRUE, "need to handle this case");
@@ -2187,10 +2346,7 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecified
}
nsTableColFrame* colFrame = resizeCols[i]->mColFrame;
nscoord startingColWidth = resizeCols[i]->mColWidth;
- nscoord maxColWidth = (PR_FALSE == aTableIsAutoWidth)
- ? colFrame->GetEffectiveMaxColWidth() : colFrame->GetMaxColWidth();
- // if we actually have room to distribute, do it here
- // otherwise, the auto columns already are set to their minimum
+ nscoord maxColWidth = colFrame->GetMaxColWidth();
float percent = ((float)maxColWidth) / (float)totalResizeColWidthRemaining;
nscoord delta = PR_MIN(availWidth, NSToCoordRound(((float)(availWidth)) * percent));
// don't go over the col max right now
@@ -2214,7 +2370,7 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecified
}
nsTableColFrame* colFrame = resizeCols[i]->mColFrame;
nscoord startingColWidth = resizeCols[i]->mColWidth;
- nscoord maxColWidth = colFrame->GetEffectiveMaxColWidth();
+ nscoord maxColWidth = colFrame->GetMaxColWidth();
// if we actually have room to distribute, do it here
float percent = ((float)maxColWidth) / (float)totalResizeColWidth;
nscoord delta = PR_MIN(availWidth, NSToCoordRound(((float)(availWidth)) * percent));
@@ -2229,6 +2385,7 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecified
DistributeRemainingSpaceCleanup(numResizeCols, resizeCols);
TDBG_WIDTHS4("at end of DistributeRemainingSpace: ",PR_FALSE,PR_FALSE);
}
+#endif
void BasicTableLayoutStrategy::AdjustTableThatIsTooWide(nscoord aComputedWidth,
nscoord aTableWidth,
diff --git a/mozilla/layout/tables/BasicTableLayoutStrategy.h b/mozilla/layout/tables/BasicTableLayoutStrategy.h
index 121c4baafd5..375d82ae4fc 100644
--- a/mozilla/layout/tables/BasicTableLayoutStrategy.h
+++ b/mozilla/layout/tables/BasicTableLayoutStrategy.h
@@ -80,7 +80,8 @@ public:
/** Public constructor.
* @paran aFrame the table frame for which this delegate will do layout
*/
- BasicTableLayoutStrategy(nsTableFrame *aFrame);
+ BasicTableLayoutStrategy(nsTableFrame *aFrame,
+ PRBool aIsNavQuirksMode = PR_TRUE);
/** destructor */
virtual ~BasicTableLayoutStrategy();
@@ -288,6 +289,7 @@ protected:
nscoord mMinTableWidth; // the smallest size for the table
nscoord mMaxTableWidth; // the "natural" size for the table, if unconstrained
nscoord mFixedTableWidth; // the amount of space taken up by fixed-width columns
+ PRBool mIsNavQuirksMode;
};
diff --git a/mozilla/layout/tables/nsTableColFrame.h b/mozilla/layout/tables/nsTableColFrame.h
index 704088a0ece..876b321160d 100644
--- a/mozilla/layout/tables/nsTableColFrame.h
+++ b/mozilla/layout/tables/nsTableColFrame.h
@@ -79,9 +79,17 @@ public:
nscoord GetEffectiveMinColWidth();
void SetEffectiveMinColWidth(nscoord aMinColWidth);
+ // return the min width for this column after provisions for col spans have
+ // been included. The adj min width is >= the min width.
nscoord GetAdjustedMinColWidth();
void SetAdjustedMinColWidth(nscoord aMinColWidth);
+ // Return true if the column has a width either from HTML width attribute,
+ // from a style rule on the column, from a width attr/style on a cell
+ // that has colspan==1.
+ PRBool HasConstrainedWidth();
+ void SetHasConstrainedWidth(PRBool aIsConstrained);
+
PRInt32 GetWidthSource();
void SetWidthSource(PRInt32 aMinColWidth);
@@ -106,6 +114,8 @@ protected:
nscoord mMinAdjustedColWidth;
+ PRBool mHasConstrainedWidth;
+
PRInt32 mWidthSource;
};
@@ -150,6 +160,12 @@ inline void nsTableColFrame::SetEffectiveMinColWidth(nscoord aMinEffectiveColWid
inline nscoord nsTableColFrame::GetAdjustedMinColWidth()
{ return mMinAdjustedColWidth; }
+inline PRBool nsTableColFrame::HasConstrainedWidth()
+{ return mHasConstrainedWidth; }
+
+inline void nsTableColFrame::SetHasConstrainedWidth(PRBool aIsConstrained)
+{ mHasConstrainedWidth = aIsConstrained; }
+
inline void nsTableColFrame::SetAdjustedMinColWidth(nscoord aMinAdjustedColWidth)
{ mMinAdjustedColWidth = aMinAdjustedColWidth; }
diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp
index 97b62c57bfd..2511a145cbf 100644
--- a/mozilla/layout/tables/nsTableFrame.cpp
+++ b/mozilla/layout/tables/nsTableFrame.cpp
@@ -3965,10 +3965,12 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext& aPresContext,
// based on the compatibility mode, create a table layout strategy
if (nsnull==mTableLayoutStrategy)
{
+ nsCompatibility mode;
+ aPresContext.GetCompatibilityMode(&mode);
if (PR_FALSE==RequiresPass1Layout())
mTableLayoutStrategy = new FixedTableLayoutStrategy(this);
else
- mTableLayoutStrategy = new BasicTableLayoutStrategy(this);
+ mTableLayoutStrategy = new BasicTableLayoutStrategy(this, eCompatibility_NavQuirks == mode);
mTableLayoutStrategy->Initialize(aMaxElementSize, GetColCount());
mColumnWidthsValid=PR_TRUE;
}
diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.cpp b/mozilla/layout/tables/nsTableRowGroupFrame.cpp
index 72840825e02..86234b517e6 100644
--- a/mozilla/layout/tables/nsTableRowGroupFrame.cpp
+++ b/mozilla/layout/tables/nsTableRowGroupFrame.cpp
@@ -524,6 +524,13 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState)
{
if (gsDebug) printf("TRGF CalculateRowHeights begin\n");
+ nsTableFrame *tableFrame=nsnull;
+ nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
+ if (NS_FAILED(rv) || nsnull==tableFrame)
+ return;
+ // all table cells have the same top and bottom margins, namely cellSpacingY
+ nscoord cellSpacingY = tableFrame->GetCellSpacingY();
+
// iterate children and for each row get its height
PRInt32 numRows;
GetRowCount(numRows);
@@ -549,22 +556,24 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
// get the height of the tallest cell in the row (excluding cells that span rows)
+ // XXX GetChildMaxTopMargin and GetChildMaxBottomMargin should be removed/simplified because
+ // according to CSS, all table cells must have the same top/bottom and left/right margins.
nscoord maxCellHeight = ((nsTableRowFrame*)rowFrame)->GetTallestChild();
nscoord maxCellTopMargin = ((nsTableRowFrame*)rowFrame)->GetChildMaxTopMargin();
nscoord maxCellBottomMargin = ((nsTableRowFrame*)rowFrame)->GetChildMaxBottomMargin();
nscoord maxRowHeight = maxCellHeight + maxCellTopMargin + maxCellBottomMargin;
- if (gsDebug) printf("TRGF CalcRowH: for row %d(%p), maxCellH=%d, maxCTopMargin=%d, maxCBM=%d\n",
- rowIndex + startRowIndex, rowFrame, maxCellHeight, maxCellTopMargin, maxCellBottomMargin);
+ // only the top row has a top margin. Other rows start at the bottom of the prev row's bottom margin.
+ if (gsDebug) printf("TRGF CalcRowH: for row %d(%p), maxCellH=%d, spacingY=%d, d\n",
+ rowIndex + startRowIndex, rowFrame, maxCellHeight, cellSpacingY);
if (gsDebug) printf(" rowHeight=%d\n", maxRowHeight);
// save the row height for pass 2 below
rowHeights[rowIndex] = maxRowHeight;
- // Update top and bottom inner margin if applicable
rowIndex++;
}
// Get the next row
rowFrame->GetNextSibling(&rowFrame);
- }
+ }
/* Step 2: Now account for cells that span rows.
* A spanning cell's height is the sum of the heights of the rows it spans,
@@ -582,11 +591,6 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
* 1. optimization, if (PR_TRUE==atLeastOneRowSpanningCell) ... otherwise skip this step entirely
* we can get this info trivially from the cell map
*/
- nsTableFrame *tableFrame=nsnull;
- nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
- if (NS_FAILED(rv) || nsnull==tableFrame)
- return;
- nscoord cellSpacingY = tableFrame->GetCellSpacingY();
PRInt32 rowGroupHeight;
for (PRInt32 counter=0; counter<2; counter++)
@@ -622,22 +626,18 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
for (i = 0; i < rowSpan; i++) {
heightOfRowsSpanned += rowHeights[rowIndex + i];
}
- // need to reduce by cell spacing, twice that if it is the top row
- heightOfRowsSpanned -= cellSpacingY;
- if (0 == rowIndex) {
- heightOfRowsSpanned -= cellSpacingY;
- }
-
- if (gsDebug) printf("TRGF CalcRowH: heightOfRowsSpanned=%d\n", heightOfRowsSpanned);
+ // the avail height needs to reduce by top and bottom margins
+ nscoord availHeightOfRowsSpanned = heightOfRowsSpanned - cellSpacingY - cellSpacingY;
+ if (gsDebug) printf("TRGF CalcRowH: availHeightOfRowsSpanned=%d\n", availHeightOfRowsSpanned);
/* if the cell height fits in the rows, expand the spanning cell's height and slap it in */
nsSize cellFrameSize;
cellFrame->GetSize(cellFrameSize);
- if (heightOfRowsSpanned > cellFrameSize.height)
+ if (availHeightOfRowsSpanned > cellFrameSize.height)
{
if (gsDebug) printf("TRGF CalcRowH: spanning cell fits in rows spanned, had h=%d, expanded to %d\n",
- cellFrameSize.height, heightOfRowsSpanned);
- cellFrame->SizeTo(cellFrameSize.width, heightOfRowsSpanned);
+ cellFrameSize.height, availHeightOfRowsSpanned);
+ cellFrame->SizeTo(cellFrameSize.width, availHeightOfRowsSpanned);
// Realign cell content based on new height
((nsTableCellFrame*)cellFrame)->VerticallyAlignChild();
}
@@ -646,20 +646,25 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
*/
else
{
- PRInt32 excessHeight = cellFrameSize.height - heightOfRowsSpanned;
+ PRInt32 excessHeight = cellFrameSize.height - availHeightOfRowsSpanned;
if (gsDebug) printf("TRGF CalcRowH: excessHeight=%d\n", excessHeight);
// for every row starting at the row with the spanning cell...
nsTableRowFrame *rowFrameToBeResized = (nsTableRowFrame *)rowFrame;
PRInt32 *excessForRow = new PRInt32[numRows];
nsCRT::memset (excessForRow, 0, numRows*sizeof(PRInt32));
- for (i = rowIndex; i < numRows; i++)
- {
+ nscoord excessAllocated = 0;
+ for (i = rowIndex; i < numRows; i++) {
if (gsDebug) printf("TRGF CalcRowH: for row index=%d\n", i);
// if the row is within the spanned range, resize the row
- if (i < (rowIndex + rowSpan))
- {
+ if (i < (rowIndex + rowSpan)) {
+ //float percent = ((float)rowHeights[i]) / ((float)availHeightOfRowsSpanned);
+ //excessForRow[i] = NSToCoordRound(((float)(excessHeight)) * percent);
float percent = ((float)rowHeights[i]) / ((float)heightOfRowsSpanned);
- excessForRow[i] = NSToCoordRound(((float)(excessHeight)) * percent);
+ // give rows their percentage, except the last row gets the remainder
+ excessForRow[i] = ((i - 1) == (rowIndex + rowSpan))
+ ? excessHeight - excessAllocated
+ : NSToCoordRound(((float)(excessHeight)) * percent);
+ excessAllocated += excessForRow[i];
if (gsDebug) printf("TRGF CalcRowH: for row %d, excessHeight=%d from percent %f\n",
i, excessForRow[i], percent);
// update the row height