From 2ed65950de07b8227bc06b51ec0c78be2e1c9b51 Mon Sep 17 00:00:00 2001 From: "dholbert@cs.stanford.edu" Date: Thu, 17 Jan 2008 20:18:21 -0800 Subject: [PATCH] Bug 368504: Create and use DistributeWidthToColumns for colspan-width and table-width distribution. r+sr=dbaron a=blocking1.9+ --- layout/reftests/bugs/368504-6-ref.html | 16 + layout/reftests/bugs/368504-6.html | 19 + layout/reftests/bugs/reftest.list | 13 +- layout/tables/BasicTableLayoutStrategy.cpp | 429 ++++++++++----------- layout/tables/BasicTableLayoutStrategy.h | 33 ++ layout/tables/nsTableColFrame.cpp | 4 +- layout/tables/nsTableColFrame.h | 10 +- 7 files changed, 275 insertions(+), 249 deletions(-) create mode 100644 layout/reftests/bugs/368504-6-ref.html create mode 100644 layout/reftests/bugs/368504-6.html diff --git a/layout/reftests/bugs/368504-6-ref.html b/layout/reftests/bugs/368504-6-ref.html new file mode 100644 index 000000000000..f63c687c17db --- /dev/null +++ b/layout/reftests/bugs/368504-6-ref.html @@ -0,0 +1,16 @@ + + + xxx + + + + + + + + + + +
x x x x x x x x x x x x xxx
xxxxxxxxx
+ + diff --git a/layout/reftests/bugs/368504-6.html b/layout/reftests/bugs/368504-6.html new file mode 100644 index 000000000000..c571302f8e0c --- /dev/null +++ b/layout/reftests/bugs/368504-6.html @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + +
xxx 
x x x x x x x x x x x x xxx
xxxxxxxxx
+ + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 6ef143947c36..4754c7bf822f 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -383,12 +383,13 @@ random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == 368020-5.html 368020-5-ref.html # bug 3 # is too exact # == 368247-1.html 368247-1-ref.html == 368247-2.html 368247-2-ref.html -fails == 368504-1.html 368504-1-ref.html -fails == 368504-2.html 368504-2-ref.html -fails == 368504-3a.html 368504-3-ref.html -fails == 368504-3b.html 368504-3-ref.html -fails == 368504-4.html 368504-4-ref.html -fails == 368504-5.html 368504-5-ref.html +== 368504-1.html 368504-1-ref.html +== 368504-2.html 368504-2-ref.html +== 368504-3a.html 368504-3-ref.html +== 368504-3b.html 368504-3-ref.html +== 368504-4.html 368504-4-ref.html +== 368504-5.html 368504-5-ref.html +== 368504-6.html 368504-6-ref.html == 368622-1.html 368622-1-ref.html == 368622-1.html 368622-1-ref.html == 368651-1.html 368651-1-ref.html diff --git a/layout/tables/BasicTableLayoutStrategy.cpp b/layout/tables/BasicTableLayoutStrategy.cpp index c511f9dd1c05..6e0a265c7859 100644 --- a/layout/tables/BasicTableLayoutStrategy.cpp +++ b/layout/tables/BasicTableLayoutStrategy.cpp @@ -254,7 +254,6 @@ BasicTableLayoutStrategy::ComputeColumnIntrinsicWidths(nsIRenderingContext* aRen nsTableFrame *tableFrame = mTableFrame; nsTableCellMap *cellMap = tableFrame->GetCellMap(); - nscoord spacing = tableFrame->GetCellSpacingX(); SpanningCellSorter spanningCells(tableFrame->PresContext()->PresShell()); // Loop over the columns to consider the columns and cells *without* @@ -351,191 +350,14 @@ BasicTableLayoutStrategy::ComputeColumnIntrinsicWidths(nsIRenderingContext* aRen CellWidthInfo info = GetCellWidthInfo(aRenderingContext, cellFrame); - // Before looping over the spanned columns to distribute - // this cell's width over the columns it spans, we first - // compute totals over the spanned columns so we know how to - // allocate the space. - - // Accumulate information about the spanned columns, and - // subtract the already-used space from |info|. - nscoord totalSPref = 0, totalSMin = 0; // total existing widths - nscoord totalSNonPctPref = 0; // total pref width of columns - // without percentage widths - nscoord totalSAutoPref = 0; // total pref width of auto-width cols - PRInt32 nonPctCount = 0; // # of columns without percentage widths - PRInt32 scol, scol_end; - for (scol = col, scol_end = col + colSpan; - scol < scol_end; ++scol) { - nsTableColFrame *scolFrame = tableFrame->GetColFrame(scol); - if (!scolFrame) { - NS_ERROR("column frames out of sync with cell map"); - continue; - } - - if (mTableFrame->GetNumCellsOriginatingInCol(scol) && - scol != col) { - info.minCoord -= spacing; - info.prefCoord = NSCoordSaturatingSubtract(info.prefCoord, - spacing, - nscoord_MAX); - } - - totalSPref += scolFrame->GetPrefCoord(); - totalSMin += scolFrame->GetMinCoord(); - if (!scolFrame->GetHasSpecifiedCoord()) { - totalSAutoPref += scolFrame->GetPrefCoord(); - } - float scolPct = scolFrame->GetPrefPercent(); - if (scolPct == 0.0f) { - totalSNonPctPref += scolFrame->GetPrefCoord(); - ++nonPctCount; - } else { - info.prefPercent -= scolPct; - } - info.minCoord -= scolFrame->GetMinCoord(); - info.prefCoord = - NSCoordSaturatingSubtract(info.prefCoord, - scolFrame->GetPrefCoord(), - nscoord_MAX); + if (info.prefPercent > 0.0f) { + DistributePctWidthToColumns(info.prefPercent, + col, colSpan); } - - if (info.minCoord < 0) - info.minCoord = 0; - if (info.prefCoord < 0) - info.prefCoord = 0; - if (info.prefPercent < 0.0f) - info.prefPercent = 0.0f; - - // The min-width of this cell that fits inside the - // pref-width of the spanned columns gets distributed - // according to different ratios. - nscoord minWithinPref = - PR_MIN(info.minCoord, totalSPref - totalSMin); - NS_ASSERTION(minWithinPref >= 0, "neither value can be negative"); - nscoord minOutsidePref = info.minCoord - minWithinPref; - - // Loop invariants (that we might get confused about as we - // subtract amounts for completed columns) - const PRBool spanHasNonPctPref = totalSNonPctPref > 0; - const PRBool spanHasPref = totalSPref > 0; - const PRBool spanHasNonPct = nonPctCount > 0; - - // ... and actually do the distribution of the widths of - // this cell exceeding the totals already in the spanned - // columns. - for (scol = col, scol_end = col + colSpan; - scol < scol_end; ++scol) { - nsTableColFrame *scolFrame = tableFrame->GetColFrame(scol); - if (!scolFrame) { - NS_ERROR("column frames out of sync with cell map"); - continue; - } - - // the percentage width (only to columns that don't - // already have percentage widths, in proportion to - // the existing pref widths) - float allocatedPct = 0.0f; - if (scolFrame->GetPrefPercent() == 0.0f && - info.prefPercent != 0.0f) { - NS_ASSERTION((!spanHasNonPctPref || - totalSNonPctPref != 0) && - nonPctCount != 0, - "should not be zero if we haven't allocated " - "all pref percent"); - if (spanHasNonPctPref) { - // Group so we're multiplying by 1.0f when we need - // to use up info.prefPercent. - allocatedPct = info.prefPercent * - (float(scolFrame->GetPrefCoord()) / - float(totalSNonPctPref)); - } else { - // distribute equally when all pref widths are 0 - allocatedPct = info.prefPercent / float(nonPctCount); - } - scolFrame->AddSpanPrefPercent(allocatedPct); - } - - // the part of the min width that fits within the - // existing pref width - float minRatio = 0.0f; - if (minWithinPref > 0) { - minRatio = float(scolFrame->GetPrefCoord() - - scolFrame->GetMinCoord()) / - float(totalSPref - totalSMin); - } - - // the rest of the min width, and the pref width (in - // proportion to the existing pref widths) - float coordRatio; // for both min and pref - if (spanHasPref) { - if (scolFrame->GetPrefCoord() == 0) { - // We might have already subtracted all of - // totalSPref. - coordRatio = 0.0f; - } else if (totalSAutoPref == 0) { - // No auto-width cols left -- dividing up totalSPref - coordRatio = float(scolFrame->GetPrefCoord()) / - float(totalSPref); - } else if (!scolFrame->GetHasSpecifiedCoord()) { - // There are auto-width cols left, and this is one - coordRatio = float(scolFrame->GetPrefCoord()) / - float(totalSAutoPref); - } else { - // There are auto-width cols left, and this isn't one - coordRatio = 0.0f; - } - } else { - // distribute equally when all pref widths are 0 - coordRatio = 1.0f / float(scol_end - scol); - } - - // combine the two min-width distributions, and record - // min and pref - nscoord allocatedMinWithinPref = - NSToCoordRound(float(minWithinPref) * minRatio); - nscoord allocatedMinOutsidePref = - NSToCoordRound(float(minOutsidePref) * coordRatio); - nscoord allocatedPref = - (info.prefCoord == nscoord_MAX ? - nscoord_MAX : - NSToCoordRound(float(info.prefCoord) * coordRatio)); - nscoord spanMin = scolFrame->GetMinCoord() + - allocatedMinWithinPref + allocatedMinOutsidePref; - nscoord spanPref = - NSCoordSaturatingAdd(scolFrame->GetPrefCoord(), - allocatedPref); - scolFrame->AddSpanCoords(spanMin, spanPref, - info.hasSpecifiedWidth); - - // To avoid accumulating rounding error from division, - // subtract everything to do with the column we've - // passed from the totals. - minWithinPref -= allocatedMinWithinPref; - minOutsidePref -= allocatedMinOutsidePref; - info.prefCoord = NSCoordSaturatingSubtract(info.prefCoord, - allocatedPref, - nscoord_MAX); - info.prefPercent -= allocatedPct; - totalSPref -= scolFrame->GetPrefCoord(); - totalSMin -= scolFrame->GetMinCoord(); - if (!scolFrame->GetHasSpecifiedCoord()) { - totalSAutoPref -= scolFrame->GetPrefCoord(); - } - if (scolFrame->GetPrefPercent() == 0.0f) { - totalSNonPctPref -= scolFrame->GetPrefCoord(); - --nonPctCount; - } - } - - // Note that we only distribute the percentage if - // spanHasNonPct. - NS_ASSERTION(totalSPref == 0 && totalSMin == 0 && - totalSNonPctPref == 0 && nonPctCount == 0 && - minOutsidePref == 0 && minWithinPref == 0 && - (info.prefCoord == 0 || - info.prefCoord == nscoord_MAX) && - (info.prefPercent == 0.0f || !spanHasNonPct), - "didn't subtract all that we added"); + DistributeWidthToColumns(info.minCoord, col, colSpan, + BTLS_MIN_WIDTH, info.hasSpecifiedWidth); + DistributeWidthToColumns(info.prefCoord, col, colSpan, + BTLS_PREF_WIDTH, info.hasSpecifiedWidth); } while ((item = item->next)); // Combine the results of the span analysis into the main results, @@ -699,25 +521,128 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt if (colCount <= 0) return; // nothing to do - nscoord spacing = mTableFrame->GetCellSpacingX(); + DistributeWidthToColumns(width, 0, colCount, BTLS_FINAL_WIDTH, PR_FALSE); - nscoord min = mMinWidth; +#ifdef DEBUG_TABLE_STRATEGY + printf("ComputeColumnWidths final\n"); + mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE); +#endif +} + +void +BasicTableLayoutStrategy::DistributePctWidthToColumns(float aSpanPrefPct, + PRInt32 aFirstCol, + PRInt32 aColCount) +{ + // First loop to determine: + PRInt32 nonPctColCount = 0; // number of spanned columns without % width + nscoord nonPctTotalPrefWidth = 0; // total pref width of those columns + // and to reduce aSpanPrefPct by columns that already have % width + + PRInt32 scol, scol_end; + for (scol = aFirstCol, scol_end = aFirstCol + aColCount; + scol < scol_end; ++scol) { + nsTableColFrame *scolFrame = mTableFrame->GetColFrame(scol); + if (!scolFrame) { + NS_ERROR("column frames out of sync with cell map"); + continue; + } + float scolPct = scolFrame->GetPrefPercent(); + if (scolPct == 0.0f) { + nonPctTotalPrefWidth += scolFrame->GetPrefCoord(); + ++nonPctColCount; + } else { + aSpanPrefPct -= scolPct; + } + } + + if (aSpanPrefPct <= 0.0f || nonPctColCount == 0) { + // There's no %-width on the colspan left over to distribute, + // or there are no columns to which we could distribute %-width + return; + } + + // Second loop, to distribute what remains of aSpanPrefPct + // between the non-percent-width spanned columns + const PRBool spanHasNonPctPref = nonPctTotalPrefWidth > 0; // Loop invariant + for (scol = aFirstCol, scol_end = aFirstCol + aColCount; + scol < scol_end; ++scol) { + nsTableColFrame *scolFrame = mTableFrame->GetColFrame(scol); + if (!scolFrame) { + NS_ERROR("column frames out of sync with cell map"); + continue; + } + + // the percentage width (only to columns that don't + // already have percentage widths, in proportion to + // the existing pref widths) + float allocatedPct = 0.0f; + if (scolFrame->GetPrefPercent() == 0.0f) { + NS_ASSERTION((!spanHasNonPctPref || + nonPctTotalPrefWidth != 0) && + nonPctColCount != 0, + "should not be zero if we haven't allocated " + "all pref percent"); + if (spanHasNonPctPref) { + // Group so we're multiplying by 1.0f when we need + // to use up aSpanPrefPct. + allocatedPct = aSpanPrefPct * + (float(scolFrame->GetPrefCoord()) / + float(nonPctTotalPrefWidth)); + } else { + // distribute equally when all pref widths are 0 + allocatedPct = aSpanPrefPct / float(nonPctColCount); + } + // Allocate the percent + scolFrame->AddSpanPrefPercent(allocatedPct); + + // To avoid accumulating rounding error from division, + // subtract this column's values from the totals. + aSpanPrefPct -= allocatedPct; + nonPctTotalPrefWidth -= scolFrame->GetPrefCoord(); + --nonPctColCount; + } + } +} + +void +BasicTableLayoutStrategy::DistributeWidthToColumns(nscoord aWidth, + PRInt32 aFirstCol, + PRInt32 aColCount, + BtlsWidthType aWidthType, + PRBool aSpanHasSpecifiedWidth) +{ + NS_ASSERTION(aWidthType != BTLS_FINAL_WIDTH || + (aFirstCol == 0 && + aColCount == mTableFrame->GetCellMap()->GetColCount()), + "Computing final column widths, but didn't get full column range"); // border-spacing isn't part of the basis for percentages. - nscoord subtract = spacing; - for (PRInt32 col = 0; col < colCount; ++col) { + nscoord spacing = mTableFrame->GetCellSpacingX(); + nscoord subtract = 0; + // aWidth initially includes border-spacing for the boundaries in between + // each of the columns. We start at aFirstCol + 1 because the first + // in-between boundary would be at the left edge of column aFirstCol + 1 + for (PRInt32 col = aFirstCol + 1; col < aFirstCol + aColCount; ++col) { if (mTableFrame->GetNumCellsOriginatingInCol(col)) { subtract += spacing; } } - width = NSCoordSaturatingSubtract(width, subtract, nscoord_MAX); - min -= subtract; - - // XXX is |width| the right basis for percentage widths? + if (aWidthType == BTLS_FINAL_WIDTH) { + // If we're computing final col-width, then aWidth initially includes + // border spacing on the table's far left + far right edge, too. Need + // to subtract those out, too. + subtract += spacing * 2; + } + aWidth = NSCoordSaturatingSubtract(aWidth, subtract, nscoord_MAX); /* - * The goal of this function is to allocate |width| to the columns - * by making an appropriate SetFinalWidth call to each column. + * The goal of this function is to distribute |aWidth| between the + * columns by making an appropriate AddSpanCoords or SetFinalWidth + * call for each column. (We call AddSpanCoords if we're + * distributing a column-spanning cell's minimum or preferred width + * to its spanned columns. We call SetFinalWidth if we're + * distributing a table's final width to its columns.) * * The idea is to either assign one of the following sets of widths * or a weighted average of two adjacent sets of widths. It is not @@ -740,7 +665,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt * 4. [guess_pref] Assign all columns with percentage widths their * specified width, and all other columns their pref width. * - * If |width| is *larger* than what we would assign in (4), then we + * If |aWidth| is *larger* than what we would assign in (4), then we * expand the columns: * * a. if any columns without a specified coordinate width or @@ -769,7 +694,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt PRInt32 numInfiniteWidthCols = 0; PRInt32 col; - for (col = 0; col < colCount; ++col) { + for (col = aFirstCol; col < aFirstCol + aColCount; ++col) { nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); if (!colFrame) { NS_ERROR("column frames out of sync with cell map"); @@ -780,7 +705,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt if (colFrame->GetPrefPercent() != 0.0f) { float pct = colFrame->GetPrefPercent(); total_pct += pct; - nscoord val = nscoord(float(width) * pct); + nscoord val = nscoord(float(aWidth) * pct); if (val < min_width) val = min_width; guess_min_pct += val; @@ -813,10 +738,10 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt FLEX_PCT_SMALL, // between (1) and (2) above FLEX_FIXED_SMALL, // between (2) and (3) above FLEX_FLEX_SMALL, // between (3) and (4) above - FLEX_FLEX_LARGE, // above (4) above, case (a) - FLEX_FIXED_LARGE, // above (4) above, case (b) - FLEX_PCT_LARGE, // above (4) above, case (c) - FLEX_ALL_LARGE // above (4) above, case (d) + FLEX_FLEX_LARGE, // greater than (4) above, case (a) + FLEX_FIXED_LARGE, // greater than (4) above, case (b) + FLEX_PCT_LARGE, // greater than (4) above, case (c) + FLEX_ALL_LARGE // greater than (4) above, case (d) }; Loop2Type l2t; @@ -828,28 +753,32 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt nscoord c; float f; } basis; // the sum of the statistic over columns to divide it - if (width < guess_pref) { - NS_ASSERTION(width >= guess_min, "bad width"); - if (width < guess_min_pct) { + if (aWidth < guess_pref) { + if ((aWidthType == BTLS_MIN_WIDTH && aWidth <= guess_min) || + (aWidthType == BTLS_PREF_WIDTH && aWidth <= guess_pref)) { + // Return early -- we don't have any extra space to distribute. + return; + } + NS_ASSERTION(!(aWidthType == BTLS_FINAL_WIDTH && aWidth < guess_min), + "Table width is less than the " + "sum of its columns' min widths"); + if (aWidth < guess_min_pct) { l2t = FLEX_PCT_SMALL; - space = width - guess_min; + space = aWidth - guess_min; basis.c = guess_min_pct - guess_min; - } else if (width < guess_min_spec) { + } else if (aWidth < guess_min_spec) { l2t = FLEX_FIXED_SMALL; - space = width - guess_min_pct; + space = aWidth - guess_min_pct; basis.c = NSCoordSaturatingSubtract(guess_min_spec, guess_min_pct, nscoord_MAX); } else { l2t = FLEX_FLEX_SMALL; - space = width - guess_min_spec; + space = aWidth - guess_min_spec; basis.c = NSCoordSaturatingSubtract(guess_pref, guess_min_spec, nscoord_MAX); } } else { - // Note: Shouldn't have to check for nscoord_MAX in this case, because - // width should be much less than nscoord_MAX, and being here means - // guess_pref is no larger than width. - space = width - guess_pref; + space = NSCoordSaturatingSubtract(aWidth, guess_pref, nscoord_MAX); if (total_flex_pref > 0) { l2t = FLEX_FLEX_LARGE; basis.c = total_flex_pref; @@ -861,7 +790,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt basis.f = total_pct; } else { l2t = FLEX_ALL_LARGE; - basis.c = colCount; + basis.c = aColCount; } } @@ -869,13 +798,13 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt printf("ComputeColumnWidths: %d columns in width %d,\n" " guesses=[%d,%d,%d,%d], totals=[%d,%d,%f],\n" " l2t=%d, space=%d, basis.c=%d\n", - colCount, width, + aColCount, aWidth, guess_min, guess_min_pct, guess_min_spec, guess_pref, total_flex_pref, total_fixed_pref, total_pct, l2t, space, basis.c); #endif - for (col = 0; col < colCount; ++col) { + for (col = aFirstCol; col < aFirstCol + aColCount; ++col) { nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); if (!colFrame) { NS_ERROR("column frames out of sync with cell map"); @@ -885,7 +814,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt float pct = colFrame->GetPrefPercent(); if (pct != 0.0f) { - col_width = nscoord(float(width) * pct); + col_width = nscoord(float(aWidth) * pct); nscoord col_min = colFrame->GetMinCoord(); if (col_width < col_min) col_width = col_min; @@ -900,7 +829,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt col_width = col_width_before_adjust = colFrame->GetMinCoord(); if (pct != 0.0f) { nscoord pct_minus_min = - nscoord(float(width) * pct) - col_width; + nscoord(float(aWidth) * pct) - col_width; if (pct_minus_min > 0) { float c = float(space) / float(basis.c); basis.c -= pct_minus_min; @@ -968,9 +897,14 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt NS_ASSERTION(col_width == colFrame->GetPrefCoord(), "wrong width assigned"); if (col_width != 0) { - float c = float(space) / float(basis.c); - basis.c -= col_width; - col_width += NSToCoordRound(float(col_width) * c); + if (space == nscoord_MAX) { + basis.c -= col_width; + col_width = nscoord_MAX; + } else { + float c = float(space) / float(basis.c); + basis.c -= col_width; + col_width += NSToCoordRound(float(col_width) * c); + } } } break; @@ -1006,24 +940,53 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt break; } - space -= col_width - col_width_before_adjust; + // Only subtract from space if it's a real number. + if (space != nscoord_MAX) { + NS_ASSERTION(col_width != nscoord_MAX, + "How is col_width nscoord_MAX if space isn't?"); + NS_ASSERTION(col_width_before_adjust != nscoord_MAX, + "How is col_width_before_adjust nscoord_MAX if space isn't?"); + space -= col_width - col_width_before_adjust; + } NS_ASSERTION(col_width >= colFrame->GetMinCoord(), "assigned width smaller than min"); - - nscoord old_final = colFrame->GetFinalWidth(); - colFrame->SetFinalWidth(col_width); - - if (old_final != col_width) - mTableFrame->DidResizeColumns(); + + // Apply the new width + switch (aWidthType) { + case BTLS_MIN_WIDTH: + { + // Note: AddSpanCoords requires both a min and pref width. + // For the pref width, we'll just pass in our computed + // min width, because the real pref width will be at least + // as big + colFrame->AddSpanCoords(col_width, col_width, + aSpanHasSpecifiedWidth); + } + break; + case BTLS_PREF_WIDTH: + { + // Note: AddSpanCoords requires both a min and pref width. + // For the min width, we'll just pass in 0, because + // the real min width will be at least 0 + colFrame->AddSpanCoords(0, col_width, + aSpanHasSpecifiedWidth); + } + break; + case BTLS_FINAL_WIDTH: + { + nscoord old_final = colFrame->GetFinalWidth(); + colFrame->SetFinalWidth(col_width); + + if (old_final != col_width) + mTableFrame->DidResizeColumns(); + } + break; + } } - NS_ASSERTION(space == 0 && + NS_ASSERTION((space == 0 || space == nscoord_MAX) && ((l2t == FLEX_PCT_LARGE) ? (-0.001f < basis.f && basis.f < 0.001f) : (basis.c == 0 || basis.c == nscoord_MAX)), "didn't subtract all that we added"); -#ifdef DEBUG_TABLE_STRATEGY - printf("ComputeColumnWidths final\n"); - mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE); -#endif } diff --git a/layout/tables/BasicTableLayoutStrategy.h b/layout/tables/BasicTableLayoutStrategy.h index 62dcb5882f6f..205b682feff4 100644 --- a/layout/tables/BasicTableLayoutStrategy.h +++ b/layout/tables/BasicTableLayoutStrategy.h @@ -62,9 +62,42 @@ public: virtual void ComputeColumnWidths(const nsHTMLReflowState& aReflowState); private: + // NOTE: Using prefix "BTLS" to avoid overlapping names with + // the values of nsLayoutUtils::IntrinsicWidthType + enum BtlsWidthType { BTLS_MIN_WIDTH, + BTLS_PREF_WIDTH, + BTLS_FINAL_WIDTH }; + // Compute intrinsic width member variables on the columns. void ComputeColumnIntrinsicWidths(nsIRenderingContext* aRenderingContext); + // Distribute a colspanning cell's percent width (if any) to its columns. + void DistributePctWidthToColumns(float aSpanPrefPct, + PRInt32 aFirstCol, + PRInt32 aColCount); + + // Distribute a width of some BltsWidthType type to a set of columns. + // aWidth: The amount of width to be distributed + // aFirstCol: The index (in the table) of the first column to be + // considered for receiving width + // aColCount: The number of consecutive columns (starting with aFirstCol) + // to be considered for receiving width + // aWidthType: The type of width being distributed. (BTLS_MIN_WIDTH and + // BTLS_PREF_WIDTH are intended to be used for dividing up + // colspan's min & pref width. BTLS_FINAL_WIDTH is intended + // to be used for distributing the table's final width across + // all its columns) + // aSpanHasSpecifiedWidth: Should be PR_TRUE iff: + // - We're distributing a colspanning cell's + // pref or min width to its columns + // - The colspanning cell has a specified width. + void DistributeWidthToColumns(nscoord aWidth, + PRInt32 aFirstCol, + PRInt32 aColCount, + BtlsWidthType aWidthType, + PRBool aSpanHasSpecifiedWidth); + + // Compute the min and pref widths of the table from the width // variables on the columns. void ComputeIntrinsicWidths(nsIRenderingContext* aRenderingContext); diff --git a/layout/tables/nsTableColFrame.cpp b/layout/tables/nsTableColFrame.cpp index 1d9aa6d3b9a7..2f6599c8fd1f 100644 --- a/layout/tables/nsTableColFrame.cpp +++ b/layout/tables/nsTableColFrame.cpp @@ -155,9 +155,9 @@ void nsTableColFrame::Dump(PRInt32 aIndent) printf(" anonymous-cell "); break; } - printf("\nm:%d c:%d(%c) p:%f sm:%d sc:%d(%c) sp:%f f:%d", + printf("\nm:%d c:%d(%c) p:%f sm:%d sc:%d sp:%f f:%d", mMinCoord, mPrefCoord, mHasSpecifiedCoord ? 's' : 'u', mPrefPercent, - mSpanMinCoord, mSpanPrefCoord, mSpanHasSpecifiedCoord ? 's' : 'u', + mSpanMinCoord, mSpanPrefCoord, mSpanPrefPercent, GetFinalWidth()); printf("\n%s**END COL DUMP** ", indent); diff --git a/layout/tables/nsTableColFrame.h b/layout/tables/nsTableColFrame.h index 15cd58bd8582..146eec19acc6 100644 --- a/layout/tables/nsTableColFrame.h +++ b/layout/tables/nsTableColFrame.h @@ -165,7 +165,6 @@ public: mSpanMinCoord = 0; mSpanPrefCoord = 0; mSpanPrefPercent = 0.0f; - mSpanHasSpecifiedCoord = PR_FALSE; } /** @@ -249,11 +248,7 @@ public: NS_ASSERTION(aSpanMinCoord <= aSpanPrefCoord, "intrinsic widths out of order"); - if (aSpanHasSpecifiedCoord && !mSpanHasSpecifiedCoord) { - mSpanPrefCoord = mSpanMinCoord; - mSpanHasSpecifiedCoord = PR_TRUE; - } - if (!aSpanHasSpecifiedCoord && mSpanHasSpecifiedCoord) { + if (!aSpanHasSpecifiedCoord && mHasSpecifiedCoord) { aSpanPrefCoord = aSpanMinCoord; // NOTE: modifying argument } @@ -279,7 +274,7 @@ public: * the primary variables. */ void AccumulateSpanIntrinsics() { - AddCoords(mSpanMinCoord, mSpanPrefCoord, mHasSpecifiedCoord && mSpanHasSpecifiedCoord); + AddCoords(mSpanMinCoord, mSpanPrefCoord, mHasSpecifiedCoord); AddPrefPercent(mSpanPrefPercent); } @@ -322,7 +317,6 @@ protected: BCPixelSize mBottomContBorderWidth; PRPackedBool mHasSpecifiedCoord; - PRPackedBool mSpanHasSpecifiedCoord; // XXX... nscoord mMinCoord; nscoord mPrefCoord; nscoord mSpanMinCoord; // XXX...