Fix slight errors when widths can't be round-tripped through floats. (Bug 467141) r+sr=roc
authorL. David Baron <dbaron@dbaron.org>
Thu, 04 Dec 2008 08:09:53 -0800
changeset 22337 fb1b3f68b09d2ee2bc6911f4b9231a1bfcaf4ecc
parent 22336 045908bd6528d9bd6cddff49d4d526acf85d49bd
child 22338 5da43688eee4b90ea0cd00b48249915d030e39a1
push idunknown
push userunknown
push dateunknown
bugs467141
milestone1.9.2a1pre
Fix slight errors when widths can't be round-tripped through floats. (Bug 467141) r+sr=roc
layout/tables/FixedTableLayoutStrategy.cpp
layout/tables/crashtests/467141-1.html
layout/tables/crashtests/crashtests.list
--- a/layout/tables/FixedTableLayoutStrategy.cpp
+++ b/layout/tables/FixedTableLayoutStrategy.cpp
@@ -163,16 +163,28 @@ FixedTableLayoutStrategy::GetPrefWidth(n
 
 /* virtual */ void
 FixedTableLayoutStrategy::MarkIntrinsicWidthsDirty()
 {
     mMinWidth = NS_INTRINSIC_WIDTH_UNKNOWN;
     mLastCalcWidth = nscoord_MIN;
 }
 
+static inline nscoord
+AllocateUnassigned(nscoord aUnassignedSpace, float aShare)
+{
+    if (aShare == 1.0f) {
+        // This happens when the numbers we're dividing to get aShare
+        // are equal.  We want to return unassignedSpace exactly, even
+        // if it can't be precisely round-tripped through float.
+        return aUnassignedSpace;
+    }
+    return NSToCoordRound(float(aUnassignedSpace) * aShare);
+}
+
 /* virtual */ void
 FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowState)
 {
     nscoord tableWidth = aReflowState.ComputedWidth();
 
     if (mLastCalcWidth == tableWidth)
         return;
     mLastCalcWidth = tableWidth;
@@ -352,18 +364,18 @@ FixedTableLayoutStrategy::ComputeColumnW
                 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)));
+                    nscoord toAdd = AllocateUnassigned(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;
                     }
@@ -381,18 +393,18 @@ FixedTableLayoutStrategy::ComputeColumnW
                 }
                 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));
+                nscoord toAdd = AllocateUnassigned(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");
@@ -401,22 +413,23 @@ FixedTableLayoutStrategy::ComputeColumnW
             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));
+                nscoord toAdd = AllocateUnassigned(unassignedSpace,
+                                                   1.0f / float(colsLeft));
                 colFrame->SetFinalWidth(toAdd);
                 unassignedSpace -= toAdd;
                 --colsLeft;
             }
+            NS_ASSERTION(unassignedSpace == 0, "failed to redistribute");
         }
     }
     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;
         }
new file mode 100644
--- /dev/null
+++ b/layout/tables/crashtests/467141-1.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<table width="16211982" cellspacing="0" style="table-layout: fixed;"><tbody><tr><td width="26"></td></tr></tbody></table>
+</body>
+</html>
--- a/layout/tables/crashtests/crashtests.list
+++ b/layout/tables/crashtests/crashtests.list
@@ -51,8 +51,9 @@ load 408753-1.xhtml
 load 411582.xhtml
 load 413180-1.html
 load 416845-1.xhtml
 load 416845-2.xhtml
 load 416845-3.html   
 load 423514-1.xhtml
 load 456041.html
 load 457115.html
+load 467141-1.html