2006-05-12 Eric Seidel <eseidel@apple.com>
authoreseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 May 2006 23:44:39 +0000 (23:44 +0000)
committereseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 May 2006 23:44:39 +0000 (23:44 +0000)
        Reviewed by hyatt.

        Split out table_layout.* into separate files (one per class).
        Search replace instnace variables "foo" with "m_foo" to comply with modern style.

        * WebCore.xcodeproj/project.pbxproj:
        * rendering/AutoTableLayout.cpp: Added.
        (WebCore::AutoTableLayout::AutoTableLayout):
        (WebCore::AutoTableLayout::recalcColumn):
        (WebCore::AutoTableLayout::fullRecalc):
        (WebCore::AutoTableLayout::calcMinMaxWidth):
        (WebCore::AutoTableLayout::calcEffectiveWidth):
        (WebCore::AutoTableLayout::insertSpanCell):
        (WebCore::AutoTableLayout::layout):
        (WebCore::AutoTableLayout::calcPercentages):
        * rendering/AutoTableLayout.h: Added.
        (WebCore::AutoTableLayout::totalPercent):
        (WebCore::AutoTableLayout::Layout::Layout):
        * rendering/FixedTableLayout.cpp: Added.
        (WebCore::FixedTableLayout::FixedTableLayout):
        (WebCore::FixedTableLayout::calcWidthArray):
        (WebCore::FixedTableLayout::calcMinMaxWidth):
        (WebCore::FixedTableLayout::layout):
        * rendering/FixedTableLayout.h: Added.
        * rendering/RenderTable.cpp:
        * rendering/TableLayout.h: Added.
        (WebCore::TableLayout::TableLayout):
        * rendering/table_layout.cpp: Removed.
        * rendering/table_layout.h: Removed.

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

WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/rendering/AutoTableLayout.cpp [new file with mode: 0644]
WebCore/rendering/AutoTableLayout.h [moved from WebCore/rendering/table_layout.h with 56% similarity]
WebCore/rendering/FixedTableLayout.cpp [new file with mode: 0644]
WebCore/rendering/FixedTableLayout.h [new file with mode: 0644]
WebCore/rendering/RenderTable.cpp
WebCore/rendering/TableLayout.cpp [moved from WebCore/rendering/table_layout.cpp with 100% similarity]
WebCore/rendering/TableLayout.h [new file with mode: 0644]

index defd0e0a29df21950968e4077aec330c028da7a5..4686e96b33f40169dcb52118649f19424e8171f5 100644 (file)
@@ -1,3 +1,35 @@
+2006-05-12  Eric Seidel  <eseidel@apple.com>
+
+        Reviewed by hyatt.
+
+        Split out table_layout.* into separate files (one per class).
+        Search replace instnace variables "foo" with "m_foo" to comply with modern style.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/AutoTableLayout.cpp: Added.
+        (WebCore::AutoTableLayout::AutoTableLayout):
+        (WebCore::AutoTableLayout::recalcColumn):
+        (WebCore::AutoTableLayout::fullRecalc):
+        (WebCore::AutoTableLayout::calcMinMaxWidth):
+        (WebCore::AutoTableLayout::calcEffectiveWidth):
+        (WebCore::AutoTableLayout::insertSpanCell):
+        (WebCore::AutoTableLayout::layout):
+        (WebCore::AutoTableLayout::calcPercentages):
+        * rendering/AutoTableLayout.h: Added.
+        (WebCore::AutoTableLayout::totalPercent):
+        (WebCore::AutoTableLayout::Layout::Layout):
+        * rendering/FixedTableLayout.cpp: Added.
+        (WebCore::FixedTableLayout::FixedTableLayout):
+        (WebCore::FixedTableLayout::calcWidthArray):
+        (WebCore::FixedTableLayout::calcMinMaxWidth):
+        (WebCore::FixedTableLayout::layout):
+        * rendering/FixedTableLayout.h: Added.
+        * rendering/RenderTable.cpp:
+        * rendering/TableLayout.h: Added.
+        (WebCore::TableLayout::TableLayout):
+        * rendering/table_layout.cpp: Removed.
+        * rendering/table_layout.h: Removed.
+
 2006-05-12  David Hyatt  <hyatt@apple.com>
 
         Bug 8877.  Change form controls and the bridge entry points from the
index 2eecd70f27d952ea5d95e5900706a1b159a02d32..9569dfc3a6f34b5aff0808c70eee4f22365d6e9f 100644 (file)
                A8C4A80D09D563270003AC8D /* Attr.h in Headers */ = {isa = PBXBuildFile; fileRef = A8C4A7FB09D563270003AC8D /* Attr.h */; };
                A8C4A80E09D563270003AC8D /* Attr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8C4A7FC09D563270003AC8D /* Attr.cpp */; };
                A8C4A84C09D5649D0003AC8D /* MappedAttributeEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = A8C4A84B09D5649D0003AC8D /* MappedAttributeEntry.h */; };
+               A8CFF04D0A154F09000A4234 /* FixedTableLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8CFF0480A154F09000A4234 /* FixedTableLayout.cpp */; };
+               A8CFF04E0A154F09000A4234 /* AutoTableLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = A8CFF0490A154F09000A4234 /* AutoTableLayout.h */; };
+               A8CFF04F0A154F09000A4234 /* FixedTableLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = A8CFF04A0A154F09000A4234 /* FixedTableLayout.h */; };
+               A8CFF0500A154F09000A4234 /* AutoTableLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8CFF04B0A154F09000A4234 /* AutoTableLayout.cpp */; };
+               A8CFF0510A154F09000A4234 /* TableLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = A8CFF04C0A154F09000A4234 /* TableLayout.h */; };
                A8DF3FCE097FA0FC0052981B /* HTMLFormCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = A8DF3FC6097FA0FB0052981B /* HTMLFormCollection.h */; };
                A8DF3FCF097FA0FC0052981B /* HTMLFormCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DF3FC7097FA0FB0052981B /* HTMLFormCollection.cpp */; };
                A8DF3FD0097FA0FC0052981B /* HTMLCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = A8DF3FC8097FA0FB0052981B /* HTMLCollection.h */; };
                BCEA488C097D93020094C9E4 /* RenderText.h in Headers */ = {isa = PBXBuildFile; fileRef = BCEA484D097D93020094C9E4 /* RenderText.h */; };
                BCEA488D097D93020094C9E4 /* RenderTextFragment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCEA484E097D93020094C9E4 /* RenderTextFragment.cpp */; };
                BCEA488E097D93020094C9E4 /* RenderTextFragment.h in Headers */ = {isa = PBXBuildFile; fileRef = BCEA484F097D93020094C9E4 /* RenderTextFragment.h */; };
-               BCEA488F097D93020094C9E4 /* table_layout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCEA4850097D93020094C9E4 /* table_layout.cpp */; };
-               BCEA4890097D93020094C9E4 /* table_layout.h in Headers */ = {isa = PBXBuildFile; fileRef = BCEA4851097D93020094C9E4 /* table_layout.h */; };
                BCEA4944097F0F5C0094C9E4 /* BrowserExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = BCEA4943097F0F5C0094C9E4 /* BrowserExtension.h */; };
                BCEA4947097F0F770094C9E4 /* BrowserExtensionMac.h in Headers */ = {isa = PBXBuildFile; fileRef = BCEA4945097F0F770094C9E4 /* BrowserExtensionMac.h */; };
                BCEA4948097F0F770094C9E4 /* BrowserExtensionMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCEA4946097F0F770094C9E4 /* BrowserExtensionMac.mm */; };
                A8C4A7FB09D563270003AC8D /* Attr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Attr.h; sourceTree = "<group>"; };
                A8C4A7FC09D563270003AC8D /* Attr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Attr.cpp; sourceTree = "<group>"; };
                A8C4A84B09D5649D0003AC8D /* MappedAttributeEntry.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MappedAttributeEntry.h; sourceTree = "<group>"; };
+               A8CFF0480A154F09000A4234 /* FixedTableLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FixedTableLayout.cpp; sourceTree = "<group>"; };
+               A8CFF0490A154F09000A4234 /* AutoTableLayout.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AutoTableLayout.h; sourceTree = "<group>"; };
+               A8CFF04A0A154F09000A4234 /* FixedTableLayout.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FixedTableLayout.h; sourceTree = "<group>"; };
+               A8CFF04B0A154F09000A4234 /* AutoTableLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AutoTableLayout.cpp; sourceTree = "<group>"; };
+               A8CFF04C0A154F09000A4234 /* TableLayout.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TableLayout.h; sourceTree = "<group>"; };
                A8DF3FC6097FA0FB0052981B /* HTMLFormCollection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HTMLFormCollection.h; sourceTree = "<group>"; };
                A8DF3FC7097FA0FB0052981B /* HTMLFormCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLFormCollection.cpp; sourceTree = "<group>"; };
                A8DF3FC8097FA0FB0052981B /* HTMLCollection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HTMLCollection.h; sourceTree = "<group>"; };
                BCEA484D097D93020094C9E4 /* RenderText.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderText.h; sourceTree = "<group>"; };
                BCEA484E097D93020094C9E4 /* RenderTextFragment.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTextFragment.cpp; sourceTree = "<group>"; };
                BCEA484F097D93020094C9E4 /* RenderTextFragment.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderTextFragment.h; sourceTree = "<group>"; };
-               BCEA4850097D93020094C9E4 /* table_layout.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = table_layout.cpp; sourceTree = "<group>"; };
-               BCEA4851097D93020094C9E4 /* table_layout.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = table_layout.h; sourceTree = "<group>"; };
                BCEA4943097F0F5C0094C9E4 /* BrowserExtension.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BrowserExtension.h; sourceTree = "<group>"; };
                BCEA4945097F0F770094C9E4 /* BrowserExtensionMac.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BrowserExtensionMac.h; sourceTree = "<group>"; };
                BCEA4946097F0F770094C9E4 /* BrowserExtensionMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = BrowserExtensionMac.mm; sourceTree = "<group>"; };
                F523D2F302DE443B018635CA /* rendering */ = {
                        isa = PBXGroup;
                        children = (
+                               A8CFF04B0A154F09000A4234 /* AutoTableLayout.cpp */,
+                               A8CFF0490A154F09000A4234 /* AutoTableLayout.h */,
                                BCEA4813097D93020094C9E4 /* bidi.cpp */,
                                BCEA4814097D93020094C9E4 /* bidi.h */,
                                BCEA4815097D93020094C9E4 /* break_lines.cpp */,
                                BCEA4816097D93020094C9E4 /* break_lines.h */,
                                BCEA4817097D93020094C9E4 /* DataRef.h */,
+                               A8CFF0480A154F09000A4234 /* FixedTableLayout.cpp */,
+                               A8CFF04A0A154F09000A4234 /* FixedTableLayout.h */,
                                935C477409AC4D8D00A6AAB4 /* GapRects.h */,
                                BCEA481A097D93020094C9E4 /* InlineTextBox.cpp */,
                                BCEA481B097D93020094C9E4 /* InlineTextBox.h */,
                                93955A4103D72932008635CE /* RenderTreeAsText.h */,
                                A871DFE10A15376B00B12A68 /* RenderWidget.cpp */,
                                A871DFE00A15376B00B12A68 /* RenderWidget.h */,
-                               BCEA4850097D93020094C9E4 /* table_layout.cpp */,
-                               BCEA4851097D93020094C9E4 /* table_layout.h */,
+                               A8CFF04C0A154F09000A4234 /* TableLayout.h */,
                        );
                        path = rendering;
                        sourceTree = "<group>";
                                BCEA488A097D93020094C9E4 /* RenderTheme.h in Headers */,
                                BCEA488C097D93020094C9E4 /* RenderText.h in Headers */,
                                BCEA488E097D93020094C9E4 /* RenderTextFragment.h in Headers */,
-                               BCEA4890097D93020094C9E4 /* table_layout.h in Headers */,
                                BCEA4944097F0F5C0094C9E4 /* BrowserExtension.h in Headers */,
                                BCEA4947097F0F770094C9E4 /* BrowserExtensionMac.h in Headers */,
                                AB67D1A9097F3AE300F9392E /* RenderTextField.h in Headers */,
                                A871DED70A1530C700B12A68 /* RenderPart.h in Headers */,
                                A871DFE30A15376B00B12A68 /* RenderReplaced.h in Headers */,
                                A871DFE40A15376B00B12A68 /* RenderWidget.h in Headers */,
+                               A8CFF04E0A154F09000A4234 /* AutoTableLayout.h in Headers */,
+                               A8CFF04F0A154F09000A4234 /* FixedTableLayout.h in Headers */,
+                               A8CFF0510A154F09000A4234 /* TableLayout.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                BCEA4889097D93020094C9E4 /* RenderTheme.cpp in Sources */,
                                BCEA488B097D93020094C9E4 /* RenderText.cpp in Sources */,
                                BCEA488D097D93020094C9E4 /* RenderTextFragment.cpp in Sources */,
-                               BCEA488F097D93020094C9E4 /* table_layout.cpp in Sources */,
                                65FEA86909833ADE00BED4AB /* Page.cpp in Sources */,
                                BCEA4948097F0F770094C9E4 /* BrowserExtensionMac.mm in Sources */,
                                AB67D1A8097F3AE300F9392E /* RenderTextField.cpp in Sources */,
                                A871DED60A1530C700B12A68 /* RenderPartObject.cpp in Sources */,
                                A871DFE20A15376B00B12A68 /* RenderReplaced.cpp in Sources */,
                                A871DFE50A15376B00B12A68 /* RenderWidget.cpp in Sources */,
+                               A8CFF04D0A154F09000A4234 /* FixedTableLayout.cpp in Sources */,
+                               A8CFF0500A154F09000A4234 /* AutoTableLayout.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/WebCore/rendering/AutoTableLayout.cpp b/WebCore/rendering/AutoTableLayout.cpp
new file mode 100644 (file)
index 0000000..525bd9c
--- /dev/null
@@ -0,0 +1,845 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
+ *           (C) 2002 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "config.h"
+#include "AutoTableLayout.h"
+
+#include "RenderTable.h"
+#include "RenderTableCell.h"
+#include "RenderTableCol.h"
+#include "RenderTableSection.h"
+
+using namespace std;
+
+namespace WebCore {
+
+AutoTableLayout::AutoTableLayout(RenderTable* table)
+    : TableLayout(table)
+    , m_hasPercent(false)
+    , m_percentagesDirty(true)
+    , m_effWidthDirty(true)
+    , m_totalPercent(0)
+{
+}
+
+AutoTableLayout::~AutoTableLayout()
+{
+}
+
+/* recalculates the full structure needed to do layouting and minmax calculations.
+   This is usually calculated on the fly, but needs to be done fully when table cells change
+   dynamically
+*/
+void AutoTableLayout::recalcColumn(int effCol)
+{
+    Layout &l = m_layoutStruct[effCol];
+
+    RenderObject* child = m_table->firstChild();
+    // first we iterate over all rows.
+
+    RenderTableCell* fixedContributor = 0;
+    RenderTableCell* maxContributor = 0;
+
+    while (child) {
+        if (child->isTableSection()) {
+            RenderTableSection* section = static_cast<RenderTableSection*>(child);
+            int numRows = section->numRows();
+            RenderTableCell* last = 0;
+            for (int i = 0; i < numRows; i++) {
+                RenderTableSection::CellStruct current = section->cellAt(i, effCol);
+                RenderTableCell* cell = current.cell;
+                
+                if (current.inColSpan)
+                    continue;
+                if (cell && cell->colSpan() == 1) {
+                    // A cell originates in this column.  Ensure we have
+                    // a min/max width of at least 1px for this column now.
+                    l.minWidth = max(l.minWidth, 1);
+                    l.maxWidth = max(l.maxWidth, 1);
+                    if (!cell->minMaxKnown())
+                        cell->calcMinMaxWidth();
+                    if (cell->minWidth() > l.minWidth)
+                        l.minWidth = cell->minWidth();
+                    if (cell->maxWidth() > l.maxWidth) {
+                        l.maxWidth = cell->maxWidth();
+                        maxContributor = cell;
+                    }
+
+                    Length w = cell->styleOrColWidth();
+                    if (w.value() > 32760)
+                        w.setValue(32760);
+                    if (w.value() < 0)
+                        w.setValue(0);
+                    switch(w.type()) {
+                    case Fixed:
+                        // ignore width=0
+                        if (w.value() > 0 && (int)l.width.type() != Percent) {
+                            int wval = cell->calcBorderBoxWidth(w.value());
+                            if (l.width.isFixed()) {
+                                // Nav/IE weirdness
+                                if ((wval > l.width.value()) ||
+                                    ((l.width.value() == wval) && (maxContributor == cell))) {
+                                    l.width.setValue(wval);
+                                    fixedContributor = cell;
+                                }
+                            } else {
+                                l.width.setValue(Fixed, wval);
+                                fixedContributor = cell;
+                            }
+                        }
+                        break;
+                    case Percent:
+                        m_hasPercent = true;
+                        if (w.value() > 0 && (!l.width.isPercent() || w.value() > l.width.value()))
+                            l.width = w;
+                        break;
+                    case Relative:
+                        if (w.isAuto() || (w.isRelative() && w.value() > l.width.value()))
+                            l.width = w;
+                    default:
+                        break;
+                    }
+                } else {
+                    if (cell && (!effCol || section->cellAt(i, effCol-1).cell != cell)) {
+                        // This spanning cell originates in this column.  Ensure we have
+                        // a min/max width of at least 1px for this column now.
+                        l.minWidth = max(l.minWidth, 1);
+                        l.maxWidth = max(l.maxWidth, 1);
+                        insertSpanCell(cell);
+                    }
+                    last = cell;
+                }
+            }
+        }
+        child = child->nextSibling();
+    }
+
+    // Nav/IE weirdness
+    if (l.width.isFixed()) {
+        if (m_table->style()->htmlHacks() && l.maxWidth > l.width.value() && fixedContributor != maxContributor) {
+            l.width = Length();
+            fixedContributor = 0;
+        }
+    }
+
+    l.maxWidth = max(l.maxWidth, l.minWidth);
+#ifdef DEBUG_LAYOUT
+    qDebug("col %d, final min=%d, max=%d, width=%d(%d)", effCol, l.minWidth, l.maxWidth, l.width.value,  l.width.type);
+#endif
+
+    // ### we need to add col elements as well
+}
+
+void AutoTableLayout::fullRecalc()
+{
+    m_percentagesDirty = true;
+    m_hasPercent = false;
+    m_effWidthDirty = true;
+
+    int nEffCols = m_table->numEffCols();
+    m_layoutStruct.resize(nEffCols);
+    m_layoutStruct.fill(Layout());
+    m_spanCells.fill(0);
+
+    RenderObject *child = m_table->firstChild();
+    Length grpWidth;
+    int cCol = 0;
+    while (child) {
+        if (child->isTableCol()) {
+            RenderTableCol *col = static_cast<RenderTableCol*>(child);
+            int span = col->span();
+            if (col->firstChild()) {
+                grpWidth = col->style()->width();
+            } else {
+                Length w = col->style()->width();
+                if (w.isAuto())
+                    w = grpWidth;
+                if ((w.isFixed() && w.value() == 0) || (w.isPercent() && w.value() == 0))
+                    w = Length();
+                int cEffCol = m_table->colToEffCol(cCol);
+#ifdef DEBUG_LAYOUT
+                qDebug("    col element %d (eff=%d): Length=%d(%d), span=%d, effColSpan=%d",  cCol, cEffCol, w.value, w.type, span, m_table->spanOfEffCol(cEffCol));
+#endif
+                if (!w.isAuto() && span == 1 && cEffCol < nEffCols) {
+                    if (m_table->spanOfEffCol(cEffCol) == 1) {
+                        m_layoutStruct[cEffCol].width = w;
+                        if (w.isFixed() && m_layoutStruct[cEffCol].maxWidth < w.value())
+                            m_layoutStruct[cEffCol].maxWidth = w.value();
+                    }
+                }
+                cCol += span;
+            }
+        } else {
+            break;
+        }
+
+        RenderObject *next = child->firstChild();
+        if (!next)
+            next = child->nextSibling();
+        if (!next && child->parent()->isTableCol()) {
+            next = child->parent()->nextSibling();
+            grpWidth = Length();
+        }
+        child = next;
+    }
+
+
+    for (int i = 0; i < nEffCols; i++)
+        recalcColumn(i);
+}
+
+static bool shouldScaleColumns(RenderTable* table)
+{
+    // A special case.  If this table is not fixed width and contained inside
+    // a cell, then don't bloat the maxwidth by examining percentage growth.
+    bool scale = true;
+    while (table) {
+        Length tw = table->style()->width();
+        if ((tw.isAuto() || tw.isPercent()) && !table->isPositioned()) {
+            RenderBlock* cb = table->containingBlock();
+            while (cb && !cb->isCanvas() && !cb->isTableCell() &&
+                cb->style()->width().isAuto() && !cb->isPositioned())
+                cb = cb->containingBlock();
+
+            table = 0;
+            if (cb && cb->isTableCell() &&
+                (cb->style()->width().isAuto() || cb->style()->width().isPercent())) {
+                if (tw.isPercent())
+                    scale = false;
+                else {
+                    RenderTableCell* cell = static_cast<RenderTableCell*>(cb);
+                    if (cell->colSpan() > 1 || cell->table()->style()->width().isAuto())
+                        scale = false;
+                    else
+                        table = cell->table();
+                }
+            }
+        }
+        else
+            table = 0;
+    }
+    return scale;
+}
+
+void AutoTableLayout::calcMinMaxWidth()
+{
+#ifdef DEBUG_LAYOUT
+    qDebug("AutoTableLayout::calcMinMaxWidth");
+#endif
+    fullRecalc();
+
+    int spanMaxWidth = calcEffectiveWidth();
+    int minWidth = 0;
+    int maxWidth = 0;
+    int maxPercent = 0;
+    int maxNonPercent = 0;
+
+    int remainingPercent = 100;
+    for (unsigned int i = 0; i < m_layoutStruct.size(); i++) {
+        minWidth += m_layoutStruct[i].effMinWidth;
+        maxWidth += m_layoutStruct[i].effMaxWidth;
+        if (m_layoutStruct[i].effWidth.isPercent()) {
+            int percent = min(m_layoutStruct[i].effWidth.value(), remainingPercent);
+            int pw = (m_layoutStruct[i].effMaxWidth * 100) / max(percent, 1);
+            remainingPercent -= percent;
+            maxPercent = max(pw,  maxPercent);
+        } else {
+            maxNonPercent += m_layoutStruct[i].effMaxWidth;
+        }
+    }
+
+    if (shouldScaleColumns(m_table)) {
+        maxNonPercent = (maxNonPercent * 100 + 50) / max(remainingPercent, 1);
+        maxWidth = max(maxNonPercent,  maxWidth);
+        maxWidth = max(maxWidth, maxPercent);
+    }
+
+    maxWidth = max(maxWidth, spanMaxWidth);
+    
+    int bs = m_table->bordersPaddingAndSpacing();
+    minWidth += bs;
+    maxWidth += bs;
+
+    Length tw = m_table->style()->width();
+    if (tw.isFixed() && tw.value() > 0) {
+        minWidth = max(minWidth, tw.value());
+        maxWidth = minWidth;
+    }
+
+    m_table->m_maxWidth = maxWidth;
+    m_table->m_minWidth = minWidth;
+#ifdef DEBUG_LAYOUT
+    qDebug("    minWidth=%d, maxWidth=%d", m_table->m_minWidth, m_table->m_maxWidth);
+#endif
+}
+
+/*
+  This method takes care of colspans.
+  effWidth is the same as width for cells without colspans. If we have colspans, they get modified.
+ */
+int AutoTableLayout::calcEffectiveWidth()
+{
+    int tMaxWidth = 0;
+
+    unsigned int nEffCols = m_layoutStruct.size();
+    int hspacing = m_table->hBorderSpacing();
+#ifdef DEBUG_LAYOUT
+    qDebug("AutoTableLayout::calcEffectiveWidth for %d cols", nEffCols);
+#endif
+    for (unsigned int i = 0; i < nEffCols; i++) {
+        m_layoutStruct[i].effWidth = m_layoutStruct[i].width;
+        m_layoutStruct[i].effMinWidth = m_layoutStruct[i].minWidth;
+        m_layoutStruct[i].effMaxWidth = m_layoutStruct[i].maxWidth;
+    }
+
+    for (unsigned int i = 0; i < m_spanCells.size(); i++) {
+        RenderTableCell *cell = m_spanCells[i];
+        if (!cell)
+            break;
+        int span = cell->colSpan();
+
+        Length w = cell->styleOrColWidth();
+        if (!w.isRelative() && w.value() == 0)
+            w = Length(); // make it Auto
+
+        int col = m_table->colToEffCol(cell->col());
+        unsigned int lastCol = col;
+        int cMinWidth = cell->minWidth() + hspacing;
+        int cMaxWidth = cell->maxWidth() + hspacing;
+        int totalPercent = 0;
+        int minWidth = 0;
+        int maxWidth = 0;
+        bool allColsArePercent = true;
+        bool allColsAreFixed = true;
+        bool haveAuto = false;
+        int fixedWidth = 0;
+#ifdef DEBUG_LAYOUT
+        int cSpan = span;
+#endif
+        while (lastCol < nEffCols && span > 0) {
+            switch (m_layoutStruct[lastCol].width.type()) {
+            case Percent:
+                totalPercent += m_layoutStruct[lastCol].width.value();
+                allColsAreFixed = false;
+                break;
+            case Fixed:
+                if (m_layoutStruct[lastCol].width.value() > 0) {
+                    fixedWidth += m_layoutStruct[lastCol].width.value();
+                    allColsArePercent = false;
+                    // IE resets effWidth to Auto here, but this breaks the konqueror about page and seems to be some bad
+                    // legacy behaviour anyway. mozilla doesn't do this so I decided we don't neither.
+                    break;
+                }
+                // fall through
+            case Auto:
+                haveAuto = true;
+                // fall through
+            default:
+                // If the column is a percentage width, do not let the spanning cell overwrite the
+                // width value.  This caused a mis-rendering on amazon.com.
+                // Sample snippet:
+                // <table border=2 width=100%><
+                //   <tr><td>1</td><td colspan=2>2-3</tr>
+                //   <tr><td>1</td><td colspan=2 width=100%>2-3</td></tr>
+                // </table>
+                if (!m_layoutStruct[lastCol].effWidth.isPercent()) {
+                    m_layoutStruct[lastCol].effWidth = Length();
+                    allColsArePercent = false;
+                }
+                else
+                    totalPercent += m_layoutStruct[lastCol].effWidth.value();
+                allColsAreFixed = false;
+            }
+            span -= m_table->spanOfEffCol(lastCol);
+            minWidth += m_layoutStruct[lastCol].effMinWidth;
+            maxWidth += m_layoutStruct[lastCol].effMaxWidth;
+            lastCol++;
+            cMinWidth -= hspacing;
+            cMaxWidth -= hspacing;
+        }
+#ifdef DEBUG_LAYOUT
+        qDebug("    colspan cell %p at effCol %d, span %d, type %d, value %d cmin=%d min=%d fixedwidth=%d", cell, col, cSpan, w.type, w.value, cMinWidth, minWidth, fixedWidth);
+#endif
+
+        // adjust table max width if needed
+        if (w.isPercent()) {
+            if (totalPercent > w.value() || allColsArePercent) {
+                // can't satify this condition, treat as variable
+                w = Length();
+            } else {
+                int spanMax = max(maxWidth, cMaxWidth);
+#ifdef DEBUG_LAYOUT
+                qDebug("    adjusting tMaxWidth (%d): spanMax=%d, value=%d, totalPercent=%d", tMaxWidth, spanMax, w.value, totalPercent);
+#endif
+                tMaxWidth = max(tMaxWidth, spanMax * 100 / w.value());
+
+                // all non percent columns in the span get percent vlaues to sum up correctly.
+                int percentMissing = w.value() - totalPercent;
+                int totalWidth = 0;
+                for (unsigned int pos = col; pos < lastCol; pos++) {
+                    if (!(m_layoutStruct[pos].width.isPercent()))
+                        totalWidth += m_layoutStruct[pos].effMaxWidth;
+                }
+
+                for (unsigned int pos = col; pos < lastCol && totalWidth > 0; pos++) {
+                    if (!(m_layoutStruct[pos].width.isPercent())) {
+                        int percent = percentMissing * m_layoutStruct[pos].effMaxWidth / totalWidth;
+#ifdef DEBUG_LAYOUT
+                        qDebug("   col %d: setting percent value %d effMaxWidth=%d totalWidth=%d", pos, percent, m_layoutStruct[pos].effMaxWidth, totalWidth);
+#endif
+                        totalWidth -= m_layoutStruct[pos].effMaxWidth;
+                        percentMissing -= percent;
+                        if (percent > 0)
+                            m_layoutStruct[pos].effWidth = Length(percent, Percent);
+                        else
+                            m_layoutStruct[pos].effWidth = Length();
+                    }
+                }
+
+            }
+        }
+
+        // make sure minWidth and maxWidth of the spanning cell are honoured
+        if (cMinWidth > minWidth) {
+            if (allColsAreFixed) {
+#ifdef DEBUG_LAYOUT
+                qDebug("extending minWidth of cols %d-%d to %dpx currentMin=%d accroding to fixed sum %d", col, lastCol-1, cMinWidth, minWidth, fixedWidth);
+#endif
+                for (unsigned int pos = col; fixedWidth > 0 && pos < lastCol; pos++) {
+                    int w = max(m_layoutStruct[pos].effMinWidth, cMinWidth * m_layoutStruct[pos].width.value() / fixedWidth);
+#ifdef DEBUG_LAYOUT
+                    qDebug("   col %d: min=%d, effMin=%d, new=%d", pos, m_layoutStruct[pos].effMinWidth, m_layoutStruct[pos].effMinWidth, w);
+#endif
+                    fixedWidth -= m_layoutStruct[pos].width.value();
+                    cMinWidth -= w;
+                    m_layoutStruct[pos].effMinWidth = w;
+                }
+
+            } else {
+#ifdef DEBUG_LAYOUT
+                qDebug("extending minWidth of cols %d-%d to %dpx currentMin=%d", col, lastCol-1, cMinWidth, minWidth);
+#endif
+                int maxw = maxWidth;
+                int minw = minWidth;
+                
+                // Give min to variable first, to fixed second, and to others third.
+                for (unsigned int pos = col; maxw >= 0 && pos < lastCol; pos++) {
+                    if (m_layoutStruct[pos].width.isFixed() && haveAuto && fixedWidth <= cMinWidth) {
+                        int w = max(m_layoutStruct[pos].effMinWidth, m_layoutStruct[pos].width.value());
+                        fixedWidth -= m_layoutStruct[pos].width.value();
+                        minw -= m_layoutStruct[pos].effMinWidth;
+#ifdef DEBUG_LAYOUT
+                        qDebug("   col %d: min=%d, effMin=%d, new=%d", pos, m_layoutStruct[pos].effMinWidth, m_layoutStruct[pos].effMinWidth, w);
+#endif
+                        maxw -= m_layoutStruct[pos].effMaxWidth;
+                        cMinWidth -= w;
+                        m_layoutStruct[pos].effMinWidth = w;
+                    }
+                }
+
+                for (unsigned int pos = col; maxw >= 0 && pos < lastCol && minw < cMinWidth; pos++) {
+                    if (!(m_layoutStruct[pos].width.isFixed() && haveAuto && fixedWidth <= cMinWidth)) {
+                        int w = max(m_layoutStruct[pos].effMinWidth, maxw ? (cMinWidth * m_layoutStruct[pos].effMaxWidth / maxw) : cMinWidth);
+                        w = min(m_layoutStruct[pos].effMinWidth+(cMinWidth-minw), w);
+                                                
+#ifdef DEBUG_LAYOUT
+                        qDebug("   col %d: min=%d, effMin=%d, new=%d", pos, m_layoutStruct[pos].effMinWidth, m_layoutStruct[pos].effMinWidth, w);
+#endif
+                        maxw -= m_layoutStruct[pos].effMaxWidth;
+                        minw -= m_layoutStruct[pos].effMinWidth;
+                        cMinWidth -= w;
+                        m_layoutStruct[pos].effMinWidth = w;
+                    }
+                }
+            }
+        }
+        if (!(w.isPercent())) {
+            if (cMaxWidth > maxWidth) {
+#ifdef DEBUG_LAYOUT
+                qDebug("extending maxWidth of cols %d-%d to %dpx", col, lastCol-1, cMaxWidth);
+#endif
+                for (unsigned int pos = col; maxWidth >= 0 && pos < lastCol; pos++) {
+                    int w = max(m_layoutStruct[pos].effMaxWidth, maxWidth ? (cMaxWidth * m_layoutStruct[pos].effMaxWidth / maxWidth) : cMaxWidth);
+#ifdef DEBUG_LAYOUT
+                    qDebug("   col %d: max=%d, effMax=%d, new=%d", pos, m_layoutStruct[pos].effMaxWidth, m_layoutStruct[pos].effMaxWidth, w);
+#endif
+                    maxWidth -= m_layoutStruct[pos].effMaxWidth;
+                    cMaxWidth -= w;
+                    m_layoutStruct[pos].effMaxWidth = w;
+                }
+            }
+        } else {
+            for (unsigned int pos = col; pos < lastCol; pos++)
+                m_layoutStruct[pos].maxWidth = max(m_layoutStruct[pos].maxWidth, m_layoutStruct[pos].minWidth);
+        }
+    }
+    m_effWidthDirty = false;
+
+    return tMaxWidth;
+}
+
+/* gets all cells that originate in a column and have a cellspan > 1
+   Sorts them by increasing cellspan
+*/
+void AutoTableLayout::insertSpanCell(RenderTableCell *cell)
+{
+    if (!cell || cell->colSpan() == 1)
+        return;
+
+    int size = m_spanCells.size();
+    if (!size || m_spanCells[size-1] != 0) {
+        m_spanCells.resize(size + 10);
+        for (int i = 0; i < 10; i++)
+            m_spanCells[size+i] = 0;
+        size += 10;
+    }
+
+    // add them in sort. This is a slow algorithm, and a binary search or a fast sorting after collection would be better
+    unsigned int pos = 0;
+    int span = cell->colSpan();
+    while (pos < m_spanCells.size() && m_spanCells[pos] && span > m_spanCells[pos]->colSpan())
+        pos++;
+    memmove(m_spanCells.data()+pos+1, m_spanCells.data()+pos, (size-pos-1)*sizeof(RenderTableCell *));
+    m_spanCells[pos] = cell;
+}
+
+
+void AutoTableLayout::layout()
+{
+    // table layout based on the values collected in the layout structure.
+    int tableWidth = m_table->width() - m_table->bordersPaddingAndSpacing();
+    int available = tableWidth;
+    int nEffCols = m_table->numEffCols();
+
+    if (nEffCols != (int)m_layoutStruct.size()) {
+        fullRecalc();
+        nEffCols = m_table->numEffCols();
+    }
+#ifdef DEBUG_LAYOUT
+    qDebug("AutoTableLayout::layout()");
+#endif
+
+    if (m_effWidthDirty)
+        calcEffectiveWidth();
+
+#ifdef DEBUG_LAYOUT
+    qDebug("    tableWidth=%d,  nEffCols=%d", tableWidth,  nEffCols);
+    for (int i = 0; i < nEffCols; i++) {
+        qDebug("    effcol %d is of type %d value %d, minWidth=%d, maxWidth=%d",
+               i, m_layoutStruct[i].width.type, m_layoutStruct[i].width.value,
+               m_layoutStruct[i].minWidth, m_layoutStruct[i].maxWidth);
+        qDebug("        effective: type %d value %d, minWidth=%d, maxWidth=%d",
+               m_layoutStruct[i].effWidth.type, m_layoutStruct[i].effWidth.value,
+               m_layoutStruct[i].effMinWidth, m_layoutStruct[i].effMaxWidth);
+    }
+#endif
+
+    bool havePercent = false;
+    bool haveRelative = false;
+    int totalRelative = 0;
+    int numAuto = 0;
+    int numFixed = 0;
+    int totalAuto = 0;
+    int totalFixed = 0;
+    int totalPercent = 0;
+    int allocAuto = 0;
+
+    // fill up every cell with its minWidth
+    for (int i = 0; i < nEffCols; i++) {
+        int w = m_layoutStruct[i].effMinWidth;
+        m_layoutStruct[i].calcWidth = w;
+        available -= w;
+        Length& width = m_layoutStruct[i].effWidth;
+        switch (width.type()) {
+        case Percent:
+            havePercent = true;
+            totalPercent += width.value();
+            break;
+        case Relative:
+            haveRelative = true;
+            totalRelative += width.value();
+            break;
+        case Fixed:
+            numFixed++;
+            totalFixed += m_layoutStruct[i].effMaxWidth;
+            // fall through
+            break;
+        case Auto:
+        case Static:
+            numAuto++;
+            totalAuto += m_layoutStruct[i].effMaxWidth;
+            allocAuto += w;
+        default:
+            break;
+        }
+    }
+
+    // allocate width to percent cols
+    if (available > 0 && havePercent) {
+        for (int i = 0; i < nEffCols; i++) {
+            Length &width = m_layoutStruct[i].effWidth;
+            if (width.isPercent()) {
+                int w = max(int(m_layoutStruct[i].effMinWidth), width.calcMinValue(tableWidth));
+                available += m_layoutStruct[i].calcWidth - w;
+                m_layoutStruct[i].calcWidth = w;
+            }
+        }
+        if (totalPercent > 100) {
+            // remove overallocated space from the last columns
+            int excess = tableWidth*(totalPercent-100)/100;
+            for (int i = nEffCols-1; i >= 0; i--) {
+                if (m_layoutStruct[i].effWidth.isPercent()) {
+                    int w = m_layoutStruct[i].calcWidth;
+                    int reduction = min(w,  excess);
+                    // the lines below might look inconsistent, but that's the way it's handled in mozilla
+                    excess -= reduction;
+                    int newWidth = max(int (m_layoutStruct[i].effMinWidth), w - reduction);
+                    available += w - newWidth;
+                    m_layoutStruct[i].calcWidth = newWidth;
+                }
+            }
+        }
+    }
+#ifdef DEBUG_LAYOUT
+    qDebug("percent satisfied: available is %d", available);
+#endif
+    
+    // then allocate width to fixed cols
+    if (available > 0) {
+        for (int i = 0; i < nEffCols; ++i) {
+            Length &width = m_layoutStruct[i].effWidth;
+            if (width.isFixed() && width.value() > m_layoutStruct[i].calcWidth) {
+                available += m_layoutStruct[i].calcWidth - width.value();
+                m_layoutStruct[i].calcWidth = width.value();
+            }
+        }
+    }
+#ifdef DEBUG_LAYOUT
+    qDebug("fixed satisfied: available is %d", available);
+#endif
+
+    // now satisfy relative
+    if (available > 0) {
+        for (int i = 0; i < nEffCols; i++) {
+            Length &width = m_layoutStruct[i].effWidth;
+            if (width.isRelative() && width.value() != 0) {
+                // width=0* gets effMinWidth.
+                int w = width.value() * tableWidth / totalRelative;
+                available += m_layoutStruct[i].calcWidth - w;
+                m_layoutStruct[i].calcWidth = w;
+            }
+        }
+    }
+
+    // now satisfy variable
+    if (available > 0 && numAuto) {
+        available += allocAuto; // this gets redistributed
+        for (int i = 0; i < nEffCols; i++) {
+            Length &width = m_layoutStruct[i].effWidth;
+            if (width.isAuto() && totalAuto != 0) {
+                int w = max(int(m_layoutStruct[i].calcWidth), available * m_layoutStruct[i].effMaxWidth / totalAuto);
+                available -= w;
+                totalAuto -= m_layoutStruct[i].effMaxWidth;
+                m_layoutStruct[i].calcWidth = w;
+            }
+        }
+    }
+#ifdef DEBUG_LAYOUT
+    qDebug("variable satisfied: available is %d",  available);
+#endif
+
+    // spread over fixed columns
+    if (available > 0 && numFixed) {
+        // still have some width to spread, distribute to fixed columns
+        for (int i = 0; i < nEffCols; i++) {
+            Length &width = m_layoutStruct[i].effWidth;
+            if (width.isFixed()) {
+                int w = available * m_layoutStruct[i].effMaxWidth / totalFixed;
+                available -= w;
+                totalFixed -= m_layoutStruct[i].effMaxWidth;
+                m_layoutStruct[i].calcWidth += w;
+            }
+        }
+    }
+    
+#ifdef DEBUG_LAYOUT
+    qDebug("after fixed distribution: available=%d",  available);
+#endif
+    
+    // spread over percent colums
+    if (available > 0 && m_hasPercent && totalPercent < 100) {
+        // still have some width to spread, distribute weighted to percent columns
+        for (int i = 0; i < nEffCols; i++) {
+            Length &width = m_layoutStruct[i].effWidth;
+            if (width.isPercent()) {
+                int w = available * width.value() / totalPercent;
+                available -= w;
+                totalPercent -= width.value();
+                m_layoutStruct[i].calcWidth += w;
+                if (!available || !totalPercent) break;
+            }
+        }
+    }
+
+#ifdef DEBUG_LAYOUT
+    qDebug("after percent distribution: available=%d",  available);
+#endif
+
+    // spread over the rest
+    if (available > 0) {
+        int total = nEffCols;
+        // still have some width to spread
+        int i = nEffCols;
+        while ( i--) {
+            int w = available / total;
+            available -= w;
+            total--;
+            m_layoutStruct[i].calcWidth += w;
+        }
+    }
+
+#ifdef DEBUG_LAYOUT
+    qDebug("after equal distribution: available=%d",  available);
+#endif
+    // if we have overallocated, reduce every cell according to the difference between desired width and minwidth
+    // this seems to produce to the pixel exaxt results with IE. Wonder is some of this also holds for width distributing.
+    if (available < 0) {
+        // Need to reduce cells with the following prioritization:
+        // (1) Auto
+        // (2) Relative
+        // (3) Fixed
+        // (4) Percent
+        // This is basically the reverse of how we grew the cells.
+        if (available < 0) {
+            int mw = 0;
+            for (int i = nEffCols-1; i >= 0; i--) {
+                Length &width = m_layoutStruct[i].effWidth;
+                if (width.isAuto())
+                    mw += m_layoutStruct[i].calcWidth - m_layoutStruct[i].effMinWidth;
+            }
+            
+            for (int i = nEffCols-1; i >= 0 && mw > 0; i--) {
+                Length &width = m_layoutStruct[i].effWidth;
+                if (width.isAuto()) {
+                    int minMaxDiff = m_layoutStruct[i].calcWidth-m_layoutStruct[i].effMinWidth;
+                    int reduce = available * minMaxDiff / mw;
+                    m_layoutStruct[i].calcWidth += reduce;
+                    available -= reduce;
+                    mw -= minMaxDiff;
+                    if (available >= 0)
+                        break;
+                }
+            }
+        }
+
+        if (available < 0) {
+            int mw = 0;
+            for (int i = nEffCols-1; i >= 0; i--) {
+                Length& width = m_layoutStruct[i].effWidth;
+                if (width.isRelative())
+                    mw += m_layoutStruct[i].calcWidth - m_layoutStruct[i].effMinWidth;
+            }
+            
+            for (int i = nEffCols-1; i >= 0 && mw > 0; i--) {
+                Length& width = m_layoutStruct[i].effWidth;
+                if (width.isRelative()) {
+                    int minMaxDiff = m_layoutStruct[i].calcWidth-m_layoutStruct[i].effMinWidth;
+                    int reduce = available * minMaxDiff / mw;
+                    m_layoutStruct[i].calcWidth += reduce;
+                    available -= reduce;
+                    mw -= minMaxDiff;
+                    if (available >= 0)
+                        break;
+                }
+            }
+        }
+
+        if (available < 0) {
+            int mw = 0;
+            for (int i = nEffCols-1; i >= 0; i--) {
+                Length& width = m_layoutStruct[i].effWidth;
+                if (width.isFixed())
+                    mw += m_layoutStruct[i].calcWidth - m_layoutStruct[i].effMinWidth;
+            }
+            
+            for (int i = nEffCols-1; i >= 0 && mw > 0; i--) {
+                Length& width = m_layoutStruct[i].effWidth;
+                if (width.isFixed()) {
+                    int minMaxDiff = m_layoutStruct[i].calcWidth-m_layoutStruct[i].effMinWidth;
+                    int reduce = available * minMaxDiff / mw;
+                    m_layoutStruct[i].calcWidth += reduce;
+                    available -= reduce;
+                    mw -= minMaxDiff;
+                    if (available >= 0)
+                        break;
+                }
+            }
+        }
+
+        if (available < 0) {
+            int mw = 0;
+            for (int i = nEffCols-1; i >= 0; i--) {
+                Length& width = m_layoutStruct[i].effWidth;
+                if (width.isPercent())
+                    mw += m_layoutStruct[i].calcWidth - m_layoutStruct[i].effMinWidth;
+            }
+            
+            for (int i = nEffCols-1; i >= 0 && mw > 0; i--) {
+                Length& width = m_layoutStruct[i].effWidth;
+                if (width.isPercent()) {
+                    int minMaxDiff = m_layoutStruct[i].calcWidth-m_layoutStruct[i].effMinWidth;
+                    int reduce = available * minMaxDiff / mw;
+                    m_layoutStruct[i].calcWidth += reduce;
+                    available -= reduce;
+                    mw -= minMaxDiff;
+                    if (available >= 0)
+                        break;
+                }
+            }
+        }
+    }
+
+    int pos = 0;
+    for (int i = 0; i < nEffCols; i++) {
+#ifdef DEBUG_LAYOUT
+        qDebug("col %d: %d (width %d)", i, pos, m_layoutStruct[i].calcWidth);
+#endif
+        m_table->columnPos[i] = pos;
+        pos += m_layoutStruct[i].calcWidth + m_table->hBorderSpacing();
+    }
+    m_table->columnPos[m_table->columnPos.size()-1] = pos;
+}
+
+
+void AutoTableLayout::calcPercentages() const
+{
+    m_totalPercent = 0;
+    for (unsigned i = 0; i < m_layoutStruct.size(); i++) {
+        if (m_layoutStruct[i].width.isPercent())
+            m_totalPercent += m_layoutStruct[i].width.value();
+    }
+    m_percentagesDirty = false;
+}
+
+#undef DEBUG_LAYOUT
+
+}
similarity index 56%
rename from WebCore/rendering/table_layout.h
rename to WebCore/rendering/AutoTableLayout.h
index c2e9a8e2055a245093b48fba36f0218c598d44d8..c28ec6115225ba999f2d26d979bd7161b22b11c3 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
-#ifndef TABLE_LAYOUT_H
-#define TABLE_LAYOUT_H
+#ifndef AutoTableLayout_H
+#define AutoTableLayout_H
+
+#include "TableLayout.h"
 
 #include "DeprecatedArray.h"
 #include "Length.h"
@@ -31,66 +33,34 @@ namespace WebCore {
 class RenderTable;
 class RenderTableCell;
 
-// -------------------------------------------------------------------------
-
-class TableLayout
-{
-public:
-    TableLayout(RenderTable* t) : table(t) {}
-    virtual ~TableLayout() {};
-
-    virtual void calcMinMaxWidth() = 0;
-    virtual void layout() = 0;
-
-protected:
-    RenderTable *table;
-};
-
-// -------------------------------------------------------------------------
-
-class FixedTableLayout : public TableLayout
-{
-public:
-    FixedTableLayout(RenderTable*);
-    ~FixedTableLayout();
-
-    void calcMinMaxWidth();
-    void layout();
-
-protected:
-    int calcWidthArray(int tableWidth);
-
-    DeprecatedArray<Length> width;
-};
-
-// -------------------------------------------------------------------------
-
 class AutoTableLayout : public TableLayout
 {
 public:
-    AutoTableLayout(RenderTable *table);
+    AutoTableLayout(RenderTable*);
     ~AutoTableLayout();
 
     void calcMinMaxWidth();
     void layout();
 
-
 protected:
     void fullRecalc();
     void recalcColumn(int effCol);
     int totalPercent() const {
-        if (percentagesDirty)
+        if (m_percentagesDirty)
             calcPercentages();
-        return total_percent;
+        return m_totalPercent;
     }
     void calcPercentages() const;
     int calcEffectiveWidth();
     void insertSpanCell(RenderTableCell*);
 
     struct Layout {
-        Layout() : minWidth(0), maxWidth(0),
-                   effMinWidth(0), effMaxWidth(0),
-                   calcWidth(0) {}
+        Layout()
+            : minWidth(0)
+            , maxWidth(0)
+            , effMinWidth(0)
+            , effMaxWidth(0)
+            , calcWidth(0) {}
         Length width;
         Length effWidth;
         int minWidth;
@@ -100,12 +70,12 @@ protected:
         int calcWidth;
     };
 
-    DeprecatedArray<Layout> layoutStruct;
-    DeprecatedArray<RenderTableCell*> spanCells;
-    bool hasPercent : 1;
-    mutable bool percentagesDirty : 1;
-    mutable bool effWidthDirty : 1;
-    mutable unsigned short total_percent;
+    DeprecatedArray<Layout> m_layoutStruct;
+    DeprecatedArray<RenderTableCell*> m_spanCells;
+    bool m_hasPercent : 1;
+    mutable bool m_percentagesDirty : 1;
+    mutable bool m_effWidthDirty : 1;
+    mutable unsigned short m_totalPercent;
 };
 
 }
diff --git a/WebCore/rendering/FixedTableLayout.cpp b/WebCore/rendering/FixedTableLayout.cpp
new file mode 100644 (file)
index 0000000..4e79078
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
+ *           (C) 2002 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "config.h"
+#include "FixedTableLayout.h"
+
+#include "RenderTable.h"
+#include "RenderTableCell.h"
+#include "RenderTableCol.h"
+#include "RenderTableSection.h"
+
+/*
+  The text below is from the CSS 2.1 specs.
+
+  Fixed table layout
+
+  With this (fast) algorithm, the horizontal layout of the table does
+  not depend on the contents of the cells; it only depends on the
+  table's m_width, the m_width of the columns, and borders or cell
+  spacing.
+
+  The table's m_width may be specified explicitly with the 'm_width'
+  property. A value of 'auto' (for both 'display: table' and 'display:
+  inline-table') means use the automatic table layout algorithm.
+
+  In the fixed table layout algorithm, the m_width of each column is
+  determined as follows:
+
+    1. A column element with a value other than 'auto' for the 'm_width'
+    property sets the m_width for that column.
+
+    2. Otherwise, a cell in the first row with a value other than
+    'auto' for the 'm_width' property sets the m_width for that column. If
+    the cell spans more than one column, the m_width is divided over the
+    columns.
+
+    3. Any remaining columns equally divide the remaining horizontal
+    table space (minus borders or cell spacing).
+
+  The m_width of the table is then the greater of the value of the
+  'm_width' property for the table element and the sum of the column
+  widths (plus cell spacing or borders). If the table is wider than
+  the columns, the extra space should be distributed over the columns.
+
+
+  In this manner, the user agent can begin to lay out the table once
+  the entire first row has been received. Cells in subsequent rows do
+  not affect column widths. Any cell that has content that overflows
+  uses the 'overflow' property to determine whether to clip the
+  overflow content.
+
+_____________________________________________________
+
+  This is not quite true when comparing to IE. IE always honours
+  table-layout:fixed and treats a variable table m_width as 100%. Makes
+  a lot of sense, and is implemented here the same way.
+
+*/
+
+using namespace std;
+
+namespace WebCore {
+
+FixedTableLayout::FixedTableLayout(RenderTable* table)
+    : TableLayout(table)
+{
+}
+
+FixedTableLayout::~FixedTableLayout()
+{
+}
+
+int FixedTableLayout::calcWidthArray(int tableWidth)
+{
+    int usedWidth = 0;
+
+    // iterate over all <col> elements
+    RenderObject* child = m_table->firstChild();
+    int cCol = 0;
+    int nEffCols = m_table->numEffCols();
+    m_width.resize(nEffCols);
+    m_width.fill(Length(Auto));
+
+#ifdef DEBUG_LAYOUT
+    qDebug("FixedTableLayout::calcWidthArray(%d)", tableWidth);
+    qDebug("    col elements:");
+#endif
+
+    Length grpWidth;
+    while (child) {
+        if (child->isTableCol()) {
+            RenderTableCol *col = static_cast<RenderTableCol *>(child);
+            int span = col->span();
+            if (col->firstChild())
+                grpWidth = col->style()->width();
+            else {
+                Length w = col->style()->width();
+                if (w.isAuto())
+                    w = grpWidth;
+                int effWidth = 0;
+                if (w.isFixed() && w.value() > 0)
+                    effWidth = w.value();
+                
+#ifdef DEBUG_LAYOUT
+                qDebug("    col element: effCol=%d, span=%d: %d w=%d type=%d",
+                       cCol, span, effWidth,  w.value, w.type());
+#endif
+                int usedSpan = 0;
+                int i = 0;
+                while (usedSpan < span) {
+                    if(cCol + i >= nEffCols) {
+                        m_table->appendColumn(span - usedSpan);
+                        nEffCols++;
+                        m_width.resize(nEffCols);
+                        m_width[nEffCols-1] = Length();
+                    }
+                    int eSpan = m_table->spanOfEffCol(cCol+i);
+                    if ((w.isFixed() || w.isPercent()) && w.value() > 0) {
+                        m_width[cCol+i] = Length(w.value() * eSpan, w.type());
+                        usedWidth += effWidth * eSpan;
+#ifdef DEBUG_LAYOUT
+                        qDebug("    setting effCol %d (span=%d) to m_width %d(type=%d)",
+                               cCol+i, eSpan, m_width[cCol+i].value, m_width[cCol+i].type());
+#endif
+                    }
+                    usedSpan += eSpan;
+                    i++;
+                }
+                cCol += i;
+            }
+        } else
+            break;
+
+        RenderObject *next = child->firstChild();
+        if (!next)
+            next = child->nextSibling();
+        if (!next && child->parent()->isTableCol()) {
+            next = child->parent()->nextSibling();
+            grpWidth = Length();
+        }
+        child = next;
+    }
+
+#ifdef DEBUG_LAYOUT
+    qDebug("    first row:");
+#endif
+    // iterate over the first row in case some are unspecified.
+    RenderTableSection *section = m_table->head;
+    if (!section)
+        section = m_table->firstBody;
+    if (!section)
+        section = m_table->foot;
+    if (section) {
+        cCol = 0;
+        // FIXME: Technically the first row could be in an arbitrary section (e.g., an nth section
+        // if the previous n-1 sections have no rows), so this check isn't good enough.
+        // get the first cell in the first row
+        RenderObject* firstRow = section->firstChild();
+        child = firstRow ? firstRow->firstChild() : 0;
+        while (child) {
+            if (child->isTableCell()) {
+                RenderTableCell *cell = static_cast<RenderTableCell *>(child);
+                Length w = cell->styleOrColWidth();
+                int span = cell->colSpan();
+                int effWidth = 0;
+                if ((w.isFixed() || w.isPercent()) && w.value() > 0)
+                    effWidth = w.value();
+                
+#ifdef DEBUG_LAYOUT
+                qDebug("    table cell: effCol=%d, span=%d: %d",  cCol, span, effWidth);
+#endif
+                int usedSpan = 0;
+                int i = 0;
+                while (usedSpan < span) {
+                    ASSERT(cCol + i < nEffCols);
+                    int eSpan = m_table->spanOfEffCol(cCol+i);
+                    // only set if no col element has already set it.
+                    if (m_width[cCol+i].isAuto() && w.type() != Auto) {
+                        m_width[cCol+i] = Length(w.value() * eSpan, w.type());
+                        usedWidth += effWidth*eSpan;
+#ifdef DEBUG_LAYOUT
+                        qDebug("    setting effCol %d (span=%d) to m_width %d(type=%d)",
+                               cCol+i, eSpan, m_width[cCol+i].value, m_width[cCol+i].type());
+#endif
+                    }
+#ifdef DEBUG_LAYOUT
+                    else {
+                        qDebug("    m_width of col %d already defined (span=%d)", cCol, m_table->spanOfEffCol(cCol));
+                    }
+#endif
+                    usedSpan += eSpan;
+                    i++;
+                }
+                cCol += i;
+            }
+            child = child->nextSibling();
+        }
+    }
+
+    return usedWidth;
+
+}
+
+void FixedTableLayout::calcMinMaxWidth()
+{
+    // FIXME: This entire calculation is incorrect for both minwidth and maxwidth.
+    
+    // we might want to wait until we have all of the first row before
+    // layouting for the first time.
+
+    // only need to calculate the minimum m_width as the sum of the
+    // cols/cells with a fixed m_width.
+    //
+    // The maximum m_width is max(minWidth, tableWidth).
+    int bs = m_table->bordersPaddingAndSpacing();
+    
+    int tableWidth = m_table->style()->width().isFixed() ? m_table->style()->width().value() - bs : 0;
+    int mw = calcWidthArray(tableWidth) + bs;
+
+    m_table->m_minWidth = max(mw, tableWidth);
+    m_table->m_maxWidth = m_table->m_minWidth;
+}
+
+void FixedTableLayout::layout()
+{
+    int tableWidth = m_table->width() - m_table->bordersPaddingAndSpacing();
+    int available = tableWidth;
+    int nEffCols = m_table->numEffCols();
+    int totalPercent = 0;
+    
+#ifdef DEBUG_LAYOUT
+    qDebug("FixedTableLayout::layout: tableWidth=%d, numEffCols=%d",  tableWidth, nEffCols);
+#endif
+
+
+    DeprecatedArray<int> calcWidth;
+    calcWidth.resize(nEffCols);
+    calcWidth.fill(-1);
+
+    // assign  percent m_width
+    if (available > 0) {
+        for (int i = 0; i < nEffCols; i++)
+            if (m_width[i].isPercent())
+                totalPercent += m_width[i].value();
+
+        // calculate how much to distribute to percent cells.
+        int base = tableWidth * totalPercent / 100;
+        if (base > available)
+            base = available;
+        else
+            totalPercent = 100;
+
+#ifdef DEBUG_LAYOUT
+        qDebug("FixedTableLayout::layout: assigning percent m_width, base=%d, totalPercent=%d", base, totalPercent);
+#endif
+        for (int i = 0; available > 0 && i < nEffCols; i++) {
+            if (m_width[i].isPercent()) {
+                int w = base * m_width[i].value() / totalPercent;
+                available -= w;
+                calcWidth[i] = w;
+            }
+        }
+    }
+    
+    // next assign fixed m_width
+    for (int i = 0; i < nEffCols; i++) {
+        if (m_width[i].isFixed()) {
+            calcWidth[i] = m_width[i].value();
+            available -= m_width[i].value();
+        }
+    }
+
+    // assign variable m_width
+    if (available > 0) {
+        int totalAuto = 0;
+        for (int i = 0; i < nEffCols; i++)
+            if (m_width[i].isAuto())
+                totalAuto++;
+
+        for (int i = 0; available > 0 && i < nEffCols; i++) {
+            if (m_width[i].isAuto()) {
+                int w = available / totalAuto;
+                available -= w;
+                calcWidth[i] = w;
+                totalAuto--;
+            }
+        }
+    }
+
+    for (int i = 0; i < nEffCols; i++)
+        if (calcWidth[i] <= 0)
+            calcWidth[i] = 0; // IE gives min 1 px...
+
+    // spread extra space over columns
+    if (available > 0) {
+        int total = nEffCols;
+        // still have some m_width to spread
+        int i = nEffCols;
+        while ( i--) {
+            int w = available / total;
+            available -= w;
+            total--;
+            calcWidth[i] += w;
+        }
+    }
+    
+    int pos = 0;
+    int hspacing = m_table->hBorderSpacing();
+    for (int i = 0; i < nEffCols; i++) {
+#ifdef DEBUG_LAYOUT
+        qDebug("col %d: %d (m_width %d)", i, pos, calcWidth[i]);
+#endif
+        m_table->columnPos[i] = pos;
+        pos += calcWidth[i] + hspacing;
+    }
+    m_table->columnPos[m_table->columnPos.size()-1] = pos;
+}
+
+#undef DEBUG_LAYOUT
+
+}
diff --git a/WebCore/rendering/FixedTableLayout.h b/WebCore/rendering/FixedTableLayout.h
new file mode 100644 (file)
index 0000000..7ea356c
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
+ *           (C) 2002 Dirk Mueller (mueller@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef FixedTableLayout_H
+#define FixedTableLayout_H
+
+#include "TableLayout.h"
+
+#include "DeprecatedArray.h"
+#include "Length.h"
+
+namespace WebCore {
+
+class RenderTable;
+
+class FixedTableLayout : public TableLayout
+{
+public:
+    FixedTableLayout(RenderTable*);
+    ~FixedTableLayout();
+
+    void calcMinMaxWidth();
+    void layout();
+
+protected:
+    int calcWidthArray(int tableWidth);
+
+    DeprecatedArray<Length> m_width;
+};
+
+}
+
+#endif
index 6ef6d4fc5206e498859c919aacf6d953318caa42..fa42ca765fc26041440b7cda7f1b8e32aec156cd 100644 (file)
 #include "config.h"
 #include "RenderTable.h"
 
-#include "RenderTableSection.h"
-#include "RenderTableCol.h"
-#include "RenderTableCell.h"
+#include "AutoTableLayout.h"
 #include "Document.h"
-#include "table_layout.h"
+#include "FixedTableLayout.h"
 #include "HTMLNames.h"
 #include "KWQTextStream.h"
+#include "RenderTableCell.h"
+#include "RenderTableCol.h"
+#include "RenderTableSection.h"
 
 using namespace std;
 
diff --git a/WebCore/rendering/TableLayout.h b/WebCore/rendering/TableLayout.h
new file mode 100644 (file)
index 0000000..c8d5ec1
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
+ *           (C) 2002 Dirk Mueller (mueller@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef TableLayout_H
+#define TableLayout_H
+
+namespace WebCore {
+
+class RenderTable;
+
+class TableLayout
+{
+public:
+    TableLayout(RenderTable* t) : m_table(t) {}
+    virtual ~TableLayout() {};
+
+    virtual void calcMinMaxWidth() = 0;
+    virtual void layout() = 0;
+
+protected:
+    RenderTable* m_table;
+};
+
+}
+
+#endif