LayoutTests:
authordarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 May 2006 04:42:09 +0000 (04:42 +0000)
committerdarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 May 2006 04:42:09 +0000 (04:42 +0000)
        Reviewed by Hyatt.

        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=6838
          Incomplete repaint of collapsed table borders

        * fast/repaint/table-collapsed-border-expected.checksum: Added.
        * fast/repaint/table-collapsed-border-expected.png: Added.
        * fast/repaint/table-collapsed-border-expected.txt: Added.
        * fast/repaint/table-collapsed-border.html: Added.

WebCore:

        Reviewed by Hyatt.

        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=6838
          Incomplete repaint of collapsed table borders

        This patch updates the implementation of collapsing borders to match
        the current spec.

        Test: fast/repaint/table-collapsed-border.html

        * rendering/RenderTable.cpp:
        (WebCore::RenderTable::RenderTable):
        (WebCore::RenderTable::layout): Calculate horizontal overflows.
        (WebCore::RenderTable::calcMinMaxWidth): Added call to recalcHorizontalBorders.
        (WebCore::RenderTable::colElement): Made const.
        (WebCore::RenderTable::calcBorderLeft): Calculates the left border. In the collapsing
        borders model, this is the left border of the leftmost cell of the first row.
        (WebCore::RenderTable::calcBorderRight): Ditto for the right border.
        (WebCore::RenderTable::recalcHorizontalBorders): Added.
        (WebCore::RenderTable::borderTop): Changed to return outerBorderTop in the
        collapsing case.
        (WebCore::RenderTable::borderBottom): Changed to return outerBorderBottom in
        the collapsing case.
        (WebCore::RenderTable::outerBorderTop): Added. Returns the table half of the
        top border, which is half the widest top border on the first row.
        (WebCore::RenderTable::outerBorderBottom): Added. Returns the table half of the
        bottom border, which is half the widest bottom border on the last row.
        (WebCore::RenderTable::outerBorderLeft): Added. Returns the table half of the
        left border, which is half the widest left border on the leftmost column.
        (WebCore::RenderTable::outerBorderRight): Added. Returns the table half of the
        right border, which is half the widest right border on the rightmost column.
        (WebCore::RenderTable::cellAbove): Return 0 if the cell is in the first row
        of the header.
        (WebCore::RenderTable::cellBelow): Return 0 if the cell is in the last row
        of the footer.
        * rendering/RenderTable.h:
        (WebCore::RenderTable::borderLeft):
        (WebCore::RenderTable::borderRight):
        (WebCore::RenderTable::overflowHeight):
        * rendering/RenderTableCell.cpp:
        (WebCore::RenderTableCell::borderLeft): Removed unnecessary use of floats.
        (WebCore::RenderTableCell::borderTop): Ditto.
        (WebCore::RenderTableCell::paint): Account for the table half of the vertical
        borders.
        (WebCore::RenderTableCell::paintCollapsedBorder): Removed unnecessary use of
        floats.
        * rendering/RenderTableSection.cpp:
        (WebCore::RenderTableSection::RenderTableSection):
        (WebCore::RenderTableSection::layoutRows): Added call to recalcOuterBorder.
        (WebCore::RenderTableSection::calcOuterBorderTop): Added. Calculates the outer half of
        the section's top border, which is half the widest top border on the first row.
        (WebCore::RenderTableSection::calcOuterBorderBottom): Ditto for the bottom border.
        (WebCore::RenderTableSection::calcOuterBorderLeft): Ditto for the left border.
        (WebCore::RenderTableSection::calcOuterBorderRight): Ditto for the right border.
        (WebCore::RenderTableSection::recalcOuterBorder): Added.
        (WebCore::RenderTableSection::paint): Account for the table half of the borders.
        * rendering/RenderTableSection.h:
        (WebCore::RenderTableSection::outerBorderTop):
        (WebCore::RenderTableSection::outerBorderBottom):
        (WebCore::RenderTableSection::outerBorderLeft):
        (WebCore::RenderTableSection::outerBorderRight):
        * rendering/render_style.cpp:
        (WebCore::RenderStyle::diff): Changed to return Layout if a border style changed
        from 'hidden' to 'none' or vice versa in the collapsing borders model, since
        'hidden' suppresses other borders.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@14372 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/repaint/table-collapsed-border-expected.checksum [new file with mode: 0644]
LayoutTests/fast/repaint/table-collapsed-border-expected.png [new file with mode: 0644]
LayoutTests/fast/repaint/table-collapsed-border-expected.txt [new file with mode: 0644]
LayoutTests/fast/repaint/table-collapsed-border.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/rendering/RenderTable.cpp
WebCore/rendering/RenderTable.h
WebCore/rendering/RenderTableCell.cpp
WebCore/rendering/RenderTableSection.cpp
WebCore/rendering/RenderTableSection.h
WebCore/rendering/render_style.cpp

index 714b4568fdfd6c43b74ae15afcbd03226e3ade5b..ad046df140afff60641dd3c487f9f5297a304194 100644 (file)
@@ -1,3 +1,15 @@
+2006-05-14  Mitz Pettel  <opendarwin.org@mitzpettel.com>
+
+        Reviewed by Hyatt.
+
+        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=6838
+          Incomplete repaint of collapsed table borders
+          
+        * fast/repaint/table-collapsed-border-expected.checksum: Added.
+        * fast/repaint/table-collapsed-border-expected.png: Added.
+        * fast/repaint/table-collapsed-border-expected.txt: Added.
+        * fast/repaint/table-collapsed-border.html: Added.
+
 2006-05-14  Rob Buis  <buis@kde.org>
 
         Reviewed by Darin.
diff --git a/LayoutTests/fast/repaint/table-collapsed-border-expected.checksum b/LayoutTests/fast/repaint/table-collapsed-border-expected.checksum
new file mode 100644 (file)
index 0000000..5467d8c
--- /dev/null
@@ -0,0 +1,2 @@
+f902001e2a9f0d640e6c813809ff5f23
+\ No newline at end of file
diff --git a/LayoutTests/fast/repaint/table-collapsed-border-expected.png b/LayoutTests/fast/repaint/table-collapsed-border-expected.png
new file mode 100644 (file)
index 0000000..eb7ffa9
Binary files /dev/null and b/LayoutTests/fast/repaint/table-collapsed-border-expected.png differ
diff --git a/LayoutTests/fast/repaint/table-collapsed-border-expected.txt b/LayoutTests/fast/repaint/table-collapsed-border-expected.txt
new file mode 100644 (file)
index 0000000..b671e7b
--- /dev/null
@@ -0,0 +1,73 @@
+layer at (0,0) size 800x600
+  RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,10) size 784x580
+      RenderTable {TABLE} at (0,0) size 95x76 [border: (4px solid #008000)]
+        RenderTableSection {TBODY} at (4,4) size 87x68
+          RenderTableRow {TR} at (0,0) size 87x24
+            RenderTableCell {TD} at (0,9) size 6x6 [border: (4px none #000000)] [r=0 c=0 rs=1 cs=1]
+            RenderTableCell {TD} at (6,0) size 81x24 [border: (4px none #000000)] [r=0 c=1 rs=1 cs=1]
+              RenderText {#text} at (1,5) size 42x18
+                text run at (1,5) width 42: "Lorem"
+          RenderTableRow {TR} at (0,24) size 87x20
+            RenderTableCell {TD} at (0,33) size 6x2 [border: none] [r=1 c=0 rs=1 cs=1]
+            RenderTableCell {TD} at (6,24) size 81x20 [border: none] [r=1 c=1 rs=1 cs=1]
+              RenderText {#text} at (1,1) size 75x18
+                text run at (1,1) width 75: "ipsum dolor"
+          RenderTableRow {TR} at (0,44) size 87x24
+            RenderTableCell {TD} at (0,53) size 6x6 [border: none] [r=2 c=0 rs=1 cs=1]
+            RenderTableCell {TD} at (6,44) size 81x24 [border: none] [r=2 c=1 rs=1 cs=1]
+              RenderText {#text} at (1,1) size 48x18
+                text run at (1,1) width 48: "sit amet"
+      RenderTable {TABLE} at (0,86) size 72x76 [border: (4px solid #000000)]
+        RenderTableSection {TBODY} at (4,4) size 64x68
+          RenderTableRow {TR} at (0,0) size 64x24
+            RenderTableCell {TD} at (0,9) size 10x6 [border: (4px none #000000)] [r=0 c=0 rs=1 cs=1]
+            RenderTableCell {TD} at (10,0) size 54x24 [border: (4px none #000000)] [r=0 c=1 rs=1 cs=1]
+              RenderText {#text} at (1,5) size 42x18
+                text run at (1,5) width 42: "Lorem"
+          RenderTableRow {TR} at (0,24) size 64x20
+            RenderTableCell {TD} at (0,24) size 10x20 [border: none] [r=1 c=0 rs=1 cs=1]
+              RenderText {#text} at (5,1) size 4x18
+                text run at (5,1) width 4: " "
+          RenderTableRow {TR} at (0,44) size 64x24
+            RenderTableCell {TD} at (0,53) size 10x6 [border: none] [r=2 c=0 rs=1 cs=1]
+            RenderTableCell {TD} at (10,44) size 54x24 [border: none] [r=2 c=1 rs=1 cs=1]
+              RenderText {#text} at (1,1) size 48x18
+                text run at (1,1) width 48: "sit amet"
+      RenderTable {TABLE} at (0,172) size 108x76 [border: (4px solid #000000)]
+        RenderTableSection {TBODY} at (4,4) size 100x68
+          RenderTableRow {TR} at (0,0) size 100x24
+            RenderTableCell {TD} at (0,9) size 10x6 [border: (4px none #000000)] [r=0 c=0 rs=1 cs=1]
+            RenderTableCell {TD} at (10,0) size 90x24 [border: (4px none #000000)] [r=0 c=1 rs=1 cs=1]
+              RenderText {#text} at (1,5) size 84x18
+                text run at (1,5) width 84: "Lorem ipsum"
+          RenderTableRow {TR} at (0,24) size 100x20
+            RenderTableCell {TD} at (0,24) size 10x20 [border: none] [r=1 c=0 rs=1 cs=1]
+              RenderText {#text} at (5,1) size 4x18
+                text run at (5,1) width 4: " "
+          RenderTableRow {TR} at (0,44) size 100x24
+            RenderTableCell {TD} at (0,53) size 10x6 [border: none] [r=2 c=0 rs=1 cs=1]
+            RenderTableCell {TD} at (10,44) size 90x24 [border: none] [r=2 c=1 rs=1 cs=1]
+              RenderText {#text} at (1,1) size 48x18
+                text run at (1,1) width 48: "sit amet"
+      RenderTable {TABLE} at (0,258) size 99x76 [border: (4px solid #000000)]
+        RenderTableSection {TBODY} at (4,4) size 91x68
+          RenderTableRow {TR} at (0,0) size 91x24
+            RenderTableCell {TD} at (0,9) size 10x6 [border: (4px none #000000)] [r=0 c=0 rs=1 cs=1]
+            RenderTableCell {TD} at (10,0) size 81x24 [border: (4px none #000000)] [r=0 c=1 rs=1 cs=1]
+              RenderText {#text} at (1,5) size 42x18
+                text run at (1,5) width 42: "Lorem"
+          RenderTableRow {TR} at (0,24) size 91x20
+            RenderTableCell {TD} at (0,24) size 10x20 [border: none] [r=1 c=0 rs=1 cs=1]
+              RenderText {#text} at (5,1) size 4x18
+                text run at (5,1) width 4: " "
+            RenderTableCell {TD} at (10,24) size 81x20 [border: none] [r=1 c=1 rs=1 cs=1]
+              RenderText {#text} at (1,1) size 75x18
+                text run at (1,1) width 75: "ipsum dolor"
+          RenderTableRow {TR} at (0,44) size 91x24
+            RenderTableCell {TD} at (0,53) size 10x6 [border: none] [r=2 c=0 rs=1 cs=1]
+            RenderTableCell {TD} at (10,44) size 81x24 [border: none] [r=2 c=1 rs=1 cs=1]
+              RenderText {#text} at (1,1) size 48x18
+                text run at (1,1) width 48: "sit amet"
diff --git a/LayoutTests/fast/repaint/table-collapsed-border.html b/LayoutTests/fast/repaint/table-collapsed-border.html
new file mode 100644 (file)
index 0000000..ac3b2f4
--- /dev/null
@@ -0,0 +1,101 @@
+<head>
+    <style type="text/css">
+        table {
+            border-collapse: collapse;
+            border: 8px solid;
+            margin: 10px 0 10px 0;
+        }
+    </style>
+       <script src="repaint.js" type="text/javascript"></script>
+       <script type="text/javascript">
+          function repaintTest()
+          {
+           document.getElementById('t').style.borderColor = 'green';
+           document.getElementById('r').removeChild(document.getElementById('d'));
+           document.getElementById('r2').removeChild(document.getElementById('d2'));
+           document.getElementById('d3').innerHTML = 'ipsum dolor';
+          }
+       </script>
+</head>
+<body onload="runRepaintTest();">
+    <table id="t">
+        <tr>
+            <td>
+            </td>
+            <td>Lorem
+            </td>
+        </tr>
+        <tr>
+            <td>
+            </td>
+            <td>ipsum dolor
+            </td>
+        </tr>
+        <tr>
+            <td>
+            </td>
+            <td>sit amet
+            </td>
+        </tr>
+    </table>
+    <table>
+        <tr>
+            <td>
+            </td>
+            <td>Lorem
+            </td>
+        </tr>
+        <tr id="r">
+            <td>&nbsp;
+            </td>
+            <td id="d">ipsum dolor
+            </td>
+        </tr>
+        <tr>
+            <td>
+            </td>
+            <td>sit amet
+            </td>
+        </tr>
+    </table>
+    <table>
+        <tr>
+            <td>
+            </td>
+            <td>Lorem ipsum
+            </td>
+        </tr>
+        <tr id="r2">
+            <td>&nbsp;
+            </td>
+            <td id="d2">dolor
+            </td>
+        </tr>
+        <tr>
+            <td>
+            </td>
+            <td>sit amet
+            </td>
+        </tr>
+    </table>
+    <table>
+        <tr>
+            <td>
+            </td>
+            <td>Lorem
+            </td>
+        </tr>
+        <tr>
+            <td>&nbsp;
+            </td>
+            <td id="d3">
+            </td>
+        </tr>
+        <tr>
+            <td>
+            </td>
+            <td>sit amet
+            </td>
+        </tr>
+    </table>
+</body>
index 0ddc88b24fe8f7cee9082d9fbc6e3883fa7fe32d..5ee8f6878cc2369a614abcb85d2c7c14fef71833 100644 (file)
@@ -1,3 +1,71 @@
+2006-05-14  Mitz Pettel  <opendarwin.org@mitzpettel.com>
+
+        Reviewed by Hyatt.
+
+        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=6838
+          Incomplete repaint of collapsed table borders
+          
+        This patch updates the implementation of collapsing borders to match
+        the current spec.
+
+        Test: fast/repaint/table-collapsed-border.html
+
+        * rendering/RenderTable.cpp:
+        (WebCore::RenderTable::RenderTable):
+        (WebCore::RenderTable::layout): Calculate horizontal overflows.
+        (WebCore::RenderTable::calcMinMaxWidth): Added call to recalcHorizontalBorders.
+        (WebCore::RenderTable::colElement): Made const.
+        (WebCore::RenderTable::calcBorderLeft): Calculates the left border. In the collapsing
+        borders model, this is the left border of the leftmost cell of the first row.
+        (WebCore::RenderTable::calcBorderRight): Ditto for the right border.
+        (WebCore::RenderTable::recalcHorizontalBorders): Added.
+        (WebCore::RenderTable::borderTop): Changed to return outerBorderTop in the
+        collapsing case.
+        (WebCore::RenderTable::borderBottom): Changed to return outerBorderBottom in
+        the collapsing case.
+        (WebCore::RenderTable::outerBorderTop): Added. Returns the table half of the
+        top border, which is half the widest top border on the first row.
+        (WebCore::RenderTable::outerBorderBottom): Added. Returns the table half of the
+        bottom border, which is half the widest bottom border on the last row.
+        (WebCore::RenderTable::outerBorderLeft): Added. Returns the table half of the
+        left border, which is half the widest left border on the leftmost column.
+        (WebCore::RenderTable::outerBorderRight): Added. Returns the table half of the
+        right border, which is half the widest right border on the rightmost column.
+        (WebCore::RenderTable::cellAbove): Return 0 if the cell is in the first row
+        of the header.
+        (WebCore::RenderTable::cellBelow): Return 0 if the cell is in the last row
+        of the footer.
+        * rendering/RenderTable.h:
+        (WebCore::RenderTable::borderLeft):
+        (WebCore::RenderTable::borderRight):
+        (WebCore::RenderTable::overflowHeight):
+        * rendering/RenderTableCell.cpp:
+        (WebCore::RenderTableCell::borderLeft): Removed unnecessary use of floats.
+        (WebCore::RenderTableCell::borderTop): Ditto.
+        (WebCore::RenderTableCell::paint): Account for the table half of the vertical
+        borders.
+        (WebCore::RenderTableCell::paintCollapsedBorder): Removed unnecessary use of
+        floats.
+        * rendering/RenderTableSection.cpp:
+        (WebCore::RenderTableSection::RenderTableSection):
+        (WebCore::RenderTableSection::layoutRows): Added call to recalcOuterBorder.
+        (WebCore::RenderTableSection::calcOuterBorderTop): Added. Calculates the outer half of
+        the section's top border, which is half the widest top border on the first row.
+        (WebCore::RenderTableSection::calcOuterBorderBottom): Ditto for the bottom border.
+        (WebCore::RenderTableSection::calcOuterBorderLeft): Ditto for the left border.
+        (WebCore::RenderTableSection::calcOuterBorderRight): Ditto for the right border.
+        (WebCore::RenderTableSection::recalcOuterBorder): Added.
+        (WebCore::RenderTableSection::paint): Account for the table half of the borders.
+        * rendering/RenderTableSection.h:
+        (WebCore::RenderTableSection::outerBorderTop):
+        (WebCore::RenderTableSection::outerBorderBottom):
+        (WebCore::RenderTableSection::outerBorderLeft):
+        (WebCore::RenderTableSection::outerBorderRight):
+        * rendering/render_style.cpp:
+        (WebCore::RenderStyle::diff): Changed to return Layout if a border style changed
+        from 'hidden' to 'none' or vice versa in the collapsing borders model, since
+        'hidden' suppresses other borders.
+
 2006-05-14  Mitz Pettel  <opendarwin.org@mitzpettel.com>
 
         Reviewed by Darin.
index fa42ca765fc26041440b7cda7f1b8e32aec156cd..0baedbf8ad0c55ff666cc0fe2f0b53756c59f75e 100644 (file)
@@ -59,6 +59,8 @@ RenderTable::RenderTable(Node* node)
     padding = 0;
     needSectionRecalc = false;
     padding = 0;
+    m_borderLeft = 0;
+    m_borderRight = 0;
 
     columnPos.resize(2);
     columnPos.fill(0);
@@ -252,7 +254,6 @@ void RenderTable::layout()
     
     //int oldWidth = m_width;
     calcWidth();
-    m_overflowWidth = m_width;
 
     // the optimisation below doesn't work since the internal table
     // layout could have changed.  we need to add a flag to the table
@@ -278,6 +279,9 @@ void RenderTable::layout()
         child = child->nextSibling();
     }
 
+    m_overflowWidth = m_width + (collapseBorders() ? outerBorderRight() - borderRight() : 0);
+    m_overflowLeft = collapseBorders() ? borderLeft() - outerBorderLeft() : 0;
+
     // ### collapse caption margin
     if (tCaption && tCaption->style()->captionSide() != CAPBOTTOM) {
         tCaption->setPos(tCaption->marginLeft(), m_height);
@@ -356,9 +360,6 @@ void RenderTable::layout()
     if (checkForRepaint)
         repaintAfterLayoutIfNeeded(oldBounds, oldFullBounds);
     
-    m_overflowHeight = max(m_overflowHeight, m_height);
-    m_overflowWidth = max(m_overflowWidth, m_width);
-
     setNeedsLayout(false);
 }
 
@@ -454,6 +455,7 @@ void RenderTable::calcMinMaxWidth()
 
     if (needSectionRecalc)
         recalcSections();
+    recalcHorizontalBorders();
 
     tableLayout->calcMinMaxWidth();
 
@@ -519,7 +521,7 @@ void RenderTable::appendColumn(int span)
     setNeedsLayoutAndMinMaxRecalc();
 }
 
-RenderTableCol *RenderTable::colElement(int col)
+RenderTableCol *RenderTable::colElement(int col) const
 {
     if (!has_col_elems)
         return 0;
@@ -634,44 +636,259 @@ RenderObject* RenderTable::removeChildNode(RenderObject* child)
     return RenderContainer::removeChildNode(child);
 }
 
-int RenderTable::borderLeft() const
+int RenderTable::calcBorderLeft() const
 {
     if (collapseBorders()) {
-        // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
-        // but I'm working to get this changed.  For now, follow the spec.
-        return 0;
+        // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2.
+        if (numEffCols() == 0)
+            return 0;
+
+        unsigned borderWidth = 0;
+
+        const BorderValue& tb = style()->borderLeft();
+        if (tb.style() == BHIDDEN)
+            return 0;
+        if (tb.style() > BHIDDEN)
+            borderWidth = tb.width;
+
+        int leftmostColumn = style()->direction() == RTL ? numEffCols() - 1 : 0;
+        RenderTableCol *colGroup = colElement(leftmostColumn);
+        if (colGroup) {
+            const BorderValue& gb = style()->borderLeft();
+            if (gb.style() == BHIDDEN)
+                return 0;
+            if (gb.style() > BHIDDEN && gb.width > borderWidth)
+                borderWidth = gb.width;
+        }
+        
+        RenderObject *child = firstChild();
+        while (child && !child->isTableSection())
+            child = child->nextSibling();
+        if (child && child->isTableSection()) {
+            RenderTableSection* section = static_cast<RenderTableSection*>(child);
+            
+            if (section->numRows() == 0)
+                return borderWidth / 2;
+            
+            const BorderValue& sb = section->style()->borderLeft();
+            if (sb.style() == BHIDDEN)
+                return 0;
+            if (sb.style() > BHIDDEN && sb.width > borderWidth)
+                borderWidth = sb.width;
+
+            const RenderTableSection::CellStruct& cs = section->cellAt(0, leftmostColumn);
+            
+            if (cs.cell) {
+                const BorderValue& cb = cs.cell->style()->borderLeft();
+                if (cb.style() == BHIDDEN)
+                    return 0;
+                const BorderValue& rb = cs.cell->parent()->style()->borderLeft();
+                if (rb.style() == BHIDDEN)
+                    return 0;
+
+                if (cb.style() > BHIDDEN && cb.width > borderWidth)
+                    borderWidth = cb.width;
+                if (rb.style() > BHIDDEN && rb.width > borderWidth)
+                    borderWidth = rb.width;
+            }
+        }
+        return borderWidth / 2;
     }
     return RenderBlock::borderLeft();
 }
     
-int RenderTable::borderRight() const
+int RenderTable::calcBorderRight() const
 {
     if (collapseBorders()) {
-        // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
-        // but I'm working to get this changed.  For now, follow the spec.
-        return 0;
+        // Determined by the last cell of the first row. See the CSS 2.1 spec, section 17.6.2.
+        if (numEffCols() == 0)
+            return 0;
+
+        unsigned borderWidth = 0;
+
+        const BorderValue& tb = style()->borderRight();
+        if (tb.style() == BHIDDEN)
+            return 0;
+        if (tb.style() > BHIDDEN)
+            borderWidth = tb.width;
+
+        int rightmostColumn = style()->direction() == RTL ? 0 : numEffCols() - 1;
+        RenderTableCol *colGroup = colElement(rightmostColumn);
+        if (colGroup) {
+            const BorderValue& gb = style()->borderRight();
+            if (gb.style() == BHIDDEN)
+                return 0;
+            if (gb.style() > BHIDDEN && gb.width > borderWidth)
+                borderWidth = gb.width;
+        }
+        
+        RenderObject *child = firstChild();
+        while (child && !child->isTableSection())
+            child = child->nextSibling();
+        if (child && child->isTableSection()) {
+            RenderTableSection* section = static_cast<RenderTableSection*>(child);
+            
+            if (section->numRows() == 0)
+                return (borderWidth + 1) / 2;
+            
+            const BorderValue& sb = section->style()->borderRight();
+            if (sb.style() == BHIDDEN)
+                return 0;
+            if (sb.style() > BHIDDEN && sb.width > borderWidth)
+                borderWidth = sb.width;
+
+            const RenderTableSection::CellStruct& cs = section->cellAt(0, rightmostColumn);
+            
+            if (cs.cell) {
+                const BorderValue& cb = cs.cell->style()->borderRight();
+                if (cb.style() == BHIDDEN)
+                    return 0;
+                const BorderValue& rb = cs.cell->parent()->style()->borderRight();
+                if (rb.style() == BHIDDEN)
+                    return 0;
+
+                if (cb.style() > BHIDDEN && cb.width > borderWidth)
+                    borderWidth = cb.width;
+                if (rb.style() > BHIDDEN && rb.width > borderWidth)
+                    borderWidth = rb.width;
+            }
+        }
+        return (borderWidth + 1) / 2;
     }
     return RenderBlock::borderRight();
 }
 
+void RenderTable::recalcHorizontalBorders()
+{
+    m_borderLeft = calcBorderLeft();
+    m_borderRight = calcBorderRight();
+}
+
 int RenderTable::borderTop() const
 {
-    if (collapseBorders()) {
-        // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
-        // but I'm working to get this changed.  For now, follow the spec.
-        return 0;
-    }
+    if (collapseBorders())
+        return outerBorderTop();
     return RenderBlock::borderTop();
 }
 
 int RenderTable::borderBottom() const
 {
-    if (collapseBorders()) {
-        // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
-        // but I'm working to get this changed.  For now, follow the spec.
+    if (collapseBorders())
+        return outerBorderBottom();
+    return RenderBlock::borderBottom();
+}
+
+int RenderTable::outerBorderTop() const
+{
+    if (!collapseBorders())
         return 0;
+    int borderWidth = 0;
+    RenderTableSection* topSection;
+    if (head)
+        topSection = head;
+    else if (firstBody)
+        topSection = firstBody;
+    else if (foot)
+        topSection = foot;
+    else
+        topSection = 0;
+    if (topSection) {
+        borderWidth = topSection->outerBorderTop();
+        if (borderWidth == -1)
+            return 0;   // Overridden by hidden
     }
-    return RenderBlock::borderBottom();
+    const BorderValue& tb = style()->borderTop();
+    if (tb.style() == BHIDDEN)
+        return 0;
+    if (tb.style() > BHIDDEN && (int)(tb.width / 2) > borderWidth)
+        borderWidth = tb.width / 2;
+    return borderWidth;
+}
+
+int RenderTable::outerBorderBottom() const
+{
+    if (!collapseBorders())
+        return 0;
+    int borderWidth = 0;
+    RenderTableSection* bottomSection;
+    if (foot)
+        bottomSection = foot;
+    else {
+        RenderObject* child;
+        for (child = lastChild(); child && !child->isTableSection(); child = child->previousSibling());
+        bottomSection = child ? static_cast<RenderTableSection *>(child) : 0;
+    }
+    if (bottomSection) {
+        borderWidth = bottomSection->outerBorderBottom();
+        if (borderWidth == -1)
+            return 0;   // Overridden by hidden
+    }
+    const BorderValue& tb = style()->borderBottom();
+    if (tb.style() == BHIDDEN)
+        return 0;
+    if (tb.style() > BHIDDEN && (int)(tb.width + 1) / 2 > borderWidth)
+        borderWidth = (tb.width + 1) / 2;
+    return borderWidth;
+}
+
+int RenderTable::outerBorderLeft() const
+{
+    if (!collapseBorders())
+        return 0;
+
+    int borderWidth = 0;
+
+    const BorderValue& tb = style()->borderLeft();
+    if (tb.style() == BHIDDEN)
+        return 0;
+    if (tb.style() > BHIDDEN)
+        borderWidth = tb.width / 2;
+
+    bool allHidden = true;
+    for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
+        if (!child->isTableSection())
+            continue;
+        int sw = static_cast<RenderTableSection *>(child)->outerBorderLeft();
+        if (sw == -1)
+            continue;
+        else
+            allHidden = false;
+        borderWidth = max(borderWidth, sw);
+    }
+    if (allHidden)
+        return 0;
+
+    return borderWidth;
+}
+
+int RenderTable::outerBorderRight() const
+{
+    if (!collapseBorders())
+        return 0;
+
+    int borderWidth = 0;
+
+    const BorderValue& tb = style()->borderRight();
+    if (tb.style() == BHIDDEN)
+        return 0;
+    if (tb.style() > BHIDDEN)
+        borderWidth = (tb.width + 1) / 2;
+
+    bool allHidden = true;
+    for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
+        if (!child->isTableSection())
+            continue;
+        int sw = static_cast<RenderTableSection *>(child)->outerBorderRight();
+        if (sw == -1)
+            continue;
+        else
+            allHidden = false;
+        borderWidth = max(borderWidth, sw);
+    }
+    if (allHidden)
+        return 0;
+
+    return borderWidth;
 }
 
 RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
@@ -685,6 +902,8 @@ RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
         section = cell->section();
         rAbove = r-1;
     } else {
+        if (cell->section() == head)
+            return 0;
         // cell is at top of a section, use last row in previous section
         for (RenderObject *prevSection = cell->section()->previousSibling();
              prevSection && rAbove < 0;
@@ -722,6 +941,8 @@ RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
         section = cell->section();
         rBelow= r+1;
     } else {
+        if (cell->section() == foot)
+            return 0;
         // The cell is at the bottom of a section. Use the first row in the next section.
         for (RenderObject* nextSection = cell->section()->nextSibling();
              nextSection && rBelow < 0;
index c316d3cae1277fca367a6f9ee532a5ceedd0d767..bb49d5efe2f6b4d8fde17f5d0cc201bc11b73af7 100644 (file)
@@ -74,8 +74,8 @@ public:
     int vBorderSpacing() const { return vspacing; }
     
     bool collapseBorders() const { return style()->borderCollapse(); }
-    int borderLeft() const;
-    int borderRight() const;
+    int borderLeft() const { return m_borderLeft; }
+    int borderRight() const { return m_borderRight; }
     int borderTop() const;
     int borderBottom() const;
     
@@ -86,9 +86,17 @@ public:
     unsigned cellPadding() const { return padding; }
     void setCellPadding(unsigned p) { padding = p; }
 
+    int outerBorderTop() const;
+    int outerBorderBottom() const;
+    int outerBorderLeft() const;
+    int outerBorderRight() const;
+    
+    int calcBorderLeft() const;
+    int calcBorderRight() const;
+    void recalcHorizontalBorders();
+
     // overrides
     virtual int overflowHeight(bool includeInterior = true) const { return height(); }
-    virtual int overflowWidth(bool includeInterior = true) const { return width(); }
     virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
     virtual void paint(PaintInfo&, int tx, int ty);
     virtual void paintBoxDecorations(PaintInfo&, int _tx, int _ty);
@@ -145,7 +153,7 @@ public:
                (collapseBorders() ? 0 : (paddingLeft() + paddingRight() + (numEffCols() + 1) * hBorderSpacing()));
     }
 
-    RenderTableCol* colElement(int col);
+    RenderTableCol* colElement(int col) const;
 
     void setNeedSectionRecalc() { needSectionRecalc = true; }
 
@@ -188,6 +196,8 @@ private:
     
     short hspacing;
     short vspacing;
+    int m_borderRight;
+    int m_borderLeft;
 };
 
 }
index e079bb10b7caf3272188e605cebf3494a86fa3d2..32b0cb65c67df87adb1f2f527f21823492cc7f8a 100644 (file)
@@ -485,7 +485,7 @@ int RenderTableCell::borderLeft() const
     if (table()->collapseBorders()) {
         CollapsedBorderValue border = collapsedLeftBorder(table()->style()->direction() == RTL);
         if (border.exists())
-            return int(border.width() / 2.0 + 0.5); // Give the extra pixel to top and left.
+            return (border.width() + 1) / 2; // Give the extra pixel to top and left.
         return 0;
     }
     return RenderBlock::borderLeft();
@@ -507,7 +507,7 @@ int RenderTableCell::borderTop() const
     if (table()->collapseBorders()) {
         CollapsedBorderValue border = collapsedTopBorder();
         if (border.exists())
-            return int(border.width() / 2.0 + 0.5); // Give the extra pixel to top and left.
+            return (border.width() + 1) / 2; // Give the extra pixel to top and left.
         return 0;
     }
     return RenderBlock::borderTop();
@@ -540,15 +540,18 @@ void RenderTableCell::paint(PaintInfo& i, int _tx, int _ty)
 
     // check if we need to do anything at all...
     int os = 2*maximalOutlineSize(i.phase);
-    if (_ty >= i.r.bottom() + os || _ty + _topExtra + m_height + _bottomExtra <= i.r.y() - os)
-        return;
 
     if (i.phase == PaintPhaseCollapsedTableBorders && style()->visibility() == VISIBLE) {
+        if (_ty - table()->outerBorderTop() >= i.r.bottom() + os || _ty + _topExtra + m_height + _bottomExtra + table()->outerBorderBottom() <= i.r.y() - os)
+            return;
         int w = width();
         int h = height() + borderTopExtra() + borderBottomExtra();
         paintCollapsedBorder(i.p, _tx, _ty, w, h);
-    } else
+    } else {
+        if (_ty >= i.r.bottom() + os || _ty + _topExtra + m_height + _bottomExtra <= i.r.y() - os)
+            return;
         RenderBlock::paintObject(i, _tx, _ty + _topExtra);
+    }
 
 #ifdef BOX_DEBUG
     ::outlineBox( i.p, _tx, _ty, width(), height() + borderTopExtra() + borderBottomExtra());
@@ -660,8 +663,8 @@ void RenderTableCell::paintCollapsedBorder(GraphicsContext* p, int _tx, int _ty,
     
     _tx -= leftWidth / 2;
     _ty -= topWidth / 2;
-    w += leftWidth / 2 + int(rightWidth / 2.0 + 0.5);
-    h += topWidth / 2 + int(bottomWidth / 2.0 + 0.5);
+    w += leftWidth / 2 + (rightWidth + 1) / 2;
+    h += topWidth / 2 + (bottomWidth + 1) / 2;
     
     bool tt = topVal.isTransparent();
     bool bt = bottomVal.isTransparent();
index ab4d70af768fb5c08b66dd49c3f9198f0c4405e1..f94f9e129f8db964896d10b735f98b9ba65df242 100644 (file)
@@ -28,6 +28,7 @@
 #include "config.h"
 #include "RenderTableSection.h"
 #include "RenderTableCell.h"
+#include "RenderTableCol.h"
 #include "RenderTableRow.h"
 #include "RenderTableCol.h"
 #include "Document.h"
@@ -49,6 +50,10 @@ RenderTableSection::RenderTableSection(Node* node)
     cCol = 0;
     cRow = -1;
     needCellRecalc = false;
+    m_outerBorderLeft = 0;
+    m_outerBorderRight = 0;
+    m_outerBorderTop = 0;
+    m_outerBorderBottom = 0;
 }
 
 RenderTableSection::~RenderTableSection()
@@ -370,6 +375,8 @@ int RenderTableSection::layoutRows(int toAdd)
     
     // Set the width of our section now.  The rows will also be this width.
     m_width = table()->contentWidth();
+    if (table()->collapseBorders())
+        recalcOuterBorder();
     
     if (toAdd && totalRows && (rowPos[totalRows] || !nextSibling())) {
 
@@ -607,6 +614,216 @@ int RenderTableSection::leftmostPosition(bool includeOverflowInterior, bool incl
     return left;
 }
 
+int RenderTableSection::calcOuterBorderTop() const
+{
+    int totalCols = table()->numEffCols();
+    if (gridRows == 0 || totalCols == 0)
+        return 0;
+
+    unsigned borderWidth = 0;
+
+    const BorderValue& sb = style()->borderTop();
+    if (sb.style() == BHIDDEN)
+        return -1;
+    if (sb.style() > BHIDDEN)
+        borderWidth = sb.width;
+
+    const BorderValue& rb = firstChild()->style()->borderTop();
+    if (rb.style() == BHIDDEN)
+        return -1;
+    if (rb.style() > BHIDDEN && rb.width > borderWidth)
+        borderWidth = rb.width;
+
+    bool allHidden = true;
+    for (int c = 0; c < totalCols; c++) {
+        const CellStruct& current = cellAt(0, c);
+        if (current.inColSpan || !current.cell)
+            continue;
+        const BorderValue& cb = current.cell->style()->borderTop();
+        // FIXME: Don't repeat for the same col group
+        RenderTableCol* colGroup = table()->colElement(c);
+        if (colGroup) {
+            const BorderValue& gb = colGroup->style()->borderTop();
+            if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
+                continue;
+            else
+                allHidden = false;
+            if (gb.style() > BHIDDEN && gb.width > borderWidth)
+                borderWidth = gb.width;
+            if (cb.style() > BHIDDEN && cb.width > borderWidth)
+                borderWidth = cb.width;
+        } else {
+            if (cb.style() == BHIDDEN)
+                continue;
+            else
+                allHidden = false;
+            if (cb.style() > BHIDDEN && cb.width > borderWidth)
+                borderWidth = cb.width;
+        }
+    }
+    if (allHidden)
+        return -1;
+
+    return borderWidth / 2;
+}
+
+int RenderTableSection::calcOuterBorderBottom() const
+{
+    int totalCols = table()->numEffCols();
+    if (gridRows == 0 || totalCols == 0)
+        return 0;
+
+    unsigned borderWidth = 0;
+
+    const BorderValue& sb = style()->borderBottom();
+    if (sb.style() == BHIDDEN)
+        return -1;
+    if (sb.style() > BHIDDEN)
+        borderWidth = sb.width;
+
+    const BorderValue& rb = lastChild()->style()->borderBottom();
+    if (rb.style() == BHIDDEN)
+        return -1;
+    if (rb.style() > BHIDDEN && rb.width > borderWidth)
+        borderWidth = rb.width;
+
+    bool allHidden = true;
+    for (int c = 0; c < totalCols; c++) {
+        const CellStruct& current = cellAt(gridRows - 1, c);
+        if (current.inColSpan || !current.cell)
+            continue;
+        const BorderValue& cb = current.cell->style()->borderBottom();
+        // FIXME: Don't repeat for the same col group
+        RenderTableCol* colGroup = table()->colElement(c);
+        if (colGroup) {
+            const BorderValue& gb = colGroup->style()->borderBottom();
+            if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
+                continue;
+            else
+                allHidden = false;
+            if (gb.style() > BHIDDEN && gb.width > borderWidth)
+                borderWidth = gb.width;
+            if (cb.style() > BHIDDEN && cb.width > borderWidth)
+                borderWidth = cb.width;
+        } else {
+            if (cb.style() == BHIDDEN)
+                continue;
+            else
+                allHidden = false;
+            if (cb.style() > BHIDDEN && cb.width > borderWidth)
+                borderWidth = cb.width;
+        }
+    }
+    if (allHidden)
+        return -1;
+
+    return (borderWidth + 1) / 2;
+}
+
+int RenderTableSection::calcOuterBorderLeft(bool rtl) const
+{
+    int totalCols = table()->numEffCols();
+    if (gridRows == 0 || totalCols == 0)
+        return 0;
+
+    unsigned borderWidth = 0;
+
+    const BorderValue& sb = style()->borderLeft();
+    if (sb.style() == BHIDDEN)
+        return -1;
+    if (sb.style() > BHIDDEN)
+        borderWidth = sb.width;
+
+    int leftmostColumn = rtl ? totalCols - 1 : 0;
+    RenderTableCol* colGroup = table()->colElement(leftmostColumn);
+    if (colGroup) {
+        const BorderValue& gb = colGroup->style()->borderLeft();
+        if (gb.style() == BHIDDEN)
+            return -1;
+        if (gb.style() > BHIDDEN && gb.width > borderWidth)
+            borderWidth = gb.width;
+    }
+
+    bool allHidden = true;
+    for (int r = 0; r < gridRows; r++) {
+        const CellStruct& current = cellAt(r, leftmostColumn);
+        if (!current.cell)
+            continue;
+        // FIXME: Don't repeat for the same cell
+        const BorderValue& cb = current.cell->style()->borderLeft();
+        const BorderValue& rb = current.cell->parent()->style()->borderLeft();
+        if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
+            continue;
+        else
+            allHidden = false;
+        if (cb.style() > BHIDDEN && cb.width > borderWidth)
+            borderWidth = cb.width;
+        if (rb.style() > BHIDDEN && rb.width > borderWidth)
+            borderWidth = rb.width;
+    }
+    if (allHidden)
+        return -1;
+
+    return borderWidth / 2;
+}
+
+int RenderTableSection::calcOuterBorderRight(bool rtl) const
+{
+    int totalCols = table()->numEffCols();
+    if (gridRows == 0 || totalCols == 0)
+        return 0;
+
+    unsigned borderWidth = 0;
+
+    const BorderValue& sb = style()->borderRight();
+    if (sb.style() == BHIDDEN)
+        return -1;
+    if (sb.style() > BHIDDEN)
+        borderWidth = sb.width;
+
+    int rightmostColumn = rtl ? 0 : totalCols - 1;
+    RenderTableCol* colGroup = table()->colElement(rightmostColumn);
+    if (colGroup) {
+        const BorderValue& gb = colGroup->style()->borderRight();
+        if (gb.style() == BHIDDEN)
+            return -1;
+        if (gb.style() > BHIDDEN && gb.width > borderWidth)
+            borderWidth = gb.width;
+    }
+
+    bool allHidden = true;
+    for (int r = 0; r < gridRows; r++) {
+        const CellStruct& current = cellAt(r, rightmostColumn);
+        if (!current.cell)
+            continue;
+        // FIXME: Don't repeat for the same cell
+        const BorderValue& cb = current.cell->style()->borderRight();
+        const BorderValue& rb = current.cell->parent()->style()->borderRight();
+        if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
+            continue;
+        else
+            allHidden = false;
+        if (cb.style() > BHIDDEN && cb.width > borderWidth)
+            borderWidth = cb.width;
+        if (rb.style() > BHIDDEN && rb.width > borderWidth)
+            borderWidth = rb.width;
+    }
+    if (allHidden)
+        return -1;
+
+    return (borderWidth + 1) / 2;
+}
+
+void RenderTableSection::recalcOuterBorder()
+{
+    bool rtl = table()->style()->direction() == RTL;
+    m_outerBorderTop = calcOuterBorderTop();
+    m_outerBorderBottom = calcOuterBorderBottom();
+    m_outerBorderLeft = calcOuterBorderLeft(rtl);
+    m_outerBorderRight = calcOuterBorderRight(rtl);
+}
+
+
 void RenderTableSection::paint(PaintInfo& i, int tx, int ty)
 {
     unsigned int totalRows = gridRows;
@@ -629,10 +846,14 @@ void RenderTableSection::paint(PaintInfo& i, int tx, int ty)
     for (; startrow < totalRows; startrow++)
         if (ty + rowPos[startrow+1] >= y - os)
             break;
+    if (startrow == totalRows && ty + rowPos[totalRows] + table()->outerBorderBottom() >= y - os)
+        startrow--;
 
     for (; endrow > 0; endrow--)
         if ( ty + rowPos[endrow-1] <= y + h + os)
             break;
+    if (endrow == 0 && ty + rowPos[0] - table()->outerBorderTop() <= y + h + os)
+        endrow++;
 
     unsigned int startcol = 0;
     unsigned int endcol = totalCols;
@@ -641,10 +862,15 @@ void RenderTableSection::paint(PaintInfo& i, int tx, int ty)
             if (tx + table()->columnPos[startcol + 1] >= x - os)
                 break;
         }
+        if (startcol == totalCols && tx + table()->columnPos[totalCols] + table()->outerBorderRight() >= x - os)
+            startcol--;
+        
         for (; endcol > 0; endcol--) {
             if (tx + table()->columnPos[endcol - 1] <= x + w + os)
                 break;
         }
+        if (endcol == 0 && tx + table()->columnPos[0] - table()->outerBorderLeft() <= y + w + os)
+            endcol++;
     }
 
     if (startcol < endcol) {
index c901bc0b72ee92e89d072c040b2fe1bf106c5b8b..a9d7bfd94e61c50456c1fa30043ad9bb5d259634 100644 (file)
@@ -85,6 +85,18 @@ public:
     virtual int lowestPosition(bool includeOverflowInterior, bool includeSelf) const;
     virtual int rightmostPosition(bool includeOverflowInterior, bool includeSelf) const;
     virtual int leftmostPosition(bool includeOverflowInterior, bool includeSelf) const;
+
+    int calcOuterBorderTop() const;
+    int calcOuterBorderBottom() const;
+    int calcOuterBorderLeft(bool rtl) const;
+    int calcOuterBorderRight(bool rtl) const;
+    void recalcOuterBorder();
+
+    int outerBorderTop() const { return m_outerBorderTop; }
+    int outerBorderBottom() const { return m_outerBorderBottom; }
+    int outerBorderLeft() const { return m_outerBorderLeft; }
+    int outerBorderRight() const { return m_outerBorderRight; }
+
     virtual void paint(PaintInfo& i, int tx, int ty);
 
     int numRows() const { return gridRows; }
@@ -115,6 +127,10 @@ public:
 protected:
     bool ensureRows(int numRows);
     void clearGrid();
+    int m_outerBorderLeft;
+    int m_outerBorderRight;
+    int m_outerBorderTop;
+    int m_outerBorderBottom;
 };
 
 }
index f04da636e0ca8335b43b24ec2c9d153010bd72a0..0e2512e167ecab00a5e5a73edfbfda78426e9dc2 100644 (file)
@@ -785,7 +785,20 @@ RenderStyle::Diff RenderStyle::diff( const RenderStyle *other ) const
              !(inherited_flags._empty_cells == other->inherited_flags._empty_cells) ||
              !(inherited_flags._caption_side == other->inherited_flags._caption_side) ||
              !(noninherited_flags._table_layout == other->noninherited_flags._table_layout))
-        return Layout;
+            return Layout;
+        
+        // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
+        // does not, so these style differences can be width differences.
+        if (inherited_flags._border_collapse &&
+            (borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE ||
+             borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN ||
+             borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE ||
+             borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN ||
+             borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE ||
+             borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN ||
+             borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE ||
+             borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN))
+            return Layout;
     }
 
 // only for lists: