diff --git a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp index c585bbc8baf..d76383ed13b 100644 --- a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp +++ b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp @@ -135,10 +135,10 @@ BasicTableLayoutStrategy::~BasicTableLayoutStrategy() PRBool BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresContext, nsIStyleContext *aTableStyle, const nsReflowState& aReflowState, - PRInt32 aMaxWidth, - PRInt32 &aTotalFixedWidth, - PRInt32 &aMinTableWidth, - PRInt32 &aMaxTableWidth, + nscoord aMaxWidth, + nscoord &aTotalFixedWidth, + nscoord &aMinTableWidth, + nscoord &aMaxTableWidth, nsSize* aMaxElementSize) { PRBool result = PR_TRUE; @@ -615,14 +615,14 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo NS_ASSERTION(nsnull==tablePIF, "never ever call me on a continuing frame!"); #endif - PRBool result = PR_TRUE; + PRBool result = PR_TRUE; nscoord tableWidth=0; // the width of the table as a result of setting column widths PRInt32 totalSlices=0; // the total number of slices the proportional-width columns request nsVoidArray *proportionalColumnsList=nsnull; // a list of the columns that are proportional-width nsVoidArray *spanList=nsnull; // a list of the cells that span columns nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData(); PRInt32 numCols = columnLayoutData->Count(); - PRInt32 * effectiveColumnWidths = new PRInt32[numCols]; // used for Nav4 compatible table fluffing + nscoord * effectiveColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing nsCRT::memset (effectiveColumnWidths, 0, numCols*sizeof(PRInt32)); for (PRInt32 colIndex = 0; colIndexAppendElement (spanInfo); + spanList->AppendElement(spanInfo); } } @@ -887,7 +887,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo nscoord widthPerSlice = widthRemaining/totalSlices; PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count(); for (PRInt32 i=0; iElementAt(i)); nscoord computedColWidth = info->mProportion*widthPerSlice; @@ -896,11 +896,12 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo printf (" 3 proportional step 2: col %d given %d proportion of remaining space %d, set to width = %d\n", info->mColIndex, info->mProportion, widthRemaining, computedColWidth); tableWidth += computedColWidth; + effectiveColumnWidths[info->mColIndex] = computedColWidth; delete info; } } else - { + { // we're in an unconstrained situation, so give each column the max of the max column widths PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count(); PRInt32 maxOfMaxColWidths = 0; PRInt32 i; @@ -920,6 +921,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo printf (" 3 proportional step 2 (unconstrained!): col %d set to width = %d\n", info->mColIndex, maxOfMaxColWidths); tableWidth += maxOfMaxColWidths; + effectiveColumnWidths[info->mColIndex] = maxOfMaxColWidths; delete info; } } @@ -929,9 +931,9 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo // next, if the specified width of the table is greater than the table's computed width, expand the // table's computed width to match the specified width, giving the extra space to proportionately-sized // columns if possible. - if (aTableFixedWidth > tableWidth) + if (aAvailWidth > tableWidth) { - DistributeExcessSpace(aTableFixedWidth, tableWidth, numCols, effectiveColumnWidths); + DistributeExcessSpace(aAvailWidth, tableWidth, effectiveColumnWidths); } // today we always allocate effectiveColumnWidths, but tomorrow we might be smarter, so leave the check in if (nsnull!=effectiveColumnWidths) @@ -941,14 +943,15 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo return result; } +// take the extra space in the table and distribute it proportionately (based on desired width) +// give extra space to auto-width cells first, or if there are none to all cells void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth, nscoord aComputedTableWidth, - PRInt32 aNumCols, - PRInt32 *aColWidths) + nscoord *aColWidths) { - nscoord excess = aTableFixedWidth - aComputedTableWidth; - if (gsDebug) printf ("fixed width %d > computed table width %d, excess = %d\n", - aTableFixedWidth, aComputedTableWidth, excess); + nscoord excess = 0; + if (PR_TRUE==gsDebug) printf ("DistributeExcessSpace: fixed width %d > computed table width %d\n", + aTableFixedWidth, aComputedTableWidth); // if there are auto-sized columns, give them the extra space PRInt32 numAutoColumns=0; PRInt32 *autoColumns=nsnull; @@ -969,14 +972,15 @@ void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth, else totalEffectiveWidthOfAutoColumns += mTableFrame->GetColumnWidth(autoColumns[i]); } + excess = aTableFixedWidth - totalEffectiveWidthOfAutoColumns; // 2. next, compute the proportion to be added to each column, and add it for (i = 0; iGetColumnWidth(autoColumns[i]); + nscoord oldColWidth = aColWidths[colIndex]; float percent; if (0!=totalEffectiveWidthOfAutoColumns) - percent = ((float)(aColWidths[autoColumns[i]]))/((float)totalEffectiveWidthOfAutoColumns); + percent = ((float)(aColWidths[colIndex]))/((float)totalEffectiveWidthOfAutoColumns); else percent = ((float)1)/((float)numAutoColumns); nscoord excessForThisColumn = (nscoord)(excess*percent); @@ -991,10 +995,11 @@ void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth, // (they must be all fixed and percentage-width columns, or we would have gone into the block above) else { - nscoord excessPerColumn = excess/aNumCols; + excess = aTableFixedWidth - aComputedTableWidth; + nscoord excessPerColumn = excess/mNumCols; if (gsDebug==PR_TRUE) printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess); - for (PRInt32 colIndex = 0; colIndexGetColumnLayoutData(); PRInt32 numCols = columnLayoutData->Count(); - PRInt32 * effectiveColumnWidths = new PRInt32[numCols]; // used for Nav4 compatible table fluffing - nsCRT::memset (effectiveColumnWidths, 0, numCols*sizeof(PRInt32)); + nscoord * effectiveMaxColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing + nsCRT::memset (effectiveMaxColumnWidths, 0, numCols*sizeof(PRInt32)); + nscoord * effectiveMinColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing + nsCRT::memset (effectiveMinColumnWidths, 0, numCols*sizeof(PRInt32)); for (PRInt32 colIndex = 0; colIndexElementAt(colIndex)); nsVoidArray *cells = colData->GetCells(); @@ -1149,17 +1158,22 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre if (PR_TRUE==gsDebug) printf("factoring in cell %d with colSpan=%d\n factoring in min=%d and desired=%d\n", cellIndex, colSpan, cellMinWidth, cellDesiredWidth); + // remember the widest min cell width if (minColWidth < cellMinWidth) minColWidth = cellMinWidth; + // effectiveMinColumnWidth is the width as if no cells with colspans existed + if ((1==colSpan) && (effectiveMinColumnWidths[colIndex] < minColWidth)) + effectiveMinColumnWidths[colIndex] = cellMinWidth; + // remember the max desired cell width if (maxColWidth < cellDesiredWidth) maxColWidth = cellDesiredWidth; - // effectiveColumnWidth is the width as if no cells with colspans existed - if ((1==colSpan) && (effectiveColumnWidths[colIndex] < maxColWidth)) - effectiveColumnWidths[colIndex] = cellDesiredWidth; + // effectiveMaxColumnWidth is the width as if no cells with colspans existed + if ((1==colSpan) && (effectiveMaxColumnWidths[colIndex] < maxColWidth)) + effectiveMaxColumnWidths[colIndex] = cellDesiredWidth; if (gsDebug==PR_TRUE) - printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d\n", + printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d,%d\n", cellIndex, minColWidth, maxColWidth, - colIndex, effectiveColumnWidths[colIndex]); + colIndex, effectiveMaxColumnWidths[colIndex], effectiveMaxColumnWidths[colIndex]); if (1GetColumnWidth(colIndex), aAvailWidth); } else if (PR_TRUE==isAutoWidth) - { // column's width is determined by its content - PRUint32 W = aMaxWidth - aMinTableWidth; - PRUint32 D = aMaxTableWidth - aMinTableWidth; - if (0==D) // fixed-size table - D=1; - // XXX really need to use effectiveColumnWidths[colIndex] here - PRUint32 d = maxColWidth - minColWidth; // XXX: if this is 0, set to minColWidth? - PRInt32 width = (d*W)/D; - mTableFrame->SetColumnWidth(colIndex, minColWidth + width); - if (gsDebug==PR_TRUE) - printf (" 4 auto-width: col %d W=%d D=%d d=%d, set to width = %d\n", - colIndex, W, D, d, mTableFrame->GetColumnWidth(colIndex)); + { // column's width is determined by its content, done in post-processing + mTableFrame->SetColumnWidth(colIndex, 0); // set to 0 width for now + atLeastOneAutoWidthColumn = PR_TRUE; } else if (-1!=specifiedProportionColumnWidth) { // we need to save these and do them after all other columns have been calculated @@ -1309,7 +1317,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre } } /* --- post-process if necessary --- */ - // first, assign a width to proportional-width columns + if (PR_TRUE==atLeastOneAutoWidthColumn) + { // proportionately distribute the remaining space to autowidth columns + DistributeRemainingSpace(aMaxWidth, tableWidth, effectiveMinColumnWidths, effectiveMaxColumnWidths); + } + // second, assign a width to proportional-width columns if (nsnull!=proportionalColumnsList) { // first, figure out the amount of space per slice @@ -1339,14 +1351,76 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre } delete proportionalColumnsList; } - + + // clean up // today we always allocate effectiveColumnWidths, but tomorrow we might be smarter, so leave the check in - if (nsnull!=effectiveColumnWidths) - delete [] effectiveColumnWidths; + if (nsnull!=effectiveMinColumnWidths) + delete [] effectiveMinColumnWidths; + if (nsnull!=effectiveMaxColumnWidths) + delete [] effectiveMaxColumnWidths; if (nsnull!=spanList) delete spanList; return result; } +//XXX: make sure aTFW takes into account fixed width cells already assigned +// take the remaining space in the table and distribute it proportionately +// to the auto-width cells in the table (based on desired width) +void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableFixedWidth, + nscoord aComputedTableWidth, + nscoord *aMinColWidths, + nscoord *aMaxColWidths) +{ + if (PR_TRUE==gsDebug) + printf ("DistributeRemainingSpace: fixed width %d > computed table width %d\n", + aTableFixedWidth, aComputedTableWidth); + // if there are auto-sized columns, give them the extra space + PRInt32 numAutoColumns=0; + PRInt32 *autoColumns=nsnull; + // availWidth is the difference between the total available width and the + // amount of space already assigned, assuming auto col widths were assigned 0. + nscoord availWidth = aTableFixedWidth - aComputedTableWidth; + mTableFrame->GetColumnsByType(eStyleUnit_Auto, numAutoColumns, autoColumns); + if (0!=numAutoColumns) + { + // there's at least one auto-width column, so give it (them) the extra space + // proportionately distributed extra space, based on the column's desired size + nscoord totalEffectiveWidthOfAutoColumns = 0; + // 1. first, get the total width of the auto columns + PRInt32 i; + for (i = 0; iGetColumnWidth(autoColumns[i]); + } + if (gsDebug==PR_TRUE) + printf(" aTableFixedWidth specified as %d, availWidth is = %d\n", + aTableFixedWidth, availWidth); + + // 2. next, compute the proportion to be added to each column, and add it + for (i = 0; iSetColumnWidth(colIndex, colWidth); + } + } +} + diff --git a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h index bb272fab46e..05e843b88af 100644 --- a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h +++ b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h @@ -169,14 +169,27 @@ public: * @param aTableFixedWidth the specified width of the table. If there is none, * this param is 0 * @param aComputedTableWidth the width of the table before this final step. - * @param aNumCols the number of columns in the table * * @return void */ virtual void DistributeExcessSpace(nscoord aTableFixedWidth, nscoord aComputedTableWidth, - PRInt32 aNumCols, - PRInt32 *aColWidths); + nscoord *aColWidths); + + /** starting with a partially balanced table, compute the amount + * of space to remove from each column to completely balance the table. + * set the column widths in mTableFrame based on these computations. + * + * @param aTableFixedWidth the specified width of the table. If there is none, + * this param is 0 + * @param aComputedTableWidth the width of the table before this final step. + * + * @return void + */ + virtual void DistributeRemainingSpace(nscoord aTableFixedWidth, + nscoord aComputedTableWidth, + nscoord *aMinColWidths, + nscoord *aMaxColWidths); /** return true if the style indicates that the width is a specific width * for the purposes of column width determination. diff --git a/mozilla/layout/html/table/src/nsCellMap.h b/mozilla/layout/html/table/src/nsCellMap.h index 6d5d4d3fce2..15f9e6c441a 100644 --- a/mozilla/layout/html/table/src/nsCellMap.h +++ b/mozilla/layout/html/table/src/nsCellMap.h @@ -38,7 +38,7 @@ class nsCellMap { protected: /** storage for CellData pointers */ - PRInt32 *mCells; + PRInt32 *mCells; ///XXX CellData *? /** the number of rows */ int mRowCount; // in java, we could just do fCellMap.length; diff --git a/mozilla/layout/html/table/src/nsTableCellFrame.cpp b/mozilla/layout/html/table/src/nsTableCellFrame.cpp index 72ffeafca3e..00676145a18 100644 --- a/mozilla/layout/html/table/src/nsTableCellFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableCellFrame.cpp @@ -268,10 +268,9 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, CreatePsuedoFrame(aPresContext); } - // reduce available space by insets - + // reduce available space by insets, if we're in a constrained situation if (NS_UNCONSTRAINEDSIZE!=availSize.width) - availSize.width -= leftInset+rightInset+margin.left+margin.right; + availSize.width -= leftInset+rightInset; if (NS_UNCONSTRAINEDSIZE!=availSize.height) availSize.height -= topInset+bottomInset+margin.top+margin.bottom; @@ -305,9 +304,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, } SetFirstContentOffset(mFirstChild); - //if (gsDebug) printf("CELL: set first content offset to %d\n", GetFirstContentOffset()); //@@@ SetLastContentOffset(mFirstChild); - //if (gsDebug) printf("CELL: set last content offset to %d\n", GetLastContentOffset()); //@@@ // Place the child mFirstChild->SetRect(nsRect(leftInset, topInset, @@ -332,13 +329,8 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, printf(" %p cellFrame height set to %d from kidSize=%d and insets %d,%d\n", this, cellHeight, kidSize.height, topInset, bottomInset); // next determine the cell's width - nscoord cellWidth = kidSize.width; // at this point, we've factored in the cell's style attributes - // if we're really in a constrained situation, factor in insets - if (NS_UNCONSTRAINEDSIZE!=aReflowState.maxSize.width) - { - NS_ASSERTION(NS_UNCONSTRAINEDSIZE!=cellWidth, "child says it has unconstrained width in a constrained case"); - cellWidth += leftInset + rightInset; - } + nscoord cellWidth = kidSize.width; // at this point, we've factored in the cell's style attributes + cellWidth += leftInset + rightInset; // factor in insets // Nav4 hack for 0 width cells. If the cell has any content, it must have a desired width of at least 1 /* @@ -370,10 +362,8 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, if (nsnull!=aDesiredSize.maxElementSize) { *aDesiredSize.maxElementSize = *pMaxElementSize; - if (NS_UNCONSTRAINEDSIZE!=aReflowState.maxSize.height) - aDesiredSize.maxElementSize->height += topInset + bottomInset; - if (NS_UNCONSTRAINEDSIZE!=aReflowState.maxSize.width) - aDesiredSize.maxElementSize->width += leftInset + rightInset; + aDesiredSize.maxElementSize->height += topInset + bottomInset; + aDesiredSize.maxElementSize->width += leftInset + rightInset; } if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) diff --git a/mozilla/layout/html/table/src/nsTableFrame.h b/mozilla/layout/html/table/src/nsTableFrame.h index 106f64415da..654920edc84 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.h +++ b/mozilla/layout/html/table/src/nsTableFrame.h @@ -29,7 +29,6 @@ class nsTableCellFrame; class nsTableColFrame; class nsTableRowGroupFrame; class nsTableRowFrame; -class CellData; class nsITableLayoutStrategy; class nsHTMLValue; class ColumnInfoCache; @@ -43,6 +42,31 @@ struct nsStyleSpacing; extern const nsIID kTableFrameCID; +/** Data stored by nsCellMap to rationalize rowspan and colspan cells. + * if mCell is null then mRealCell will be the rowspan/colspan source + * in addition, if fOverlap is non-null then it will point to the + * other cell that overlaps this position + * @see nsCellMap + * @see nsTableFrame::BuildCellMap + * @see nsTableFrame::GrowCellMap + * @see nsTableFrame::BuildCellIntoMap + * + */ +class CellData +{ +public: + nsTableCellFrame *mCell; + CellData *mRealCell; + CellData *mOverlap; + + CellData(); + + ~CellData(); +}; + + +/* ============================================================================ */ + /** nsTableFrame maps the inner portion of a table (everything except captions.) * Used as a pseudo-frame within nsTableOuterFrame, * it may also be used stand-alone as the top-level frame. diff --git a/mozilla/layout/html/table/src/nsTablePart.h b/mozilla/layout/html/table/src/nsTablePart.h index 3ba28a8ea9c..479c4def322 100644 --- a/mozilla/layout/html/table/src/nsTablePart.h +++ b/mozilla/layout/html/table/src/nsTablePart.h @@ -23,35 +23,11 @@ #include "nsHTMLContainer.h" // forward declarations -class nsTableCellFrame; -class nsCellMap; class nsTableRowGroup; class nsTableColGroup; class nsTableCol; class nsTableCaption; -/** Data stored by nsCellMap to rationalize rowspan and colspan cells. - * if mCell is null then mRealCell will be the rowspan/colspan source - * in addition, if fOverlap is non-null then it will point to the - * other cell that overlaps this position - * @see nsCellMap - * @see nsTableFrame::BuildCellMap - * @see nsTableFrame::GrowCellMap - * @see nsTableFrame::BuildCellIntoMap - * - */ -class CellData -{ -public: - nsTableCellFrame *mCell; - CellData *mRealCell; - CellData *mOverlap; - - CellData(); - - ~CellData(); -}; - /** * Table Content Model. * We build a full rationalized content model, so the structure of a table @@ -118,7 +94,6 @@ public: protected: /** destructor - * deletes mCellMap, if allocated. */ virtual ~nsTablePart(); diff --git a/mozilla/layout/html/table/src/nsTableRowFrame.cpp b/mozilla/layout/html/table/src/nsTableRowFrame.cpp index cc6d9cf6997..80897b6f69b 100644 --- a/mozilla/layout/html/table/src/nsTableRowFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableRowFrame.cpp @@ -405,16 +405,12 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext, { kidAvailSize.height -= kidMargin.top + kidMargin.bottom; } - // Subtract off for left and right margin - // XXX Why bother doing this if we always set the available width - // based on the column width below? - if (PR_FALSE == aState.unconstrainedWidth) { - kidAvailSize.width -= kidMargin.left + kidMargin.right; - } + + // left and right margins already taken into account by table layout strategy // Compute the x-origin for the child, taking into account straddlers (cells from prior // rows with rowspans > 1) - nscoord x = kidMargin.left; + nscoord x = 0; PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex(); for (PRInt32 colIndex=0; colIndexGetColSpan(); nscoord availWidth = 0; for (PRInt32 numColSpan=0; numColSpanGetColumnWidth(cellStartingCol+numColSpan); + } kidAvailSize.width = availWidth; if (availWidth != ((nsTableCellFrame *)kidFrame)->GetPriorAvailWidth()) { diff --git a/mozilla/layout/tables/BasicTableLayoutStrategy.cpp b/mozilla/layout/tables/BasicTableLayoutStrategy.cpp index c585bbc8baf..d76383ed13b 100644 --- a/mozilla/layout/tables/BasicTableLayoutStrategy.cpp +++ b/mozilla/layout/tables/BasicTableLayoutStrategy.cpp @@ -135,10 +135,10 @@ BasicTableLayoutStrategy::~BasicTableLayoutStrategy() PRBool BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresContext, nsIStyleContext *aTableStyle, const nsReflowState& aReflowState, - PRInt32 aMaxWidth, - PRInt32 &aTotalFixedWidth, - PRInt32 &aMinTableWidth, - PRInt32 &aMaxTableWidth, + nscoord aMaxWidth, + nscoord &aTotalFixedWidth, + nscoord &aMinTableWidth, + nscoord &aMaxTableWidth, nsSize* aMaxElementSize) { PRBool result = PR_TRUE; @@ -615,14 +615,14 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo NS_ASSERTION(nsnull==tablePIF, "never ever call me on a continuing frame!"); #endif - PRBool result = PR_TRUE; + PRBool result = PR_TRUE; nscoord tableWidth=0; // the width of the table as a result of setting column widths PRInt32 totalSlices=0; // the total number of slices the proportional-width columns request nsVoidArray *proportionalColumnsList=nsnull; // a list of the columns that are proportional-width nsVoidArray *spanList=nsnull; // a list of the cells that span columns nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData(); PRInt32 numCols = columnLayoutData->Count(); - PRInt32 * effectiveColumnWidths = new PRInt32[numCols]; // used for Nav4 compatible table fluffing + nscoord * effectiveColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing nsCRT::memset (effectiveColumnWidths, 0, numCols*sizeof(PRInt32)); for (PRInt32 colIndex = 0; colIndexAppendElement (spanInfo); + spanList->AppendElement(spanInfo); } } @@ -887,7 +887,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo nscoord widthPerSlice = widthRemaining/totalSlices; PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count(); for (PRInt32 i=0; iElementAt(i)); nscoord computedColWidth = info->mProportion*widthPerSlice; @@ -896,11 +896,12 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo printf (" 3 proportional step 2: col %d given %d proportion of remaining space %d, set to width = %d\n", info->mColIndex, info->mProportion, widthRemaining, computedColWidth); tableWidth += computedColWidth; + effectiveColumnWidths[info->mColIndex] = computedColWidth; delete info; } } else - { + { // we're in an unconstrained situation, so give each column the max of the max column widths PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count(); PRInt32 maxOfMaxColWidths = 0; PRInt32 i; @@ -920,6 +921,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo printf (" 3 proportional step 2 (unconstrained!): col %d set to width = %d\n", info->mColIndex, maxOfMaxColWidths); tableWidth += maxOfMaxColWidths; + effectiveColumnWidths[info->mColIndex] = maxOfMaxColWidths; delete info; } } @@ -929,9 +931,9 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo // next, if the specified width of the table is greater than the table's computed width, expand the // table's computed width to match the specified width, giving the extra space to proportionately-sized // columns if possible. - if (aTableFixedWidth > tableWidth) + if (aAvailWidth > tableWidth) { - DistributeExcessSpace(aTableFixedWidth, tableWidth, numCols, effectiveColumnWidths); + DistributeExcessSpace(aAvailWidth, tableWidth, effectiveColumnWidths); } // today we always allocate effectiveColumnWidths, but tomorrow we might be smarter, so leave the check in if (nsnull!=effectiveColumnWidths) @@ -941,14 +943,15 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo return result; } +// take the extra space in the table and distribute it proportionately (based on desired width) +// give extra space to auto-width cells first, or if there are none to all cells void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth, nscoord aComputedTableWidth, - PRInt32 aNumCols, - PRInt32 *aColWidths) + nscoord *aColWidths) { - nscoord excess = aTableFixedWidth - aComputedTableWidth; - if (gsDebug) printf ("fixed width %d > computed table width %d, excess = %d\n", - aTableFixedWidth, aComputedTableWidth, excess); + nscoord excess = 0; + if (PR_TRUE==gsDebug) printf ("DistributeExcessSpace: fixed width %d > computed table width %d\n", + aTableFixedWidth, aComputedTableWidth); // if there are auto-sized columns, give them the extra space PRInt32 numAutoColumns=0; PRInt32 *autoColumns=nsnull; @@ -969,14 +972,15 @@ void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth, else totalEffectiveWidthOfAutoColumns += mTableFrame->GetColumnWidth(autoColumns[i]); } + excess = aTableFixedWidth - totalEffectiveWidthOfAutoColumns; // 2. next, compute the proportion to be added to each column, and add it for (i = 0; iGetColumnWidth(autoColumns[i]); + nscoord oldColWidth = aColWidths[colIndex]; float percent; if (0!=totalEffectiveWidthOfAutoColumns) - percent = ((float)(aColWidths[autoColumns[i]]))/((float)totalEffectiveWidthOfAutoColumns); + percent = ((float)(aColWidths[colIndex]))/((float)totalEffectiveWidthOfAutoColumns); else percent = ((float)1)/((float)numAutoColumns); nscoord excessForThisColumn = (nscoord)(excess*percent); @@ -991,10 +995,11 @@ void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth, // (they must be all fixed and percentage-width columns, or we would have gone into the block above) else { - nscoord excessPerColumn = excess/aNumCols; + excess = aTableFixedWidth - aComputedTableWidth; + nscoord excessPerColumn = excess/mNumCols; if (gsDebug==PR_TRUE) printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess); - for (PRInt32 colIndex = 0; colIndexGetColumnLayoutData(); PRInt32 numCols = columnLayoutData->Count(); - PRInt32 * effectiveColumnWidths = new PRInt32[numCols]; // used for Nav4 compatible table fluffing - nsCRT::memset (effectiveColumnWidths, 0, numCols*sizeof(PRInt32)); + nscoord * effectiveMaxColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing + nsCRT::memset (effectiveMaxColumnWidths, 0, numCols*sizeof(PRInt32)); + nscoord * effectiveMinColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing + nsCRT::memset (effectiveMinColumnWidths, 0, numCols*sizeof(PRInt32)); for (PRInt32 colIndex = 0; colIndexElementAt(colIndex)); nsVoidArray *cells = colData->GetCells(); @@ -1149,17 +1158,22 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre if (PR_TRUE==gsDebug) printf("factoring in cell %d with colSpan=%d\n factoring in min=%d and desired=%d\n", cellIndex, colSpan, cellMinWidth, cellDesiredWidth); + // remember the widest min cell width if (minColWidth < cellMinWidth) minColWidth = cellMinWidth; + // effectiveMinColumnWidth is the width as if no cells with colspans existed + if ((1==colSpan) && (effectiveMinColumnWidths[colIndex] < minColWidth)) + effectiveMinColumnWidths[colIndex] = cellMinWidth; + // remember the max desired cell width if (maxColWidth < cellDesiredWidth) maxColWidth = cellDesiredWidth; - // effectiveColumnWidth is the width as if no cells with colspans existed - if ((1==colSpan) && (effectiveColumnWidths[colIndex] < maxColWidth)) - effectiveColumnWidths[colIndex] = cellDesiredWidth; + // effectiveMaxColumnWidth is the width as if no cells with colspans existed + if ((1==colSpan) && (effectiveMaxColumnWidths[colIndex] < maxColWidth)) + effectiveMaxColumnWidths[colIndex] = cellDesiredWidth; if (gsDebug==PR_TRUE) - printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d\n", + printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d,%d\n", cellIndex, minColWidth, maxColWidth, - colIndex, effectiveColumnWidths[colIndex]); + colIndex, effectiveMaxColumnWidths[colIndex], effectiveMaxColumnWidths[colIndex]); if (1GetColumnWidth(colIndex), aAvailWidth); } else if (PR_TRUE==isAutoWidth) - { // column's width is determined by its content - PRUint32 W = aMaxWidth - aMinTableWidth; - PRUint32 D = aMaxTableWidth - aMinTableWidth; - if (0==D) // fixed-size table - D=1; - // XXX really need to use effectiveColumnWidths[colIndex] here - PRUint32 d = maxColWidth - minColWidth; // XXX: if this is 0, set to minColWidth? - PRInt32 width = (d*W)/D; - mTableFrame->SetColumnWidth(colIndex, minColWidth + width); - if (gsDebug==PR_TRUE) - printf (" 4 auto-width: col %d W=%d D=%d d=%d, set to width = %d\n", - colIndex, W, D, d, mTableFrame->GetColumnWidth(colIndex)); + { // column's width is determined by its content, done in post-processing + mTableFrame->SetColumnWidth(colIndex, 0); // set to 0 width for now + atLeastOneAutoWidthColumn = PR_TRUE; } else if (-1!=specifiedProportionColumnWidth) { // we need to save these and do them after all other columns have been calculated @@ -1309,7 +1317,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre } } /* --- post-process if necessary --- */ - // first, assign a width to proportional-width columns + if (PR_TRUE==atLeastOneAutoWidthColumn) + { // proportionately distribute the remaining space to autowidth columns + DistributeRemainingSpace(aMaxWidth, tableWidth, effectiveMinColumnWidths, effectiveMaxColumnWidths); + } + // second, assign a width to proportional-width columns if (nsnull!=proportionalColumnsList) { // first, figure out the amount of space per slice @@ -1339,14 +1351,76 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre } delete proportionalColumnsList; } - + + // clean up // today we always allocate effectiveColumnWidths, but tomorrow we might be smarter, so leave the check in - if (nsnull!=effectiveColumnWidths) - delete [] effectiveColumnWidths; + if (nsnull!=effectiveMinColumnWidths) + delete [] effectiveMinColumnWidths; + if (nsnull!=effectiveMaxColumnWidths) + delete [] effectiveMaxColumnWidths; if (nsnull!=spanList) delete spanList; return result; } +//XXX: make sure aTFW takes into account fixed width cells already assigned +// take the remaining space in the table and distribute it proportionately +// to the auto-width cells in the table (based on desired width) +void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableFixedWidth, + nscoord aComputedTableWidth, + nscoord *aMinColWidths, + nscoord *aMaxColWidths) +{ + if (PR_TRUE==gsDebug) + printf ("DistributeRemainingSpace: fixed width %d > computed table width %d\n", + aTableFixedWidth, aComputedTableWidth); + // if there are auto-sized columns, give them the extra space + PRInt32 numAutoColumns=0; + PRInt32 *autoColumns=nsnull; + // availWidth is the difference between the total available width and the + // amount of space already assigned, assuming auto col widths were assigned 0. + nscoord availWidth = aTableFixedWidth - aComputedTableWidth; + mTableFrame->GetColumnsByType(eStyleUnit_Auto, numAutoColumns, autoColumns); + if (0!=numAutoColumns) + { + // there's at least one auto-width column, so give it (them) the extra space + // proportionately distributed extra space, based on the column's desired size + nscoord totalEffectiveWidthOfAutoColumns = 0; + // 1. first, get the total width of the auto columns + PRInt32 i; + for (i = 0; iGetColumnWidth(autoColumns[i]); + } + if (gsDebug==PR_TRUE) + printf(" aTableFixedWidth specified as %d, availWidth is = %d\n", + aTableFixedWidth, availWidth); + + // 2. next, compute the proportion to be added to each column, and add it + for (i = 0; iSetColumnWidth(colIndex, colWidth); + } + } +} + diff --git a/mozilla/layout/tables/BasicTableLayoutStrategy.h b/mozilla/layout/tables/BasicTableLayoutStrategy.h index bb272fab46e..05e843b88af 100644 --- a/mozilla/layout/tables/BasicTableLayoutStrategy.h +++ b/mozilla/layout/tables/BasicTableLayoutStrategy.h @@ -169,14 +169,27 @@ public: * @param aTableFixedWidth the specified width of the table. If there is none, * this param is 0 * @param aComputedTableWidth the width of the table before this final step. - * @param aNumCols the number of columns in the table * * @return void */ virtual void DistributeExcessSpace(nscoord aTableFixedWidth, nscoord aComputedTableWidth, - PRInt32 aNumCols, - PRInt32 *aColWidths); + nscoord *aColWidths); + + /** starting with a partially balanced table, compute the amount + * of space to remove from each column to completely balance the table. + * set the column widths in mTableFrame based on these computations. + * + * @param aTableFixedWidth the specified width of the table. If there is none, + * this param is 0 + * @param aComputedTableWidth the width of the table before this final step. + * + * @return void + */ + virtual void DistributeRemainingSpace(nscoord aTableFixedWidth, + nscoord aComputedTableWidth, + nscoord *aMinColWidths, + nscoord *aMaxColWidths); /** return true if the style indicates that the width is a specific width * for the purposes of column width determination. diff --git a/mozilla/layout/tables/nsCellMap.h b/mozilla/layout/tables/nsCellMap.h index 6d5d4d3fce2..15f9e6c441a 100644 --- a/mozilla/layout/tables/nsCellMap.h +++ b/mozilla/layout/tables/nsCellMap.h @@ -38,7 +38,7 @@ class nsCellMap { protected: /** storage for CellData pointers */ - PRInt32 *mCells; + PRInt32 *mCells; ///XXX CellData *? /** the number of rows */ int mRowCount; // in java, we could just do fCellMap.length; diff --git a/mozilla/layout/tables/nsTableCellFrame.cpp b/mozilla/layout/tables/nsTableCellFrame.cpp index 72ffeafca3e..00676145a18 100644 --- a/mozilla/layout/tables/nsTableCellFrame.cpp +++ b/mozilla/layout/tables/nsTableCellFrame.cpp @@ -268,10 +268,9 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, CreatePsuedoFrame(aPresContext); } - // reduce available space by insets - + // reduce available space by insets, if we're in a constrained situation if (NS_UNCONSTRAINEDSIZE!=availSize.width) - availSize.width -= leftInset+rightInset+margin.left+margin.right; + availSize.width -= leftInset+rightInset; if (NS_UNCONSTRAINEDSIZE!=availSize.height) availSize.height -= topInset+bottomInset+margin.top+margin.bottom; @@ -305,9 +304,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, } SetFirstContentOffset(mFirstChild); - //if (gsDebug) printf("CELL: set first content offset to %d\n", GetFirstContentOffset()); //@@@ SetLastContentOffset(mFirstChild); - //if (gsDebug) printf("CELL: set last content offset to %d\n", GetLastContentOffset()); //@@@ // Place the child mFirstChild->SetRect(nsRect(leftInset, topInset, @@ -332,13 +329,8 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, printf(" %p cellFrame height set to %d from kidSize=%d and insets %d,%d\n", this, cellHeight, kidSize.height, topInset, bottomInset); // next determine the cell's width - nscoord cellWidth = kidSize.width; // at this point, we've factored in the cell's style attributes - // if we're really in a constrained situation, factor in insets - if (NS_UNCONSTRAINEDSIZE!=aReflowState.maxSize.width) - { - NS_ASSERTION(NS_UNCONSTRAINEDSIZE!=cellWidth, "child says it has unconstrained width in a constrained case"); - cellWidth += leftInset + rightInset; - } + nscoord cellWidth = kidSize.width; // at this point, we've factored in the cell's style attributes + cellWidth += leftInset + rightInset; // factor in insets // Nav4 hack for 0 width cells. If the cell has any content, it must have a desired width of at least 1 /* @@ -370,10 +362,8 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, if (nsnull!=aDesiredSize.maxElementSize) { *aDesiredSize.maxElementSize = *pMaxElementSize; - if (NS_UNCONSTRAINEDSIZE!=aReflowState.maxSize.height) - aDesiredSize.maxElementSize->height += topInset + bottomInset; - if (NS_UNCONSTRAINEDSIZE!=aReflowState.maxSize.width) - aDesiredSize.maxElementSize->width += leftInset + rightInset; + aDesiredSize.maxElementSize->height += topInset + bottomInset; + aDesiredSize.maxElementSize->width += leftInset + rightInset; } if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) diff --git a/mozilla/layout/tables/nsTableFrame.h b/mozilla/layout/tables/nsTableFrame.h index 106f64415da..654920edc84 100644 --- a/mozilla/layout/tables/nsTableFrame.h +++ b/mozilla/layout/tables/nsTableFrame.h @@ -29,7 +29,6 @@ class nsTableCellFrame; class nsTableColFrame; class nsTableRowGroupFrame; class nsTableRowFrame; -class CellData; class nsITableLayoutStrategy; class nsHTMLValue; class ColumnInfoCache; @@ -43,6 +42,31 @@ struct nsStyleSpacing; extern const nsIID kTableFrameCID; +/** Data stored by nsCellMap to rationalize rowspan and colspan cells. + * if mCell is null then mRealCell will be the rowspan/colspan source + * in addition, if fOverlap is non-null then it will point to the + * other cell that overlaps this position + * @see nsCellMap + * @see nsTableFrame::BuildCellMap + * @see nsTableFrame::GrowCellMap + * @see nsTableFrame::BuildCellIntoMap + * + */ +class CellData +{ +public: + nsTableCellFrame *mCell; + CellData *mRealCell; + CellData *mOverlap; + + CellData(); + + ~CellData(); +}; + + +/* ============================================================================ */ + /** nsTableFrame maps the inner portion of a table (everything except captions.) * Used as a pseudo-frame within nsTableOuterFrame, * it may also be used stand-alone as the top-level frame. diff --git a/mozilla/layout/tables/nsTableRowFrame.cpp b/mozilla/layout/tables/nsTableRowFrame.cpp index cc6d9cf6997..80897b6f69b 100644 --- a/mozilla/layout/tables/nsTableRowFrame.cpp +++ b/mozilla/layout/tables/nsTableRowFrame.cpp @@ -405,16 +405,12 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext, { kidAvailSize.height -= kidMargin.top + kidMargin.bottom; } - // Subtract off for left and right margin - // XXX Why bother doing this if we always set the available width - // based on the column width below? - if (PR_FALSE == aState.unconstrainedWidth) { - kidAvailSize.width -= kidMargin.left + kidMargin.right; - } + + // left and right margins already taken into account by table layout strategy // Compute the x-origin for the child, taking into account straddlers (cells from prior // rows with rowspans > 1) - nscoord x = kidMargin.left; + nscoord x = 0; PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex(); for (PRInt32 colIndex=0; colIndexGetColSpan(); nscoord availWidth = 0; for (PRInt32 numColSpan=0; numColSpanGetColumnWidth(cellStartingCol+numColSpan); + } kidAvailSize.width = availWidth; if (availWidth != ((nsTableCellFrame *)kidFrame)->GetPriorAvailWidth()) {