Distribute extra space in fixed-layout tables where all columns have widths proportionally rather than equally, for compatibility. (Bug 445142) r=bernd sr=roc a=blocking1.9.1+

This commit is contained in:
L. David Baron
2008-11-25 15:22:39 -08:00
parent 40a061f21a
commit ca363c5843
9 changed files with 1208 additions and 12 deletions

View File

@@ -199,10 +199,14 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
const nscoord unassignedMarker = nscoord_MIN;
// We use the PrefPercent on the columns to store the percentages
// used to compute column widths in case we need to reduce their
// basis.
// used to compute column widths in case we need to shrink or expand
// the columns.
float pctTotal = 0.0f;
// Accumulate the total specified (non-percent) on the columns for
// distributing excess width to the columns.
nscoord specTotal = 0;
for (PRInt32 col = 0; col < colCount; ++col) {
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
if (!colFrame) {
@@ -217,6 +221,7 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
colWidth = nsLayoutUtils::ComputeWidthValue(
aReflowState.rendContext,
colFrame, 0, 0, 0, *styleWidth);
specTotal += colWidth;
} else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
float pct = styleWidth->GetPercentValue();
colWidth = NSToCoordFloor(pct * float(tableWidth));
@@ -272,6 +277,9 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
if (colWidth < 0)
colWidth = 0;
}
if (styleWidth->GetUnit() != eStyleUnit_Percent) {
specTotal += colWidth;
}
}
} else {
colWidth = unassignedMarker;
@@ -313,6 +321,8 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
}
if (unassignedCount > 0) {
// The spec says to distribute the remaining space evenly among
// the columns.
nscoord toAssign = unassignedSpace / unassignedCount;
for (PRInt32 col = 0; col < colCount; ++col) {
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
@@ -324,17 +334,74 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
colFrame->SetFinalWidth(toAssign);
}
} else if (unassignedSpace > 0) {
// The spec says to distribute extra space evenly. (That's not
// what WinIE6 does, though. It treats percentages and
// nonpercentages differently.)
nscoord toAdd = unassignedSpace / colCount;
for (PRInt32 col = 0; col < colCount; ++col) {
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
if (!colFrame) {
NS_ERROR("column frames out of sync with cell map");
continue;
// The spec doesn't say how to distribute the unassigned space.
if (specTotal > 0) {
// Distribute proportionally to non-percentage columns.
nscoord specUndist = specTotal;
for (PRInt32 col = 0; col < colCount; ++col) {
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
if (!colFrame) {
NS_ERROR("column frames out of sync with cell map");
continue;
}
if (colFrame->GetPrefPercent() == 0.0f) {
NS_ASSERTION(colFrame->GetFinalWidth() <= specUndist,
"widths don't add up");
nscoord toAdd = NSToCoordRound(float(unassignedSpace) *
(float(colFrame->GetFinalWidth()) / float(specUndist)));
specUndist -= colFrame->GetFinalWidth();
colFrame->SetFinalWidth(colFrame->GetFinalWidth() + toAdd);
unassignedSpace -= toAdd;
if (specUndist <= 0) {
NS_ASSERTION(specUndist == 0,
"math should be exact");
break;
}
}
}
NS_ASSERTION(unassignedSpace == 0, "failed to redistribute");
} else if (pctTotal > 0) {
// Distribute proportionally to percentage columns.
float pctUndist = pctTotal;
for (PRInt32 col = 0; col < colCount; ++col) {
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
if (!colFrame) {
NS_ERROR("column frames out of sync with cell map");
continue;
}
if (pctUndist < colFrame->GetPrefPercent()) {
// This can happen with floating-point math.
NS_ASSERTION(colFrame->GetPrefPercent() - pctUndist
< 0.0001,
"widths don't add up");
pctUndist = colFrame->GetPrefPercent();
}
nscoord toAdd = NSToCoordRound(float(unassignedSpace) *
(colFrame->GetPrefPercent() / pctUndist));
colFrame->SetFinalWidth(colFrame->GetFinalWidth() + toAdd);
unassignedSpace -= toAdd;
pctUndist -= colFrame->GetPrefPercent();
if (pctUndist <= 0.0f) {
break;
}
}
NS_ASSERTION(unassignedSpace == 0, "failed to redistribute");
} else {
// Distribute equally to the zero-width columns.
PRInt32 colsLeft = colCount;
for (PRInt32 col = 0; col < colCount; ++col) {
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
if (!colFrame) {
NS_ERROR("column frames out of sync with cell map");
continue;
}
NS_ASSERTION(colFrame->GetFinalWidth() == 0, "yikes");
nscoord toAdd = NSToCoordRound(float(unassignedSpace) /
float(colsLeft));
colFrame->SetFinalWidth(toAdd);
unassignedSpace -= toAdd;
--colsLeft;
}
colFrame->SetFinalWidth(colFrame->GetFinalWidth() + toAdd);
}
}
}