Prefer distributing the width of a column-spanning cell to columns without specified widths, and make a specified width on a column-spanning cell not cause the column to be considered to have a specified width. b=379361 Patch by Daniel Holbert <dholbert@mozilla.com>. r+sr=dbaron
authordbaron@dbaron.org
Thu, 02 Aug 2007 17:07:29 -0700
changeset 4213 4cac8633e579ee785ee100b8c4b794ddc8941626
parent 4212 a105a8df0bbe79b3a115d6f546d7583853945553
child 4214 e52e5efd67ffc71e6d2715c7c5dfb0a3ccda996a
push idunknown
push userunknown
push dateunknown
bugs379361
milestone1.9a7pre
Prefer distributing the width of a column-spanning cell to columns without specified widths, and make a specified width on a column-spanning cell not cause the column to be considered to have a specified width. b=379361 Patch by Daniel Holbert <dholbert@mozilla.com>. r+sr=dbaron
layout/reftests/bugs/379361-1-ref.html
layout/reftests/bugs/379361-1.html
layout/reftests/bugs/379361-2-ref.html
layout/reftests/bugs/379361-2.html
layout/reftests/bugs/379361-3-ref.html
layout/reftests/bugs/379361-3.html
layout/reftests/bugs/reftest.list
layout/tables/BasicTableLayoutStrategy.cpp
layout/tables/nsTableColFrame.h
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/379361-1-ref.html
@@ -0,0 +1,16 @@
+<html>
+<body>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow">Cell A</td>
+    <td style="width: 300px; background: lightgreen">This text should be on one line</td>
+  </tr>
+
+  <tr>
+    <td style="width: 100px; background: lightblue" colspan="2">Cell B</td>
+  </tr>
+</table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/379361-1.html
@@ -0,0 +1,16 @@
+<html>
+<body>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow">Cell A</td>
+    <td style="background: lightgreen">This text should be on one line</td>
+  </tr>
+
+  <tr>
+    <td style="width: 100px; background: lightblue" colspan="2">Cell B</td>
+  </tr>
+</table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/379361-2-ref.html
@@ -0,0 +1,16 @@
+<html>
+<body>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 300px; background: lightgreen">This text should be on one line</td>
+    <td style="width: 200px; background: yellow">Cell A</td>
+  </tr>
+
+  <tr>
+    <td style="width: 100px; background: lightblue" colspan="2">Cell B</td>
+  </tr>
+</table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/379361-2.html
@@ -0,0 +1,16 @@
+<html>
+<body>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="background: lightgreen">This text should be on one line</td>
+    <td style="width: 200px; background: yellow">Cell A</td>
+  </tr>
+
+  <tr>
+    <td style="width: 100px; background: lightblue" colspan="2">Cell B</td>
+  </tr>
+</table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/379361-3-ref.html
@@ -0,0 +1,123 @@
+<html>
+<body>
+
+<li>Tables have width 500px.
+<li>Yellow cells have width 200px.
+<li>Green cells are auto-width.
+<li>Blue cells have colspan = 2 and, in test case, have various specified widths.
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="background: lightblue" colspan="2">10 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="background: lightblue" colspan="2">50 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="background: lightblue" colspan="2">100 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="background: lightblue" colspan="2">384 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="background: lightblue" colspan="2">385 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="background: lightblue" colspan="2">390 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="background: lightblue" colspan="2">500 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="background: lightblue" colspan="2">600 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="background: lightblue" colspan="2">900 px</td>
+  </tr>
+</table>
+<br/>
+
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="background: lightblue" colspan="2">1500 px</td>
+  </tr>
+</table>
+<br/>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/379361-3.html
@@ -0,0 +1,123 @@
+<html>
+<body>
+
+<li>Tables have width 500px.
+<li>Yellow cells have width 200px.
+<li>Green cells are auto-width.
+<li>Blue cells have colspan = 2 and, in test case, have various specified widths.
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="width: 10px; background: lightblue" colspan="2">10 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="width: 50px; background: lightblue" colspan="2">50 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="width: 100px; background: lightblue" colspan="2">100 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="width: 384px; background: lightblue" colspan="2">384 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="width: 385px; background: lightblue" colspan="2">385 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="width: 390px; background: lightblue" colspan="2">390 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="width: 500px; background: lightblue" colspan="2">500 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="width: 600px; background: lightblue" colspan="2">600 px</td>
+  </tr>
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="width: 900px; background: lightblue" colspan="2">900 px</td>
+  </tr>
+</table>
+<br/>
+
+</table>
+<br/>
+
+<table width="500px" cellspacing="0" cellpadding="0">
+  <tr>
+    <td style="width: 200px; background: yellow"></td>
+    <td style="background: lightgreen">Here are some words.</td>
+  </tr>
+  <tr>
+    <td style="width: 1500px; background: lightblue" colspan="2">1500 px</td>
+  </tr>
+</table>
+<br/>
+
+</body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -297,25 +297,28 @@ fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") ==
 == 374193-1.xhtml about:blank
 == 375716-1.html 375716-1-ref.html
 == 375827-1.html 375827-1-ref.html
 == 376484-1.html 376484-1-ref.html
 == 377603-1.html 377603-1-ref.html
 == 377918.html 377918-ref.html
 == 378535-1.html 378535-1-ref.html
 == 379316-1.html 379316-1-ref.html
+random-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 379316-2.html 379316-2-ref.html # bug 379786
+== 379328-1.html 379328-1-ref.html
 == 379349-1a.xhtml 379349-1-ref.xhtml
 == 379349-1b.xhtml 379349-1-ref.xhtml
 == 379349-1c.xhtml 379349-1-ref.xhtml
 == 379349-2a.xhtml 379349-2-ref.xhtml
 == 379349-2b.xhtml 379349-2-ref.xhtml
 == 379349-3a.xhtml 379349-3-ref.xhtml
 == 379349-3b.xhtml 379349-3-ref.xhtml
-random-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 379316-2.html 379316-2-ref.html # bug 379786
-== 379328-1.html 379328-1-ref.html
+== 379361-1.html 379361-1-ref.html
+== 379361-2.html 379361-2-ref.html
+== 379361-3.html 379361-3-ref.html
 == 380004-1.html 380004-1-ref.html
 == 380227-1.html 380227-1-ref.html
 == 380842-1.html 380842-1-ref.html
 == 381130-1.html 381130-1-ref.html
 == 381507-1.html 381507-1-ref.html
 == 382600-1.html 382600-1-ref.html
 == 383551-1.html 383551-1-ref.html
 == 384576-1.html 384576-1-ref.html
--- a/layout/tables/BasicTableLayoutStrategy.cpp
+++ b/layout/tables/BasicTableLayoutStrategy.cpp
@@ -356,51 +356,47 @@ BasicTableLayoutStrategy::ComputeColumnI
             // 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 -= spacing;
                 }
 
-                nscoord curPref;
-                if (info.hasSpecifiedWidth &&
-                    !scolFrame->GetHasSpecifiedCoord()) {
-                    curPref = scolFrame->GetMinCoord();
-                } else {
-                    curPref = scolFrame->GetPrefCoord();
+                totalSPref += scolFrame->GetPrefCoord();
+                totalSMin += scolFrame->GetMinCoord();
+                if (!scolFrame->GetHasSpecifiedCoord()) {
+                    totalSAutoPref += scolFrame->GetPrefCoord();
                 }
-
-                totalSPref += curPref;
-                totalSMin += scolFrame->GetMinCoord();
                 float scolPct = scolFrame->GetPrefPercent();
                 if (scolPct == 0.0f) {
-                    totalSNonPctPref += curPref;
+                    totalSNonPctPref += scolFrame->GetPrefCoord();
                     ++nonPctCount;
                 } else {
                     info.prefPercent -= scolPct;
                 }
                 info.minCoord -= scolFrame->GetMinCoord();
-                info.prefCoord -= curPref;
+                info.prefCoord -= scolFrame->GetPrefCoord();
             }
 
             if (info.minCoord < 0)
                 info.minCoord = 0;
             if (info.prefCoord < 0)
                 info.prefCoord = 0;
             if (info.prefPercent < 0.0f)
                 info.prefPercent = 0.0f;
@@ -425,97 +421,102 @@ BasicTableLayoutStrategy::ComputeColumnI
             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;
                 }
 
-                nscoord curPref;
-                if (info.hasSpecifiedWidth &&
-                    !scolFrame->GetHasSpecifiedCoord()) {
-                    curPref = scolFrame->GetMinCoord();
-                } else {
-                    curPref = scolFrame->GetPrefCoord();
-                }
-
                 // 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(curPref) /
+                                           (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(curPref - scolFrame->GetMinCoord()) /
+                    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 (curPref == 0) {
+                    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 {
-                        coordRatio = float(curPref) / float(totalSPref);
+                        // 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 =
                     NSToCoordRound(float(info.prefCoord) * coordRatio);
                 nscoord spanMin = scolFrame->GetMinCoord() +
                         allocatedMinWithinPref + allocatedMinOutsidePref;
-                nscoord spanPref = curPref + allocatedPref;
+                nscoord spanPref = 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 -= allocatedPref;
                 info.prefPercent -= allocatedPct;
-                totalSPref -= curPref;
+                totalSPref -= scolFrame->GetPrefCoord();
                 totalSMin -= scolFrame->GetMinCoord();
+                if (!scolFrame->GetHasSpecifiedCoord()) {
+                    totalSAutoPref -= scolFrame->GetPrefCoord();
+                }                
                 if (scolFrame->GetPrefPercent() == 0.0f) {
-                    totalSNonPctPref -= curPref;
+                    totalSNonPctPref -= scolFrame->GetPrefCoord();
                     --nonPctCount;
                 }
             }
 
             // Note that we only distribute the percentage if
             // spanHasNonPct.
             NS_ASSERTION(totalSPref == 0 && totalSMin == 0 &&
                          totalSNonPctPref == 0 && nonPctCount == 0 &&
--- a/layout/tables/nsTableColFrame.h
+++ b/layout/tables/nsTableColFrame.h
@@ -271,17 +271,17 @@ public:
       mSpanPrefPercent = aSpanPrefPercent;
   }
 
   /*
    * Accumulate the temporary variables for column spanning cells into
    * the primary variables.
    */
   void AccumulateSpanIntrinsics() {
-    AddCoords(mSpanMinCoord, mSpanPrefCoord, mSpanHasSpecifiedCoord);
+    AddCoords(mSpanMinCoord, mSpanPrefCoord, mHasSpecifiedCoord && mSpanHasSpecifiedCoord);
     AddPrefPercent(mSpanPrefPercent);
   }
 
   // Used to adjust a column's pref percent so that the table's total
   // never exceeeds 100% (by only allowing percentages to be used,
   // starting at the first column, until they reach 100%).
   void AdjustPrefPercent(float *aTableTotalPercent) {
     float allowed = 1.0f - *aTableTotalPercent;