auto import from //depot/cupcake/@135843
diff --git a/WebCore/rendering/AutoTableLayout.cpp b/WebCore/rendering/AutoTableLayout.cpp
new file mode 100644
index 0000000..43c66cd
--- /dev/null
+++ b/WebCore/rendering/AutoTableLayout.cpp
@@ -0,0 +1,789 @@
+/*
+ * Copyright (C) 2002 Lars Knoll ([email protected])
+ *           (C) 2002 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, 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;
+                
+                bool cellHasContent = cell && (cell->firstChild() || cell->style()->hasBorder() || cell->style()->hasPadding());
+                if (cellHasContent)
+                    l.emptyCellsOnly = false;
+                    
+                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, cellHasContent ? 1 : 0);
+                    l.maxWidth = max(l.maxWidth, 1);
+                    if (cell->prefWidthsDirty())
+                        cell->calcPrefWidths();
+                    l.minWidth = max(cell->minPrefWidth(), l.minWidth);
+                    if (cell->maxPrefWidth() > l.maxWidth) {
+                        l.maxWidth = cell->maxPrefWidth();
+                        maxContributor = cell;
+                    }
+
+                    Length w = cell->styleOrColWidth();
+                    // FIXME: What is this arbitrary value?
+                    if (w.rawValue() > 32760)
+                        w.setRawValue(32760);
+                    if (w.isNegative())
+                        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.isPositive() && (!l.width.isPercent() || w.rawValue() > l.width.rawValue()))
+                            l.width = w;
+                        break;
+                    case Relative:
+                        // FIXME: Need to understand this case and whether it makes sense to compare values
+                        // which are not necessarily of the same type.
+                        if (w.isAuto() || (w.isRelative() && w.value() > l.width.rawValue()))
+                            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, cellHasContent ? 1 : 0);
+                        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);
+
+    // ### 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.isPercent()) && w.isZero())
+                    w = Length();
+                int cEffCol = m_table->colToEffCol(cCol);
+                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->isRenderView() && !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::calcPrefWidths(int& minWidth, int& maxWidth)
+{
+    fullRecalc();
+
+    int spanMaxWidth = calcEffectiveWidth();
+    minWidth = 0;
+    maxWidth = 0;
+    float maxPercent = 0;
+    float maxNonPercent = 0;
+    bool scaleColumns = shouldScaleColumns(m_table);
+
+    // We substitute 0 percent by (epsilon / percentScaleFactor) percent in two places below to avoid division by zero.
+    // FIXME: Handle the 0% cases properly.
+    const int epsilon = 1;
+
+    int remainingPercent = 100 * percentScaleFactor;
+    for (unsigned int i = 0; i < m_layoutStruct.size(); i++) {
+        minWidth += m_layoutStruct[i].effMinWidth;
+        maxWidth += m_layoutStruct[i].effMaxWidth;
+        if (scaleColumns) {
+            if (m_layoutStruct[i].effWidth.isPercent()) {
+                int percent = min(m_layoutStruct[i].effWidth.rawValue(), remainingPercent);
+                float pw = static_cast<float>(m_layoutStruct[i].effMaxWidth) * 100 * percentScaleFactor / max(percent, epsilon);
+                maxPercent = max(pw,  maxPercent);
+                remainingPercent -= percent;
+            } else
+                maxNonPercent += m_layoutStruct[i].effMaxWidth;
+        }
+    }
+
+    if (scaleColumns) {
+        maxNonPercent = maxNonPercent * 100 * percentScaleFactor / max(remainingPercent, epsilon);
+        maxWidth = max(maxWidth, static_cast<int>(min(maxNonPercent, INT_MAX / 2.0f)));
+        maxWidth = max(maxWidth, static_cast<int>(min(maxPercent, INT_MAX / 2.0f)));
+    }
+
+    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;
+    }
+}
+
+/*
+  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()
+{
+    float tMaxWidth = 0;
+
+    unsigned int nEffCols = m_layoutStruct.size();
+    int hspacing = m_table->hBorderSpacing();
+
+    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.isZero())
+            w = Length(); // make it Auto
+
+        int col = m_table->colToEffCol(cell->col());
+        unsigned int lastCol = col;
+        int cMinWidth = cell->minPrefWidth() + hspacing;
+        float cMaxWidth = cell->maxPrefWidth() + hspacing;
+        int totalPercent = 0;
+        int minWidth = 0;
+        float maxWidth = 0;
+        bool allColsArePercent = true;
+        bool allColsAreFixed = true;
+        bool haveAuto = false;
+        bool spanHasEmptyCellsOnly = true;
+        int fixedWidth = 0;
+        while (lastCol < nEffCols && span > 0) {
+            switch (m_layoutStruct[lastCol].width.type()) {
+            case Percent:
+                totalPercent += m_layoutStruct[lastCol].width.rawValue();
+                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.rawValue();
+                allColsAreFixed = false;
+            }
+            if (!m_layoutStruct[lastCol].emptyCellsOnly)
+                spanHasEmptyCellsOnly = false;
+            span -= m_table->spanOfEffCol(lastCol);
+            minWidth += m_layoutStruct[lastCol].effMinWidth;
+            maxWidth += m_layoutStruct[lastCol].effMaxWidth;
+            lastCol++;
+            cMinWidth -= hspacing;
+            cMaxWidth -= hspacing;
+        }
+
+        // adjust table max width if needed
+        if (w.isPercent()) {
+            if (totalPercent > w.rawValue() || allColsArePercent) {
+                // can't satify this condition, treat as variable
+                w = Length();
+            } else {
+                float spanMax = max(maxWidth, cMaxWidth);
+                tMaxWidth = max(tMaxWidth, spanMax * 100 * percentScaleFactor / w.rawValue());
+
+                // all non percent columns in the span get percent vlaues to sum up correctly.
+                int percentMissing = w.rawValue() - totalPercent;
+                float totalWidth = 0;
+                for (unsigned int pos = col; pos < lastCol; pos++) {
+                    if (!(m_layoutStruct[pos].effWidth.isPercent()))
+                        totalWidth += m_layoutStruct[pos].effMaxWidth;
+                }
+
+                for (unsigned int pos = col; pos < lastCol && totalWidth > 0; pos++) {
+                    if (!(m_layoutStruct[pos].effWidth.isPercent())) {
+                        int percent = static_cast<int>(percentMissing * static_cast<float>(m_layoutStruct[pos].effMaxWidth) / totalWidth);
+                        totalWidth -= m_layoutStruct[pos].effMaxWidth;
+                        percentMissing -= percent;
+                        if (percent > 0)
+                            m_layoutStruct[pos].effWidth.setRawValue(Percent, percent);
+                        else
+                            m_layoutStruct[pos].effWidth = Length();
+                    }
+                }
+
+            }
+        }
+
+        // make sure minWidth and maxWidth of the spanning cell are honoured
+        if (cMinWidth > minWidth) {
+            if (allColsAreFixed) {
+                for (unsigned int pos = col; fixedWidth > 0 && pos < lastCol; pos++) {
+                    int w = max(m_layoutStruct[pos].effMinWidth, cMinWidth * m_layoutStruct[pos].width.value() / fixedWidth);
+                    fixedWidth -= m_layoutStruct[pos].width.value();
+                    cMinWidth -= w;
+                    m_layoutStruct[pos].effMinWidth = w;
+                }
+
+            } else {
+                float 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;
+                        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, static_cast<int>(maxw ? cMinWidth * static_cast<float>(m_layoutStruct[pos].effMaxWidth) / maxw : cMinWidth));
+                        w = min(m_layoutStruct[pos].effMinWidth+(cMinWidth-minw), w);
+                                                
+                        maxw -= m_layoutStruct[pos].effMaxWidth;
+                        minw -= m_layoutStruct[pos].effMinWidth;
+                        cMinWidth -= w;
+                        m_layoutStruct[pos].effMinWidth = w;
+                    }
+                }
+            }
+        }
+        if (!(w.isPercent())) {
+            if (cMaxWidth > maxWidth) {
+                for (unsigned int pos = col; maxWidth >= 0 && pos < lastCol; pos++) {
+                    int w = max(m_layoutStruct[pos].effMaxWidth, static_cast<int>(maxWidth ? cMaxWidth * static_cast<float>(m_layoutStruct[pos].effMaxWidth) / maxWidth : cMaxWidth));
+                    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);
+        }
+        // treat span ranges consisting of empty cells only as if they had content
+        if (spanHasEmptyCellsOnly)
+            for (unsigned int pos = col; pos < lastCol; pos++)
+                m_layoutStruct[pos].emptyCellsOnly = false;
+    }
+    m_effWidthDirty = false;
+
+    return static_cast<int>(min(tMaxWidth, INT_MAX / 2.0f));
+}
+
+/* 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.grow(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()
+{
+#ifdef ANDROID_LAYOUT    
+    if (m_table->isSingleColumn())
+        return;
+#endif        
+    // 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();
+    }
+
+    if (m_effWidthDirty)
+        calcEffectiveWidth();
+
+    bool havePercent = false;
+    bool haveRelative = false;
+    int totalRelative = 0;
+    int numAuto = 0;
+    int numFixed = 0;
+    float totalAuto = 0;
+    float totalFixed = 0;
+    int totalPercent = 0;
+    int allocAuto = 0;
+    int numAutoEmptyCellsOnly = 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.rawValue();
+            break;
+        case Relative:
+            haveRelative = true;
+            totalRelative += width.value();
+            break;
+        case Fixed:
+            numFixed++;
+            totalFixed += m_layoutStruct[i].effMaxWidth;
+            // fall through
+            break;
+        case Auto:
+        case Static:
+            if (m_layoutStruct[i].emptyCellsOnly) 
+                numAutoEmptyCellsOnly++;            
+            else {
+                numAuto++;
+                totalAuto += m_layoutStruct[i].effMaxWidth;
+                allocAuto += w;
+            }
+            break;
+        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 * percentScaleFactor) {
+            // remove overallocated space from the last columns
+            int excess = tableWidth*(totalPercent - 100 * percentScaleFactor) / (100 * percentScaleFactor);
+            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;
+                }
+            }
+        }
+    }
+    
+    // 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();
+            }
+        }
+    }
+
+    // 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 && !m_layoutStruct[i].emptyCellsOnly) {
+                int w = max(m_layoutStruct[i].calcWidth, static_cast<int>(available * static_cast<float>(m_layoutStruct[i].effMaxWidth) / totalAuto));
+                available -= w;
+                totalAuto -= m_layoutStruct[i].effMaxWidth;
+                m_layoutStruct[i].calcWidth = w;
+            }
+        }
+    }
+
+    // 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 = static_cast<int>(available * static_cast<float>(m_layoutStruct[i].effMaxWidth) / totalFixed);
+                available -= w;
+                totalFixed -= m_layoutStruct[i].effMaxWidth;
+                m_layoutStruct[i].calcWidth += w;
+            }
+        }
+    }
+
+    // spread over percent colums
+    if (available > 0 && m_hasPercent && totalPercent < 100 * percentScaleFactor) {
+        // 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.rawValue() / totalPercent;
+                available -= w;
+                totalPercent -= width.rawValue();
+                m_layoutStruct[i].calcWidth += w;
+                if (!available || !totalPercent) break;
+            }
+        }
+    }
+
+    // spread over the rest
+    if (available > 0 && nEffCols > numAutoEmptyCellsOnly) {
+        int total = nEffCols - numAutoEmptyCellsOnly;
+        // still have some width to spread
+        int i = nEffCols;
+        while (i--) {
+            // variable columns with empty cells only don't get any width
+            if (m_layoutStruct[i].effWidth.isAuto() && m_layoutStruct[i].emptyCellsOnly)
+                continue;
+            int w = available / total;
+            available -= w;
+            total--;
+            m_layoutStruct[i].calcWidth += w;
+        }
+    }
+
+    // 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++) {
+        m_table->columnPositions()[i] = pos;
+        pos += m_layoutStruct[i].calcWidth + m_table->hBorderSpacing();
+    }
+    m_table->columnPositions()[m_table->columnPositions().size() - 1] = pos;
+}
+
+
+void AutoTableLayout::calcPercentages() const
+{
+    unsigned totalPercent = 0;
+    for (unsigned i = 0; i < m_layoutStruct.size(); i++) {
+        if (m_layoutStruct[i].width.isPercent())
+            totalPercent += m_layoutStruct[i].width.rawValue();
+    }
+    m_totalPercent = totalPercent / percentScaleFactor;
+    m_percentagesDirty = false;
+}
+
+#undef DEBUG_LAYOUT
+
+}
diff --git a/WebCore/rendering/AutoTableLayout.h b/WebCore/rendering/AutoTableLayout.h
new file mode 100644
index 0000000..641a68b
--- /dev/null
+++ b/WebCore/rendering/AutoTableLayout.h
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2002 Lars Knoll ([email protected])
+ *           (C) 2002 Dirk Mueller ([email protected])
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef AutoTableLayout_h
+#define AutoTableLayout_h
+
+#include "Length.h"
+#include "TableLayout.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderTable;
+class RenderTableCell;
+
+class AutoTableLayout : public TableLayout {
+public:
+    AutoTableLayout(RenderTable*);
+    ~AutoTableLayout();
+
+    virtual void calcPrefWidths(int& minWidth, int& maxWidth);
+    virtual void layout();
+
+protected:
+    void fullRecalc();
+    void recalcColumn(int effCol);
+
+    void calcPercentages() const;
+    int totalPercent() const
+    {
+        if (m_percentagesDirty)
+            calcPercentages();
+        return m_totalPercent;
+    }
+
+    int calcEffectiveWidth();
+
+    void insertSpanCell(RenderTableCell*);
+
+    struct Layout {
+        Layout()
+            : minWidth(0)
+            , maxWidth(0)
+            , effMinWidth(0)
+            , effMaxWidth(0)
+            , calcWidth(0)
+            , emptyCellsOnly(true) {}
+        Length width;
+        Length effWidth;
+        int minWidth;
+        int maxWidth;
+        int effMinWidth;
+        int effMaxWidth;
+        int calcWidth;
+        bool emptyCellsOnly;
+    };
+
+    Vector<Layout, 4> m_layoutStruct;
+    Vector<RenderTableCell*, 4> m_spanCells;
+    bool m_hasPercent : 1;
+    mutable bool m_percentagesDirty : 1;
+    mutable bool m_effWidthDirty : 1;
+    mutable unsigned short m_totalPercent;
+};
+
+} // namespace WebCore
+
+#endif // AutoTableLayout_h
diff --git a/WebCore/rendering/CounterNode.cpp b/WebCore/rendering/CounterNode.cpp
new file mode 100644
index 0000000..c30ca9a
--- /dev/null
+++ b/WebCore/rendering/CounterNode.cpp
@@ -0,0 +1,192 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2005 Allan Sandfeld Jensen ([email protected])
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "CounterNode.h"
+
+#include "RenderObject.h"
+#include <stdio.h>
+
+// FIXME: There's currently no strategy for getting the counter tree updated when new
+// elements with counter-reset and counter-increment styles are added to the render tree.
+// Also, the code can't handle changes where an existing node needs to change into a
+// "reset" node, or from a "reset" node back to not a "reset" node. As of this writing,
+// at least some of these problems manifest as failures in the t1204-increment and
+// t1204-reset tests in the CSS 2.1 test suite.
+
+namespace WebCore {
+
+CounterNode::CounterNode(RenderObject* o, bool isReset, int value)
+    : m_isReset(isReset)
+    , m_value(value)
+    , m_countInParent(0)
+    , m_renderer(o)
+    , m_parent(0)
+    , m_previousSibling(0)
+    , m_nextSibling(0)
+    , m_firstChild(0)
+    , m_lastChild(0)
+{   
+}
+
+int CounterNode::computeCountInParent() const
+{
+    int increment = m_isReset ? 0 : m_value;
+    if (m_previousSibling)
+        return m_previousSibling->m_countInParent + increment;
+    ASSERT(m_parent->m_firstChild == this);
+    return m_parent->m_value + increment;
+}
+
+void CounterNode::recount()
+{
+    for (CounterNode* c = this; c; c = c->m_nextSibling) {
+        int oldCount = c->m_countInParent;
+        int newCount = c->computeCountInParent();
+        c->m_countInParent = newCount;
+        if (oldCount == newCount)
+            break;
+        if (c->m_renderer->isCounter())
+            c->m_renderer->setNeedsLayoutAndPrefWidthsRecalc();
+    }
+}
+
+void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild)
+{
+    ASSERT(newChild);
+    ASSERT(!newChild->m_parent);
+    ASSERT(!newChild->m_previousSibling);
+    ASSERT(!newChild->m_nextSibling);
+    ASSERT(!refChild || refChild->m_parent == this);
+
+    CounterNode* next;
+
+    if (refChild) {
+        next = refChild->m_nextSibling;
+        refChild->m_nextSibling = newChild;
+    } else {
+        next = m_firstChild;
+        m_firstChild = newChild;
+    }
+
+    if (next) {
+        ASSERT(next->m_previousSibling == refChild);
+        next->m_previousSibling = newChild;
+    } else {
+        ASSERT(m_lastChild == refChild);
+        m_lastChild = newChild;
+    }
+
+    newChild->m_parent = this;
+    newChild->m_previousSibling = refChild;
+    newChild->m_nextSibling = next;
+
+    newChild->m_countInParent = newChild->computeCountInParent();
+    if (next)
+        next->recount();
+}
+
+void CounterNode::removeChild(CounterNode* oldChild)
+{
+    ASSERT(oldChild);
+    ASSERT(!oldChild->m_firstChild);
+    ASSERT(!oldChild->m_lastChild);
+
+    CounterNode* next = oldChild->m_nextSibling;
+    CounterNode* prev = oldChild->m_previousSibling;
+
+    oldChild->m_nextSibling = 0;
+    oldChild->m_previousSibling = 0;
+    oldChild->m_parent = 0;
+
+    if (prev) 
+        prev->m_nextSibling = next;
+    else {
+        ASSERT(m_firstChild == oldChild);
+        m_firstChild = next;
+    }
+    
+    if (next)
+        next->m_previousSibling = prev;
+    else {
+        ASSERT(m_lastChild == oldChild);
+        m_lastChild = prev;
+    }
+    
+    if (next)
+        next->recount();
+}
+
+#ifndef NDEBUG
+
+static const CounterNode* nextInPreOrderAfterChildren(const CounterNode* node)
+{
+    CounterNode* next = node->nextSibling();
+    if (!next) {
+        next = node->parent();
+        while (next && !next->nextSibling())
+            next = next->parent();
+        if (next)
+            next = next->nextSibling();
+    }
+    return next;
+}
+
+static const CounterNode* nextInPreOrder(const CounterNode* node)
+{
+    if (CounterNode* child = node->firstChild())
+        return child;
+    return nextInPreOrderAfterChildren(node);
+}
+
+static void showTreeAndMark(const CounterNode* node)
+{
+    const CounterNode* root = node;
+    while (root->parent())
+        root = root->parent();
+
+    for (const CounterNode* c = root; c; c = nextInPreOrder(c)) {
+        if (c == node)
+            fprintf(stderr, "*");                        
+        for (const CounterNode* d = c; d && d != root; d = d->parent())
+            fprintf(stderr, "\t");
+        if (c->isReset())
+            fprintf(stderr, "reset: %d\n", c->value());
+        else
+            fprintf(stderr, "increment: %d\n", c->value());
+    }
+}
+
+#endif
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+
+void showTree(const WebCore::CounterNode* counter)
+{
+    if (counter)
+        showTreeAndMark(counter);
+}
+
+#endif
diff --git a/WebCore/rendering/CounterNode.h b/WebCore/rendering/CounterNode.h
new file mode 100644
index 0000000..57f9563
--- /dev/null
+++ b/WebCore/rendering/CounterNode.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2005 Allan Sandfeld Jensen ([email protected])
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+*/
+
+#ifndef CounterNode_h
+#define CounterNode_h
+
+#include <wtf/Noncopyable.h>
+
+// This implements a counter tree that is used for finding parents in counters() lookup,
+// and for propagating count changes when nodes are added or removed.
+
+// Parents represent unique counters and their scope, which are created either explicitly
+// by "counter-reset" style rules or implicitly by referring to a counter that is not in scope.
+// Such nodes are tagged as "reset" nodes, although they are not all due to "counter-reset".
+
+// Not that render tree children are often counter tree siblings due to counter scoping rules.
+
+namespace WebCore {
+
+class RenderObject;
+
+class CounterNode : Noncopyable {
+public:
+    CounterNode(RenderObject*, bool isReset, int value);
+
+    bool isReset() const { return m_isReset; }
+    int value() const { return m_value; }
+    int countInParent() const { return m_countInParent; }
+    RenderObject* renderer() const { return m_renderer; }
+
+    CounterNode* parent() const { return m_parent; }
+    CounterNode* previousSibling() const { return m_previousSibling; }
+    CounterNode* nextSibling() const { return m_nextSibling; }
+    CounterNode* firstChild() const { return m_firstChild; }
+    CounterNode* lastChild() const { return m_lastChild; }
+
+    void insertAfter(CounterNode* newChild, CounterNode* beforeChild);
+    void removeChild(CounterNode*);
+
+private:
+    int computeCountInParent() const;
+    void recount();
+
+    bool m_isReset;
+    int m_value;
+    int m_countInParent;
+    RenderObject* m_renderer;
+
+    CounterNode* m_parent;
+    CounterNode* m_previousSibling;
+    CounterNode* m_nextSibling;
+    CounterNode* m_firstChild;
+    CounterNode* m_lastChild;
+};
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showTree(const WebCore::CounterNode*);
+#endif
+
+#endif // CounterNode_h
diff --git a/WebCore/rendering/EllipsisBox.cpp b/WebCore/rendering/EllipsisBox.cpp
new file mode 100644
index 0000000..7f563d5
--- /dev/null
+++ b/WebCore/rendering/EllipsisBox.cpp
@@ -0,0 +1,85 @@
+/**
+* This file is part of the html renderer for KDE.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "EllipsisBox.h"
+
+#include "Document.h"
+#include "GraphicsContext.h"
+#include "HitTestResult.h"
+
+namespace WebCore {
+
+void EllipsisBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
+{
+    GraphicsContext* context = paintInfo.context;
+    RenderStyle* style = m_object->style(m_firstLine);
+    if (style->font() != context->font())
+        context->setFont(style->font());
+
+    Color textColor = style->color();
+    if (textColor != context->fillColor())
+        context->setFillColor(textColor);
+    bool setShadow = false;
+    if (style->textShadow()) {
+        context->setShadow(IntSize(style->textShadow()->x, style->textShadow()->y),
+                           style->textShadow()->blur, style->textShadow()->color);
+        setShadow = true;
+    }
+
+    const String& str = m_str;
+    context->drawText(TextRun(str.characters(), str.length(), false, 0, 0, false, style->visuallyOrdered()), IntPoint(m_x + tx, m_y + ty + m_baseline));
+
+    if (setShadow)
+        context->clearShadow();
+
+    if (m_markupBox) {
+        // Paint the markup box
+        tx += m_x + m_width - m_markupBox->xPos();
+        ty += m_y + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline());
+        m_markupBox->paint(paintInfo, tx, ty);
+    }
+}
+
+bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+{
+    tx += m_x;
+    ty += m_y;
+
+    // Hit test the markup box.
+    if (m_markupBox) {
+        int mtx = tx + m_width - m_markupBox->xPos();
+        int mty = ty + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline());
+        if (m_markupBox->nodeAtPoint(request, result, x, y, mtx, mty)) {
+            object()->updateHitTestResult(result, IntPoint(x - mtx, y - mty));
+            return true;
+        }
+    }
+
+    if (object()->style()->visibility() == VISIBLE && IntRect(tx, ty, m_width, m_height).contains(x, y)) {
+        object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
+        return true;
+    }
+
+    return false;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/EllipsisBox.h b/WebCore/rendering/EllipsisBox.h
new file mode 100644
index 0000000..dbb30cd
--- /dev/null
+++ b/WebCore/rendering/EllipsisBox.h
@@ -0,0 +1,53 @@
+/**
+* This file is part of the html renderer for KDE.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef EllipsisBox_h
+#define EllipsisBox_h
+
+#include "InlineBox.h"
+
+namespace WebCore {
+
+class HitTestResult;
+
+struct HitTestRequest;
+
+class EllipsisBox : public InlineBox {
+public:
+    EllipsisBox(RenderObject* obj, const AtomicString& ellipsisStr, InlineFlowBox* parent,
+                int width, int y, int height, int baseline, bool firstLine, InlineBox* markupBox)
+        : InlineBox(obj, 0, y, width, height, baseline, firstLine, true, false, false, 0, 0, parent)
+        , m_str(ellipsisStr)
+        , m_markupBox(markupBox)
+    {
+    }
+
+    virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
+
+private:
+    AtomicString m_str;
+    InlineBox* m_markupBox;
+};
+
+} // namespace WebCore
+
+#endif // EllipsisBox_h
diff --git a/WebCore/rendering/FixedTableLayout.cpp b/WebCore/rendering/FixedTableLayout.cpp
new file mode 100644
index 0000000..1dc66a9
--- /dev/null
+++ b/WebCore/rendering/FixedTableLayout.cpp
@@ -0,0 +1,309 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2002 Lars Knoll ([email protected])
+ *           (C) 2002 Dirk Mueller ([email protected])
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, 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 width, the width of the columns, and borders or cell
+  spacing.
+
+  The table's width may be specified explicitly with the '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 width of each column is
+  determined as follows:
+
+    1. A column element with a value other than 'auto' for the 'width'
+    property sets the width for that column.
+
+    2. Otherwise, a cell in the first row with a value other than
+    'auto' for the 'width' property sets the width for that column. If
+    the cell spans more than one column, the width is divided over the
+    columns.
+
+    3. Any remaining columns equally divide the remaining horizontal
+    table space (minus borders or cell spacing).
+
+  The width of the table is then the greater of the value of the
+  '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.
+*/
+
+using namespace std;
+
+namespace WebCore {
+
+FixedTableLayout::FixedTableLayout(RenderTable* table)
+    : TableLayout(table)
+{
+}
+
+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));
+
+    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();
+                
+                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.isPositive()) {
+                        m_width[cCol + i].setRawValue(w.type(), w.rawValue() * eSpan);
+                        usedWidth += effWidth * eSpan;
+                    }
+                    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;
+    }
+
+    // Iterate over the first row in case some are unspecified.
+    RenderTableSection* section = m_table->header();
+    if (!section)
+        section = m_table->firstBody();
+    if (!section)
+        section = m_table->footer();
+    if (section && !section->numRows())
+        section = m_table->sectionBelow(section, true);
+    if (section) {
+        cCol = 0;
+        RenderObject* firstRow = section->firstChild();
+        child = firstRow->firstChild();
+        while (child) {
+            if (child->isTableCell()) {
+                RenderTableCell* cell = static_cast<RenderTableCell*>(child);
+                if (cell->prefWidthsDirty())
+                    cell->calcPrefWidths();
+
+                Length w = cell->styleOrColWidth();
+                int span = cell->colSpan();
+                int effWidth = 0;
+                if (w.isFixed() && w.isPositive())
+                    effWidth = w.value();
+                
+                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].setRawValue(w.type(), w.rawValue() * eSpan / span);
+                        usedWidth += effWidth * eSpan / span;
+                    }
+                    usedSpan += eSpan;
+                    i++;
+                }
+                cCol += i;
+            }
+            child = child->nextSibling();
+        }
+    }
+
+    return usedWidth;
+}
+
+void FixedTableLayout::calcPrefWidths(int& minWidth, int& maxWidth)
+{
+    // 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 width as the sum of the
+    // cols/cells with a fixed width.
+    //
+    // The maximum 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;
+
+    minWidth = max(mw, tableWidth);
+    maxWidth = minWidth;
+}
+
+void FixedTableLayout::layout()
+{
+    int tableWidth = m_table->width() - m_table->bordersPaddingAndSpacing();
+    int nEffCols = m_table->numEffCols();
+    Vector<int> calcWidth(nEffCols, 0);
+
+    int numAuto = 0;
+    int autoSpan = 0;
+    int totalFixedWidth = 0;
+    int totalPercentWidth = 0;
+    int totalRawPercent = 0;
+
+    // Compute requirements and try to satisfy fixed and percent widths.
+    // Percentages are of the table's width, so for example
+    // for a table width of 100px with columns (40px, 10%), the 10% compute
+    // to 10px here, and will scale up to 20px in the final (80px, 20px).
+    for (int i = 0; i < nEffCols; i++) {
+        if (m_width[i].isFixed()) {
+            calcWidth[i] = m_width[i].value();
+            totalFixedWidth += calcWidth[i];
+        } else if (m_width[i].isPercent()) {
+            calcWidth[i] = m_width[i].calcValue(tableWidth);
+            totalPercentWidth += calcWidth[i];
+            totalRawPercent += m_width[i].rawValue();
+        } else if (m_width[i].isAuto()) {
+            numAuto++;
+            autoSpan += m_table->spanOfEffCol(i);
+        }
+    }
+
+    int hspacing = m_table->hBorderSpacing();
+    int totalWidth = totalFixedWidth + totalPercentWidth;
+    if (!numAuto || totalWidth > tableWidth) {
+        // If there are no auto columns, or if the total is too wide, take
+        // what we have and scale it to fit as necessary.
+        if (totalWidth != tableWidth) {
+            // Fixed widths only scale up
+            if (totalFixedWidth && totalWidth < tableWidth) {
+                totalFixedWidth = 0;
+                for (int i = 0; i < nEffCols; i++) {
+                    if (m_width[i].isFixed()) {
+                        calcWidth[i] = calcWidth[i] * tableWidth / totalWidth;
+                        totalFixedWidth += calcWidth[i];
+                    }
+                }
+            }
+            if (totalRawPercent) {
+                totalPercentWidth = 0;
+                for (int i = 0; i < nEffCols; i++) {
+                    if (m_width[i].isPercent()) {
+                        calcWidth[i] = m_width[i].rawValue() * (tableWidth - totalFixedWidth) / totalRawPercent;
+                        totalPercentWidth += calcWidth[i];
+                    }
+                }
+            }
+            totalWidth = totalFixedWidth + totalPercentWidth;
+        }
+    } else {
+        // Divide the remaining width among the auto columns.
+        int remainingWidth = tableWidth - totalFixedWidth - totalPercentWidth - hspacing * (autoSpan - numAuto);
+        int lastAuto = 0;
+        for (int i = 0; i < nEffCols; i++) {
+            if (m_width[i].isAuto()) {
+                int span = m_table->spanOfEffCol(i);
+                int w = remainingWidth * span / autoSpan;
+                calcWidth[i] = w + hspacing * (span - 1);
+                remainingWidth -= w;
+                if (!remainingWidth)
+                    break;
+                lastAuto = i;
+                numAuto--;
+                autoSpan -= span;
+            }
+        }
+        // Last one gets the remainder.
+        if (remainingWidth)
+            calcWidth[lastAuto] += remainingWidth;
+        totalWidth = tableWidth;
+    }
+
+    if (totalWidth < tableWidth) {
+        // Spread extra space over columns.
+        int remainingWidth = tableWidth - totalWidth;
+        int total = nEffCols;
+        while (total) {
+            int w = remainingWidth / total;
+            remainingWidth -= w;
+            calcWidth[--total] += w;
+        }
+        if (nEffCols > 0)
+            calcWidth[nEffCols - 1] += remainingWidth;
+    }
+    
+    int pos = 0;
+    for (int i = 0; i < nEffCols; i++) {
+        m_table->columnPositions()[i] = pos;
+        pos += calcWidth[i] + hspacing;
+    }
+    int colPositionsSize = m_table->columnPositions().size();
+    if (colPositionsSize > 0)
+        m_table->columnPositions()[colPositionsSize - 1] = pos;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/FixedTableLayout.h b/WebCore/rendering/FixedTableLayout.h
new file mode 100644
index 0000000..ed7c089
--- /dev/null
+++ b/WebCore/rendering/FixedTableLayout.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2002 Lars Knoll ([email protected])
+ *           (C) 2002 Dirk Mueller ([email protected])
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef FixedTableLayout_h
+#define FixedTableLayout_h
+
+#include "Length.h"
+#include "TableLayout.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderTable;
+
+class FixedTableLayout : public TableLayout {
+public:
+    FixedTableLayout(RenderTable*);
+
+    virtual void calcPrefWidths(int& minWidth, int& maxWidth);
+    virtual void layout();
+
+protected:
+    int calcWidthArray(int tableWidth);
+
+    Vector<Length> m_width;
+};
+
+} // namespace WebCore
+
+#endif // FixedTableLayout_h
diff --git a/WebCore/rendering/GapRects.h b/WebCore/rendering/GapRects.h
new file mode 100644
index 0000000..bf53d70
--- /dev/null
+++ b/WebCore/rendering/GapRects.h
@@ -0,0 +1,64 @@
+/*
+    This file is part of the KDE libraries
+
+    Copyright (C) 2005, 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, or (at your option) any later version.
+
+    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., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+
+
+    Some useful definitions needed for laying out elements
+*/
+
+#ifndef GapRects_h
+#define GapRects_h
+
+#include "IntRect.h"
+
+namespace WebCore {
+
+    struct GapRects {
+        const IntRect& left() const { return m_left; }
+        const IntRect& center() const { return m_center; }
+        const IntRect& right() const { return m_right; }
+        
+        void uniteLeft(const IntRect& r) { m_left.unite(r); }
+        void uniteCenter(const IntRect& r) { m_center.unite(r); }
+        void uniteRight(const IntRect& r) { m_right.unite(r); }
+        void unite(const GapRects& o) { uniteLeft(o.left()); uniteCenter(o.center()); uniteRight(o.right()); }
+
+        operator IntRect() const
+        {
+            IntRect result = m_left;
+            result.unite(m_center);
+            result.unite(m_right);
+            return result;
+        }
+
+        bool operator==(const GapRects& other)
+        {
+            return m_left == other.left() && m_center == other.center() && m_right == other.right();
+        }
+        bool operator!=(const GapRects& other) { return !(*this == other); }
+
+    private:
+        IntRect m_left;
+        IntRect m_center;
+        IntRect m_right;
+    };
+
+} // namespace WebCore
+
+#endif // GapRects_h
diff --git a/WebCore/rendering/HitTestRequest.h b/WebCore/rendering/HitTestRequest.h
new file mode 100644
index 0000000..11dca4b
--- /dev/null
+++ b/WebCore/rendering/HitTestRequest.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+*/
+#ifndef HitTestRequest_h
+#define HitTestRequest_h
+
+namespace WebCore {
+
+struct HitTestRequest {
+    HitTestRequest(bool r, bool a, bool m = false, bool u = false)
+        : readonly(r)
+        , active(a)
+        , mouseMove(m)
+        , mouseUp(u)
+    { 
+    }
+
+    bool readonly;
+    bool active;
+    bool mouseMove;
+    bool mouseUp;
+};
+
+} // namespace WebCore
+
+#endif // HitTestRequest_h
diff --git a/WebCore/rendering/HitTestResult.cpp b/WebCore/rendering/HitTestResult.cpp
new file mode 100644
index 0000000..53b376d
--- /dev/null
+++ b/WebCore/rendering/HitTestResult.cpp
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+*/
+
+#include "config.h"
+#include "HitTestResult.h"
+
+#include "Frame.h"
+#include "FrameTree.h"
+#include "HTMLAnchorElement.h"
+#include "HTMLImageElement.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "RenderImage.h"
+#include "Scrollbar.h"
+#include "SelectionController.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "XLinkNames.h"
+#endif
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+HitTestResult::HitTestResult(const IntPoint& point)
+    : m_point(point)
+    , m_isOverWidget(false)
+{
+}
+
+HitTestResult::HitTestResult(const HitTestResult& other)
+    : m_innerNode(other.innerNode())
+    , m_innerNonSharedNode(other.innerNonSharedNode())
+    , m_point(other.point())
+    , m_localPoint(other.localPoint())
+    , m_innerURLElement(other.URLElement())
+    , m_scrollbar(other.scrollbar())
+    , m_isOverWidget(other.isOverWidget())
+{
+}
+
+HitTestResult::~HitTestResult()
+{
+}
+
+HitTestResult& HitTestResult::operator=(const HitTestResult& other)
+{
+    m_innerNode = other.innerNode();
+    m_innerNonSharedNode = other.innerNonSharedNode();
+    m_point = other.point();
+    m_localPoint = other.localPoint();
+    m_innerURLElement = other.URLElement();
+    m_scrollbar = other.scrollbar();
+    m_isOverWidget = other.isOverWidget();
+    return *this;
+}
+
+void HitTestResult::setToNonShadowAncestor()
+{
+    Node* node = innerNode();
+    if (node)
+        node = node->shadowAncestorNode();
+    setInnerNode(node);
+    node = innerNonSharedNode();
+    if (node)
+        node = node->shadowAncestorNode();
+    setInnerNonSharedNode(node);
+}
+
+void HitTestResult::setInnerNode(Node* n)
+{
+    m_innerNode = n;
+}
+    
+void HitTestResult::setInnerNonSharedNode(Node* n)
+{
+    m_innerNonSharedNode = n;
+}
+
+void HitTestResult::setURLElement(Element* n) 
+{ 
+    m_innerURLElement = n; 
+}
+
+void HitTestResult::setScrollbar(Scrollbar* s)
+{
+    m_scrollbar = s;
+}
+
+Frame* HitTestResult::targetFrame() const
+{
+    if (!m_innerURLElement)
+        return 0;
+
+    Frame* frame = m_innerURLElement->document()->frame();
+    if (!frame)
+        return 0;
+
+    return frame->tree()->find(m_innerURLElement->target());
+}
+
+IntRect HitTestResult::boundingBox() const
+{
+    if (m_innerNonSharedNode) {
+        RenderObject* renderer = m_innerNonSharedNode->renderer();
+        if (renderer)
+            return renderer->absoluteBoundingBoxRect();
+    }
+    
+    return IntRect();
+}
+
+bool HitTestResult::isSelected() const
+{
+    if (!m_innerNonSharedNode)
+        return false;
+
+    Frame* frame = m_innerNonSharedNode->document()->frame();
+    if (!frame)
+        return false;
+
+    return frame->selection()->contains(m_point);
+}
+
+String HitTestResult::spellingToolTip() const
+{
+    // Return the tool tip string associated with this point, if any. Only markers associated with bad grammar
+    // currently supply strings, but maybe someday markers associated with misspelled words will also.
+    if (!m_innerNonSharedNode)
+        return String();
+    
+     DocumentMarker* marker = m_innerNonSharedNode->document()->markerContainingPoint(m_point, DocumentMarker::Grammar);
+    if (!marker)
+        return String();
+
+    return marker->description;
+}
+
+String HitTestResult::title() const
+{
+    // Find the title in the nearest enclosing DOM node.
+    // For <area> tags in image maps, walk the tree for the <area>, not the <img> using it.
+    for (Node* titleNode = m_innerNode.get(); titleNode; titleNode = titleNode->parentNode()) {
+        if (titleNode->isElementNode()) {
+            String title = static_cast<Element*>(titleNode)->title();
+            if (!title.isEmpty())
+                return title;
+        }
+    }
+    return String();
+}
+
+String displayString(const String& string, const Node* node)
+{
+    if (!node)
+        return string;
+    String copy(string);
+    copy.replace('\\', node->document()->backslashAsCurrencySymbol());
+    return copy;
+}
+
+String HitTestResult::altDisplayString() const
+{
+    if (!m_innerNonSharedNode)
+        return String();
+    
+    if (m_innerNonSharedNode->hasTagName(imgTag)) {
+        HTMLImageElement* image = static_cast<HTMLImageElement*>(m_innerNonSharedNode.get());
+        return displayString(image->alt(), m_innerNonSharedNode.get());
+    }
+    
+    if (m_innerNonSharedNode->hasTagName(inputTag)) {
+        HTMLInputElement* input = static_cast<HTMLInputElement*>(m_innerNonSharedNode.get());
+        return displayString(input->alt(), m_innerNonSharedNode.get());
+    }
+    
+    return String();
+}
+
+Image* HitTestResult::image() const
+{
+    if (!m_innerNonSharedNode)
+        return 0;
+    
+    RenderObject* renderer = m_innerNonSharedNode->renderer();
+    if (renderer && renderer->isImage()) {
+        RenderImage* image = static_cast<WebCore::RenderImage*>(renderer);
+        if (image->cachedImage() && !image->cachedImage()->errorOccurred())
+            return image->cachedImage()->image();
+    }
+
+    return 0;
+}
+
+IntRect HitTestResult::imageRect() const
+{
+    if (!image())
+        return IntRect();
+    return m_innerNonSharedNode->renderer()->absoluteContentBox();
+}
+
+KURL HitTestResult::absoluteImageURL() const
+{
+    if (!(m_innerNonSharedNode && m_innerNonSharedNode->document()))
+        return KURL();
+
+    if (!(m_innerNonSharedNode->renderer() && m_innerNonSharedNode->renderer()->isImage()))
+        return KURL();
+
+    AtomicString urlString;
+    if (m_innerNonSharedNode->hasTagName(imgTag) || m_innerNonSharedNode->hasTagName(inputTag))
+        urlString = static_cast<Element*>(m_innerNonSharedNode.get())->getAttribute(srcAttr);
+#if ENABLE(SVG)
+    else if (m_innerNonSharedNode->hasTagName(SVGNames::imageTag))
+        urlString = static_cast<Element*>(m_innerNonSharedNode.get())->getAttribute(XLinkNames::hrefAttr);
+#endif
+    else if (m_innerNonSharedNode->hasTagName(embedTag) || m_innerNonSharedNode->hasTagName(objectTag)) {
+        Element* element = static_cast<Element*>(m_innerNonSharedNode.get());
+        urlString = element->getAttribute(element->imageSourceAttributeName());
+    } else
+        return KURL();
+    
+    return m_innerNonSharedNode->document()->completeURL(parseURL(urlString));
+}
+
+KURL HitTestResult::absoluteLinkURL() const
+{
+    if (!(m_innerURLElement && m_innerURLElement->document()))
+        return KURL();
+
+    AtomicString urlString;
+    if (m_innerURLElement->hasTagName(aTag) || m_innerURLElement->hasTagName(areaTag) || m_innerURLElement->hasTagName(linkTag))
+        urlString = m_innerURLElement->getAttribute(hrefAttr);
+#if ENABLE(SVG)
+    else if (m_innerURLElement->hasTagName(SVGNames::aTag))
+        urlString = m_innerURLElement->getAttribute(XLinkNames::hrefAttr);
+#endif
+    else
+        return KURL();
+
+    return m_innerURLElement->document()->completeURL(parseURL(urlString));
+}
+
+bool HitTestResult::isLiveLink() const
+{
+    if (!(m_innerURLElement && m_innerURLElement->document()))
+        return false;
+
+    if (m_innerURLElement->hasTagName(aTag))
+        return static_cast<HTMLAnchorElement*>(m_innerURLElement.get())->isLiveLink();
+#if ENABLE(SVG)
+    if (m_innerURLElement->hasTagName(SVGNames::aTag))
+        return m_innerURLElement->isLink();
+#endif
+    
+    return false;
+}
+
+String HitTestResult::titleDisplayString() const
+{
+    if (!m_innerURLElement)
+        return String();
+    
+    return displayString(m_innerURLElement->title(), m_innerURLElement.get());
+}
+
+String HitTestResult::textContent() const
+{
+    if (!m_innerURLElement)
+        return String();
+    return m_innerURLElement->textContent();
+}
+
+// FIXME: This function needs a better name and may belong in a different class. It's not
+// really isContentEditable(); it's more like needsEditingContextMenu(). In many ways, this
+// function would make more sense in the ContextMenu class, except that WebElementDictionary 
+// hooks into it. Anyway, we should architect this better. 
+bool HitTestResult::isContentEditable() const
+{
+    if (!m_innerNonSharedNode)
+        return false;
+
+    if (m_innerNonSharedNode->hasTagName(textareaTag) || m_innerNonSharedNode->hasTagName(isindexTag))
+        return true;
+
+    if (m_innerNonSharedNode->hasTagName(inputTag))
+        return static_cast<HTMLInputElement*>(m_innerNonSharedNode.get())->isTextField();
+
+    return m_innerNonSharedNode->isContentEditable();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/HitTestResult.h b/WebCore/rendering/HitTestResult.h
new file mode 100644
index 0000000..5ed9b34
--- /dev/null
+++ b/WebCore/rendering/HitTestResult.h
@@ -0,0 +1,94 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+*/
+#ifndef HitTestResult_h
+#define HitTestResult_h
+
+#include "IntPoint.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Element;
+class Frame;
+class Image;
+class KURL;
+class IntRect;
+class Node;
+class Scrollbar;
+class String;
+
+class HitTestResult {
+public:
+    HitTestResult(const IntPoint&);
+    HitTestResult(const HitTestResult&);
+    ~HitTestResult();
+    HitTestResult& operator=(const HitTestResult&);
+
+    Node* innerNode() const { return m_innerNode.get(); }
+    Node* innerNonSharedNode() const { return m_innerNonSharedNode.get(); }
+    IntPoint point() const { return m_point; }
+    IntPoint localPoint() const { return m_localPoint; }
+    Element* URLElement() const { return m_innerURLElement.get(); }
+    Scrollbar* scrollbar() const { return m_scrollbar.get(); }
+    bool isOverWidget() const { return m_isOverWidget; }
+
+    void setToNonShadowAncestor();
+
+    void setInnerNode(Node*);
+    void setInnerNonSharedNode(Node*);
+    void setPoint(const IntPoint& p) { m_point = p; }
+    void setLocalPoint(const IntPoint& p) { m_localPoint = p; }
+    void setURLElement(Element*);
+    void setScrollbar(Scrollbar*);
+    void setIsOverWidget(bool b) { m_isOverWidget = b; }
+
+    Frame* targetFrame() const;
+    IntRect boundingBox() const;
+    bool isSelected() const;
+    String spellingToolTip() const;
+    String title() const;
+    String altDisplayString() const;
+    String titleDisplayString() const;
+    Image* image() const;
+    IntRect imageRect() const;
+    KURL absoluteImageURL() const;
+    KURL absoluteLinkURL() const;
+    String textContent() const;
+    bool isLiveLink() const;
+    bool isContentEditable() const;
+
+private:
+    RefPtr<Node> m_innerNode;
+    RefPtr<Node> m_innerNonSharedNode;
+    IntPoint m_point;
+    IntPoint m_localPoint; // A point in the local coordinate space of m_innerNonSharedNode's renderer.  Allows us to efficiently
+                           // determine where inside the renderer we hit on subsequent operations.
+    RefPtr<Element> m_innerURLElement;
+    RefPtr<Scrollbar> m_scrollbar;
+    bool m_isOverWidget; // Returns true if we are over a widget (and not in the border/padding area of a RenderWidget for example).
+};
+
+String displayString(const String&, const Node*);
+
+} // namespace WebCore
+
+#endif // HitTestResult_h
diff --git a/WebCore/rendering/InlineBox.cpp b/WebCore/rendering/InlineBox.cpp
new file mode 100644
index 0000000..5dc1f47
--- /dev/null
+++ b/WebCore/rendering/InlineBox.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "InlineBox.h"
+
+#include "HitTestResult.h"
+#include "InlineFlowBox.h"
+#include "RenderArena.h"
+#include "RootInlineBox.h"
+
+using namespace std;
+
+namespace WebCore {
+    
+#ifndef NDEBUG
+static bool inInlineBoxDetach;
+#endif
+
+#ifndef NDEBUG
+
+InlineBox::~InlineBox()
+{
+    if (!m_hasBadParent && m_parent)
+        m_parent->setHasBadChildList();
+}
+
+#endif
+
+void InlineBox::remove()
+{ 
+    if (parent())
+        parent()->removeChild(this);
+}
+
+void InlineBox::destroy(RenderArena* renderArena)
+{
+#ifndef NDEBUG
+    inInlineBoxDetach = true;
+#endif
+    delete this;
+#ifndef NDEBUG
+    inInlineBoxDetach = false;
+#endif
+
+    // Recover the size left there for us by operator delete and free the memory.
+    renderArena->free(*(size_t *)this, this);
+}
+
+void* InlineBox::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void InlineBox::operator delete(void* ptr, size_t sz)
+{
+    ASSERT(inInlineBoxDetach);
+
+    // Stash size where destroy can find it.
+    *(size_t *)ptr = sz;
+}
+
+#ifndef NDEBUG
+void InlineBox::showTreeForThis() const
+{
+    if (m_object)
+        m_object->showTreeForThis();
+}
+#endif
+
+int InlineBox::caretMinOffset() const 
+{ 
+    return m_object->caretMinOffset(); 
+}
+
+int InlineBox::caretMaxOffset() const 
+{ 
+    return m_object->caretMaxOffset(); 
+}
+
+unsigned InlineBox::caretMaxRenderedOffset() const 
+{ 
+    return 1; 
+}
+
+void InlineBox::dirtyLineBoxes()
+{
+    markDirty();
+    for (InlineFlowBox* curr = parent(); curr && !curr->isDirty(); curr = curr->parent())
+        curr->markDirty();
+}
+
+void InlineBox::deleteLine(RenderArena* arena)
+{
+    if (!m_extracted)
+        m_object->setInlineBoxWrapper(0);
+    destroy(arena);
+}
+
+void InlineBox::extractLine()
+{
+    m_extracted = true;
+    m_object->setInlineBoxWrapper(0);
+}
+
+void InlineBox::attachLine()
+{
+    m_extracted = false;
+    m_object->setInlineBoxWrapper(this);
+}
+
+void InlineBox::adjustPosition(int dx, int dy)
+{
+    m_x += dx;
+    m_y += dy;
+    if (m_object->isReplaced() || m_object->isBR())
+        m_object->setPos(m_object->xPos() + dx, m_object->yPos() + dy);
+}
+
+void InlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
+{
+    if (!object()->shouldPaintWithinRoot(paintInfo) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
+        return;
+
+    // Paint all phases of replaced elements atomically, as though the replaced element established its
+    // own stacking context.  (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
+    // specification.)
+    bool preservePhase = paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip;
+    RenderObject::PaintInfo info(paintInfo);
+    info.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
+    object()->paint(info, tx, ty);
+    if (!preservePhase) {
+        info.phase = PaintPhaseChildBlockBackgrounds;
+        object()->paint(info, tx, ty);
+        info.phase = PaintPhaseFloat;
+        object()->paint(info, tx, ty);
+        info.phase = PaintPhaseForeground;
+        object()->paint(info, tx, ty);
+        info.phase = PaintPhaseOutline;
+        object()->paint(info, tx, ty);
+    }
+}
+
+bool InlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+{
+    // Hit test all phases of replaced elements atomically, as though the replaced element established its
+    // own stacking context.  (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
+    // specification.)
+    return object()->hitTest(request, result, IntPoint(x, y), tx, ty);
+}
+
+RootInlineBox* InlineBox::root()
+{ 
+    if (m_parent)
+        return m_parent->root(); 
+    ASSERT(isRootInlineBox());
+    return static_cast<RootInlineBox*>(this);
+}
+
+bool InlineBox::nextOnLineExists() const
+{
+    if (!m_determinedIfNextOnLineExists) {
+        m_determinedIfNextOnLineExists = true;
+
+        if (!parent())
+            m_nextOnLineExists = false;
+        else if (nextOnLine())
+            m_nextOnLineExists = true;
+        else
+            m_nextOnLineExists = parent()->nextOnLineExists();
+    }
+    return m_nextOnLineExists;
+}
+
+bool InlineBox::prevOnLineExists() const
+{
+    if (!m_determinedIfPrevOnLineExists) {
+        m_determinedIfPrevOnLineExists = true;
+        
+        if (!parent())
+            m_prevOnLineExists = false;
+        else if (prevOnLine())
+            m_prevOnLineExists = true;
+        else
+            m_prevOnLineExists = parent()->prevOnLineExists();
+    }
+    return m_prevOnLineExists;
+}
+
+InlineBox* InlineBox::firstLeafChild()
+{
+    return this;
+}
+
+InlineBox* InlineBox::lastLeafChild()
+{
+    return this;
+}
+
+InlineBox* InlineBox::nextLeafChild()
+{
+    return parent() ? parent()->firstLeafChildAfterBox(this) : 0;
+}
+
+InlineBox* InlineBox::prevLeafChild()
+{
+    return parent() ? parent()->lastLeafChildBeforeBox(this) : 0;
+}
+
+RenderObject::SelectionState InlineBox::selectionState()
+{
+    return object()->selectionState();
+}
+
+bool InlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth)
+{
+    // Non-replaced elements can always accommodate an ellipsis.
+    if (!m_object || !m_object->isReplaced())
+        return true;
+    
+    IntRect boxRect(m_x, 0, m_width, 10);
+    IntRect ellipsisRect(ltr ? blockEdge - ellipsisWidth : blockEdge, 0, ellipsisWidth, 10);
+    return !(boxRect.intersects(ellipsisRect));
+}
+
+int InlineBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&)
+{
+    // Use -1 to mean "we didn't set the position."
+    return -1;
+}
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+
+void showTree(const WebCore::InlineBox* b)
+{
+    if (b)
+        b->showTreeForThis();
+}
+
+#endif
diff --git a/WebCore/rendering/InlineBox.h b/WebCore/rendering/InlineBox.h
new file mode 100644
index 0000000..48aab77
--- /dev/null
+++ b/WebCore/rendering/InlineBox.h
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef InlineBox_h
+#define InlineBox_h
+
+#include "RenderObject.h" // needed for RenderObject::PaintInfo
+#include "TextDirection.h"
+
+namespace WebCore {
+
+class HitTestResult;
+class RootInlineBox;
+
+struct HitTestRequest;
+
+// InlineBox represents a rectangle that occurs on a line.  It corresponds to
+// some RenderObject (i.e., it represents a portion of that RenderObject).
+class InlineBox {
+public:
+    InlineBox(RenderObject* obj)
+        : m_object(obj)
+        , m_x(0)
+        , m_y(0)
+        , m_width(0)
+        , m_height(0)
+        , m_baseline(0)
+        , m_next(0)
+        , m_prev(0)
+        , m_parent(0)
+        , m_firstLine(false)
+        , m_constructed(false)
+        , m_bidiEmbeddingLevel(0)
+        , m_dirty(false)
+        , m_extracted(false)
+        , m_includeLeftEdge(false)
+        , m_includeRightEdge(false)
+        , m_hasTextChildren(true)
+        , m_endsWithBreak(false)
+        , m_hasSelectedChildren(false)
+        , m_hasEllipsisBox(false)
+        , m_dirOverride(false)
+        , m_treatAsText(true)
+        , m_determinedIfNextOnLineExists(false)
+        , m_determinedIfPrevOnLineExists(false)
+        , m_nextOnLineExists(false)
+        , m_prevOnLineExists(false)
+        , m_toAdd(0)
+#ifndef NDEBUG
+        , m_hasBadParent(false)
+#endif
+    {
+    }
+
+    InlineBox(RenderObject* obj, int x, int y, int width, int height, int baseline, bool firstLine, bool constructed,
+              bool dirty, bool extracted, InlineBox* next, InlineBox* prev, InlineFlowBox* parent)
+        : m_object(obj)
+        , m_x(x)
+        , m_y(y)
+        , m_width(width)
+        , m_height(height)
+        , m_baseline(baseline)
+        , m_next(next)
+        , m_prev(prev)
+        , m_parent(parent)
+        , m_firstLine(firstLine)
+        , m_constructed(constructed)
+        , m_bidiEmbeddingLevel(0)
+        , m_dirty(dirty)
+        , m_extracted(extracted)
+        , m_includeLeftEdge(false)
+        , m_includeRightEdge(false)
+        , m_hasTextChildren(true)
+        , m_endsWithBreak(false)
+        , m_hasSelectedChildren(false)   
+        , m_hasEllipsisBox(false)
+        , m_dirOverride(false)
+        , m_treatAsText(true)
+        , m_determinedIfNextOnLineExists(false)
+        , m_determinedIfPrevOnLineExists(false)
+        , m_nextOnLineExists(false)
+        , m_prevOnLineExists(false)
+        , m_toAdd(0)
+#ifndef NDEBUG
+        , m_hasBadParent(false)
+#endif
+    {
+    }
+
+    virtual ~InlineBox();
+
+    virtual void destroy(RenderArena*);
+
+    virtual void deleteLine(RenderArena*);
+    virtual void extractLine();
+    virtual void attachLine();
+
+    virtual bool isLineBreak() const { return false; }
+
+    virtual void adjustPosition(int dx, int dy);
+
+    virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
+
+    // Overloaded new operator.
+    void* operator new(size_t, RenderArena*) throw();
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void*, size_t);
+
+private:
+    // The normal operator new is disallowed.
+    void* operator new(size_t) throw();
+
+public:
+#ifndef NDEBUG
+    void showTreeForThis() const;
+#endif
+    virtual bool isInlineBox() { return false; }
+    virtual bool isInlineFlowBox() { return false; }
+    virtual bool isContainer() { return false; }
+    virtual bool isInlineTextBox() { return false; }
+    virtual bool isRootInlineBox() { return false; }
+#if ENABLE(SVG) 
+    virtual bool isSVGRootInlineBox() { return false; }
+#endif
+    virtual bool isText() const { return false; }
+
+    bool isConstructed() { return m_constructed; }
+    virtual void setConstructed()
+    {
+        m_constructed = true;
+        if (m_next)
+            m_next->setConstructed();
+    }
+
+    void setExtracted(bool b = true) { m_extracted = b; }
+    
+    void setFirstLineStyleBit(bool f) { m_firstLine = f; }
+    bool isFirstLineStyle() const { return m_firstLine; }
+
+    void remove();
+
+    InlineBox* nextOnLine() const { return m_next; }
+    InlineBox* prevOnLine() const { return m_prev; }
+    void setNextOnLine(InlineBox* next)
+    {
+        ASSERT(m_parent || !next);
+        m_next = next;
+    }
+    void setPrevOnLine(InlineBox* prev)
+    {
+        ASSERT(m_parent || !prev);
+        m_prev = prev;
+    }
+    bool nextOnLineExists() const;
+    bool prevOnLineExists() const;
+
+    virtual InlineBox* firstLeafChild();
+    virtual InlineBox* lastLeafChild();
+    InlineBox* nextLeafChild();
+    InlineBox* prevLeafChild();
+        
+    RenderObject* object() const { return m_object; }
+
+    InlineFlowBox* parent() const
+    {
+        ASSERT(!m_hasBadParent);
+        return m_parent;
+    }
+    void setParent(InlineFlowBox* par) { m_parent = par; }
+
+    RootInlineBox* root();
+    
+    void setWidth(int w) { m_width = w; }
+    int width() const { return m_width; }
+
+    void setXPos(int x) { m_x = x; }
+    int xPos() const { return m_x; }
+
+    void setYPos(int y) { m_y = y; }
+    int yPos() const { return m_y; }
+
+    void setHeight(int h) { m_height = h; }
+    int height() const { return m_height; }
+    
+    void setBaseline(int b) { m_baseline = b; }
+    int baseline() const { return m_baseline; }
+
+    bool hasTextChildren() const { return m_hasTextChildren; }
+
+    virtual int topOverflow() { return yPos(); }
+    virtual int bottomOverflow() { return yPos() + height(); }
+    virtual int leftOverflow() { return xPos(); }
+    virtual int rightOverflow() { return xPos() + width(); }
+
+    virtual int caretMinOffset() const;
+    virtual int caretMaxOffset() const;
+    virtual unsigned caretMaxRenderedOffset() const;
+
+    unsigned char bidiLevel() const { return m_bidiEmbeddingLevel; }
+    void setBidiLevel(unsigned char level) { m_bidiEmbeddingLevel = level; }
+    TextDirection direction() const { return m_bidiEmbeddingLevel % 2 ? RTL : LTR; }
+    int caretLeftmostOffset() const { return direction() == LTR ? caretMinOffset() : caretMaxOffset(); }
+    int caretRightmostOffset() const { return direction() == LTR ? caretMaxOffset() : caretMinOffset(); }
+
+    virtual void clearTruncation() { }
+
+    bool isDirty() const { return m_dirty; }
+    void markDirty(bool dirty = true) { m_dirty = dirty; }
+
+    void dirtyLineBoxes();
+    
+    virtual RenderObject::SelectionState selectionState();
+
+    virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth);
+    virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&);
+
+    void setHasBadParent();
+
+    int toAdd() const { return m_toAdd; }
+    
+public:
+    RenderObject* m_object;
+
+    int m_x;
+    int m_y;
+    int m_width;
+    int m_height;
+    int m_baseline;
+
+private:
+    InlineBox* m_next; // The next element on the same line as us.
+    InlineBox* m_prev; // The previous element on the same line as us.
+
+    InlineFlowBox* m_parent; // The box that contains us.
+    
+    // Some of these bits are actually for subclasses and moved here to compact the structures.
+
+    // for this class
+protected:
+    bool m_firstLine : 1;
+private:
+    bool m_constructed : 1;
+    unsigned char m_bidiEmbeddingLevel : 6;
+protected:
+    bool m_dirty : 1;
+    bool m_extracted : 1;
+
+    // for InlineFlowBox
+    bool m_includeLeftEdge : 1;
+    bool m_includeRightEdge : 1;
+    bool m_hasTextChildren : 1;
+
+    // for RootInlineBox
+    bool m_endsWithBreak : 1;  // Whether the line ends with a <br>.
+    bool m_hasSelectedChildren : 1; // Whether we have any children selected (this bit will also be set if the <br> that terminates our line is selected).
+    bool m_hasEllipsisBox : 1; 
+
+    // for InlineTextBox
+public:
+    bool m_dirOverride : 1;
+    bool m_treatAsText : 1; // Whether or not to treat a <br> as text for the purposes of line height.
+protected:
+    mutable bool m_determinedIfNextOnLineExists : 1;
+    mutable bool m_determinedIfPrevOnLineExists : 1;
+    mutable bool m_nextOnLineExists : 1;
+    mutable bool m_prevOnLineExists : 1;
+    int m_toAdd : 13; // for justified text
+
+#ifndef NDEBUG
+private:
+    bool m_hasBadParent;
+#endif
+};
+
+#ifdef NDEBUG
+inline InlineBox::~InlineBox()
+{
+}
+#endif
+
+inline void InlineBox::setHasBadParent()
+{
+#ifndef NDEBUG
+    m_hasBadParent = true;
+#endif
+}
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showTree(const WebCore::InlineBox*);
+#endif
+
+#endif // InlineBox_h
diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp
new file mode 100644
index 0000000..5f37ad6
--- /dev/null
+++ b/WebCore/rendering/InlineFlowBox.cpp
@@ -0,0 +1,1064 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "InlineFlowBox.h"
+
+#include "CachedImage.h"
+#include "Document.h"
+#include "EllipsisBox.h"
+#include "GraphicsContext.h"
+#include "InlineTextBox.h"
+#include "HitTestResult.h"
+#include "RootInlineBox.h"
+#include "RenderBlock.h"
+#include "RenderFlow.h"
+#include "RenderListMarker.h"
+#include "RenderTableCell.h"
+#include "RootInlineBox.h"
+#include "Text.h"
+
+#include <math.h>
+
+using namespace std;
+
+namespace WebCore {
+
+#ifndef NDEBUG
+
+InlineFlowBox::~InlineFlowBox()
+{
+    if (!m_hasBadChildList)
+        for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+            child->setHasBadParent();
+}
+
+#endif
+
+RenderFlow* InlineFlowBox::flowObject()
+{
+    return static_cast<RenderFlow*>(m_object);
+}
+
+int InlineFlowBox::marginLeft()
+{
+    if (!includeLeftEdge())
+        return 0;
+    
+    Length margin = object()->style()->marginLeft();
+    if (margin.isAuto())
+        return 0;
+    if (margin.isFixed())
+        return margin.value();
+    return object()->marginLeft();
+}
+
+int InlineFlowBox::marginRight()
+{
+    if (!includeRightEdge())
+        return 0;
+    
+    Length margin = object()->style()->marginRight();
+    if (margin.isAuto())
+        return 0;
+    if (margin.isFixed())
+        return margin.value();
+    return object()->marginRight();
+}
+
+int InlineFlowBox::marginBorderPaddingLeft()
+{
+    return marginLeft() + borderLeft() + paddingLeft();
+}
+
+int InlineFlowBox::marginBorderPaddingRight()
+{
+    return marginRight() + borderRight() + paddingRight();
+}
+
+int InlineFlowBox::getFlowSpacingWidth()
+{
+    int totWidth = marginBorderPaddingLeft() + marginBorderPaddingRight();
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->isInlineFlowBox())
+            totWidth += static_cast<InlineFlowBox*>(curr)->getFlowSpacingWidth();
+    }
+    return totWidth;
+}
+
+void InlineFlowBox::addToLine(InlineBox* child) 
+{
+    ASSERT(!child->parent());
+    ASSERT(!child->nextOnLine());
+    ASSERT(!child->prevOnLine());
+    checkConsistency();
+
+    child->setParent(this);
+    if (!m_firstChild) {
+        m_firstChild = child;
+        m_lastChild = child;
+    } else {
+        m_lastChild->setNextOnLine(child);
+        child->setPrevOnLine(m_lastChild);
+        m_lastChild = child;
+    }
+    child->setFirstLineStyleBit(m_firstLine);
+    if (child->isText())
+        m_hasTextChildren = true;
+    if (child->object()->selectionState() != RenderObject::SelectionNone)
+        root()->setHasSelectedChildren(true);
+
+    checkConsistency();
+}
+
+void InlineFlowBox::removeChild(InlineBox* child)
+{
+    checkConsistency();
+
+    if (!m_dirty)
+        dirtyLineBoxes();
+
+    root()->childRemoved(child);
+
+    if (child == m_firstChild)
+        m_firstChild = child->nextOnLine();
+    if (child == m_lastChild)
+        m_lastChild = child->prevOnLine();
+    if (child->nextOnLine())
+        child->nextOnLine()->setPrevOnLine(child->prevOnLine());
+    if (child->prevOnLine())
+        child->prevOnLine()->setNextOnLine(child->nextOnLine());
+    
+    child->setParent(0);
+
+    checkConsistency();
+}
+
+void InlineFlowBox::deleteLine(RenderArena* arena)
+{
+    InlineBox* child = firstChild();
+    InlineBox* next = 0;
+    while (child) {
+        ASSERT(this == child->parent());
+        next = child->nextOnLine();
+#ifndef NDEBUG
+        child->setParent(0);
+#endif
+        child->deleteLine(arena);
+        child = next;
+    }
+#ifndef NDEBUG
+    m_firstChild = 0;
+    m_lastChild = 0;
+#endif
+
+    static_cast<RenderFlow*>(m_object)->removeLineBox(this);
+    destroy(arena);
+}
+
+void InlineFlowBox::extractLine()
+{
+    if (!m_extracted)
+        static_cast<RenderFlow*>(m_object)->extractLineBox(this);
+    for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+        child->extractLine();
+}
+
+void InlineFlowBox::attachLine()
+{
+    if (m_extracted)
+        static_cast<RenderFlow*>(m_object)->attachLineBox(this);
+    for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+        child->attachLine();
+}
+
+void InlineFlowBox::adjustPosition(int dx, int dy)
+{
+    InlineRunBox::adjustPosition(dx, dy);
+    for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+        child->adjustPosition(dx, dy);
+}
+
+bool InlineFlowBox::onEndChain(RenderObject* endObject)
+{
+    if (!endObject)
+        return false;
+    
+    if (endObject == object())
+        return true;
+
+    RenderObject* curr = endObject;
+    RenderObject* parent = curr->parent();
+    while (parent && !parent->isRenderBlock()) {
+        if (parent->lastChild() != curr || parent == object())
+            return false;
+            
+        curr = parent;
+        parent = curr->parent();
+    }
+
+    return true;
+}
+
+void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject)
+{
+    // All boxes start off open.  They will not apply any margins/border/padding on
+    // any side.
+    bool includeLeftEdge = false;
+    bool includeRightEdge = false;
+
+    RenderFlow* flow = static_cast<RenderFlow*>(object());
+    
+    if (!flow->firstChild())
+        includeLeftEdge = includeRightEdge = true; // Empty inlines never split across lines.
+    else if (parent()) { // The root inline box never has borders/margins/padding.
+        bool ltr = flow->style()->direction() == LTR;
+        
+        // Check to see if all initial lines are unconstructed.  If so, then
+        // we know the inline began on this line.
+        if (!flow->firstLineBox()->isConstructed()) {
+            if (ltr && flow->firstLineBox() == this)
+                includeLeftEdge = true;
+            else if (!ltr && flow->lastLineBox() == this)
+                includeRightEdge = true;
+        }
+    
+        // In order to determine if the inline ends on this line, we check three things:
+        // (1) If we are the last line and we don't have a continuation(), then we can
+        // close up.
+        // (2) If the last line box for the flow has an object following it on the line (ltr,
+        // reverse for rtl), then the inline has closed.
+        // (3) The line may end on the inline.  If we are the last child (climbing up
+        // the end object's chain), then we just closed as well.
+        if (!flow->lastLineBox()->isConstructed()) {
+            if (ltr) {
+                if (!nextLineBox() &&
+                    ((lastLine && !object()->continuation()) || nextOnLineExists() || onEndChain(endObject)))
+                    includeRightEdge = true;
+            } else {
+                if ((!prevLineBox() || prevLineBox()->isConstructed()) &&
+                    ((lastLine && !object()->continuation()) || prevOnLineExists() || onEndChain(endObject)))
+                    includeLeftEdge = true;
+            }
+        }
+    }
+
+    setEdges(includeLeftEdge, includeRightEdge);
+
+    // Recur into our children.
+    for (InlineBox* currChild = firstChild(); currChild; currChild = currChild->nextOnLine()) {
+        if (currChild->isInlineFlowBox()) {
+            InlineFlowBox* currFlow = static_cast<InlineFlowBox*>(currChild);
+            currFlow->determineSpacingForFlowBoxes(lastLine, endObject);
+        }
+    }
+}
+
+int InlineFlowBox::placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing)
+{
+    // Set our x position.
+    setXPos(x);
+
+    int boxShadowLeft = 0;
+    int boxShadowRight = 0;
+    for (ShadowData* boxShadow = object()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+        boxShadowLeft = min(boxShadow->x - boxShadow->blur, boxShadowLeft);
+        boxShadowRight = max(boxShadow->x + boxShadow->blur, boxShadowRight);
+    }
+    leftPosition = min(x + boxShadowLeft, leftPosition);
+
+    int startX = x;
+    x += borderLeft() + paddingLeft();
+    
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->object()->isText()) {
+            InlineTextBox* text = static_cast<InlineTextBox*>(curr);
+            RenderText* rt = static_cast<RenderText*>(text->object());
+            if (rt->textLength()) {
+                if (needsWordSpacing && isSpaceOrNewline(rt->characters()[text->start()]))
+                    x += rt->style(m_firstLine)->font().wordSpacing();
+                needsWordSpacing = !isSpaceOrNewline(rt->characters()[text->end()]);
+            }
+            text->setXPos(x);
+            
+            int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f));
+            
+            // If letter-spacing is negative, we should factor that into right overflow. (Even in RTL, letter-spacing is
+            // applied to the right, so this is not an issue with left overflow.
+            int letterSpacing = min(0, (int)rt->style(m_firstLine)->font().letterSpacing());
+            
+            int leftGlyphOverflow = -strokeOverflow;
+            int rightGlyphOverflow = strokeOverflow - letterSpacing;
+            
+            int visualOverflowLeft = leftGlyphOverflow;
+            int visualOverflowRight = rightGlyphOverflow;
+            for (ShadowData* shadow = rt->style()->textShadow(); shadow; shadow = shadow->next) {
+                visualOverflowLeft = min(visualOverflowLeft, shadow->x - shadow->blur + leftGlyphOverflow);
+                visualOverflowRight = max(visualOverflowRight, shadow->x + shadow->blur + rightGlyphOverflow);
+            }
+            
+            leftPosition = min(x + visualOverflowLeft, leftPosition);
+            rightPosition = max(x + text->width() + visualOverflowRight, rightPosition);
+            m_maxHorizontalVisualOverflow = max(max(visualOverflowRight, -visualOverflowLeft), m_maxHorizontalVisualOverflow);
+            x += text->width();
+        } else {
+            if (curr->object()->isPositioned()) {
+                if (curr->object()->parent()->style()->direction() == LTR)
+                    curr->setXPos(x);
+                else
+                    // Our offset that we cache needs to be from the edge of the right border box and
+                    // not the left border box.  We have to subtract |x| from the width of the block
+                    // (which can be obtained from the root line box).
+                    curr->setXPos(root()->object()->width()-x);
+                continue; // The positioned object has no effect on the width.
+            }
+            if (curr->object()->isInlineFlow()) {
+                InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
+                if (curr->object()->isCompact()) {
+                    int ignoredX = x;
+                    flow->placeBoxesHorizontally(ignoredX, leftPosition, rightPosition, needsWordSpacing);
+                } else {
+                    x += flow->marginLeft();
+                    x = flow->placeBoxesHorizontally(x, leftPosition, rightPosition, needsWordSpacing);
+                    x += flow->marginRight();
+                }
+            } else if (!curr->object()->isCompact() && (!curr->object()->isListMarker() || static_cast<RenderListMarker*>(curr->object())->isInside())) {
+                x += curr->object()->marginLeft();
+                curr->setXPos(x);
+                leftPosition = min(x + curr->object()->overflowLeft(false), leftPosition);
+                rightPosition = max(x + curr->object()->overflowWidth(false), rightPosition);
+                x += curr->width() + curr->object()->marginRight();
+            }
+        }
+    }
+
+    x += borderRight() + paddingRight();
+    setWidth(x - startX);
+    rightPosition = max(xPos() + width() + boxShadowRight, rightPosition);
+
+    return x;
+}
+
+void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
+{
+    int maxPositionTop = 0;
+    int maxPositionBottom = 0;
+    int maxAscent = 0;
+    int maxDescent = 0;
+
+    // Figure out if we're in strict mode.  Note that we can't simply use !style()->htmlHacks(),
+    // because that would match almost strict mode as well.
+    RenderObject* curr = object();
+    while (curr && !curr->element())
+        curr = curr->container();
+    bool strictMode = (curr && curr->document()->inStrictMode());
+    
+    computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
+
+    if (maxAscent + maxDescent < max(maxPositionTop, maxPositionBottom))
+        adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
+
+    int maxHeight = maxAscent + maxDescent;
+    int topPosition = heightOfBlock;
+    int bottomPosition = heightOfBlock;
+    int selectionTop = heightOfBlock;
+    int selectionBottom = heightOfBlock;
+    placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, strictMode, topPosition, bottomPosition, selectionTop, selectionBottom);
+
+    setVerticalOverflowPositions(topPosition, bottomPosition);
+    setVerticalSelectionPositions(selectionTop, selectionBottom);
+
+    // Shrink boxes with no text children in quirks and almost strict mode.
+    if (!strictMode)
+        shrinkBoxesWithNoTextChildren(topPosition, bottomPosition);
+    
+    heightOfBlock += maxHeight;
+}
+
+void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
+                                              int maxPositionTop, int maxPositionBottom)
+{
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        // The computed lineheight needs to be extended for the
+        // positioned elements
+        if (curr->object()->isPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+        if (curr->yPos() == PositionTop || curr->yPos() == PositionBottom) {
+            if (curr->yPos() == PositionTop) {
+                if (maxAscent + maxDescent < curr->height())
+                    maxDescent = curr->height() - maxAscent;
+            }
+            else {
+                if (maxAscent + maxDescent < curr->height())
+                    maxAscent = curr->height() - maxDescent;
+            }
+
+            if (maxAscent + maxDescent >= max(maxPositionTop, maxPositionBottom))
+                break;
+        }
+
+        if (curr->isInlineFlowBox())
+            static_cast<InlineFlowBox*>(curr)->adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
+    }
+}
+
+void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
+                                             int& maxAscent, int& maxDescent, bool strictMode)
+{
+    if (isRootInlineBox()) {
+        // Examine our root box.
+        setHeight(object()->lineHeight(m_firstLine, true));
+        bool isTableCell = object()->isTableCell();
+        if (isTableCell) {
+            RenderTableCell* tableCell = static_cast<RenderTableCell*>(object());
+            setBaseline(tableCell->RenderBlock::baselinePosition(m_firstLine, true));
+        }
+        else
+            setBaseline(object()->baselinePosition(m_firstLine, true));
+        if (hasTextChildren() || strictMode) {
+            int ascent = baseline();
+            int descent = height() - ascent;
+            if (maxAscent < ascent)
+                maxAscent = ascent;
+            if (maxDescent < descent)
+                maxDescent = descent;
+        }
+    }
+    
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->object()->isPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+        
+        curr->setHeight(curr->object()->lineHeight(m_firstLine));
+        curr->setBaseline(curr->object()->baselinePosition(m_firstLine));
+        curr->setYPos(curr->object()->verticalPositionHint(m_firstLine));
+        if (curr->yPos() == PositionTop) {
+            if (maxPositionTop < curr->height())
+                maxPositionTop = curr->height();
+        }
+        else if (curr->yPos() == PositionBottom) {
+            if (maxPositionBottom < curr->height())
+                maxPositionBottom = curr->height();
+        }
+        else if (curr->hasTextChildren() || curr->object()->hasHorizontalBordersOrPadding() || strictMode) {
+            int ascent = curr->baseline() - curr->yPos();
+            int descent = curr->height() - ascent;
+            if (maxAscent < ascent)
+                maxAscent = ascent;
+            if (maxDescent < descent)
+                maxDescent = descent;
+        }
+
+        if (curr->isInlineFlowBox())
+            static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
+    }
+}
+
+void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode,
+                                         int& topPosition, int& bottomPosition, int& selectionTop, int& selectionBottom)
+{
+    if (isRootInlineBox())
+        setYPos(y + maxAscent - baseline());// Place our root box.
+    
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->object()->isPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+        
+        // Adjust boxes to use their real box y/height and not the logical height (as dictated by
+        // line-height).
+        if (curr->isInlineFlowBox())
+            static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(y, maxHeight, maxAscent, strictMode, topPosition, bottomPosition, selectionTop, selectionBottom);
+
+        bool childAffectsTopBottomPos = true;
+        if (curr->yPos() == PositionTop)
+            curr->setYPos(y);
+        else if (curr->yPos() == PositionBottom)
+            curr->setYPos(y + maxHeight - curr->height());
+        else {
+            if (!curr->hasTextChildren() && !curr->object()->hasHorizontalBordersOrPadding() && !strictMode)
+                childAffectsTopBottomPos = false;
+            curr->setYPos(curr->yPos() + y + maxAscent - curr->baseline());
+        }
+        
+        int newY = curr->yPos();
+        int newHeight = curr->height();
+        int newBaseline = curr->baseline();
+        int overflowTop = 0;
+        int overflowBottom = 0;
+        if (curr->isText() || curr->isInlineFlowBox()) {
+            const Font& font = curr->object()->style(m_firstLine)->font();
+            newBaseline = font.ascent();
+            newY += curr->baseline() - newBaseline;
+            newHeight = newBaseline + font.descent();
+            for (ShadowData* shadow = curr->object()->style()->textShadow(); shadow; shadow = shadow->next) {
+                overflowTop = min(overflowTop, shadow->y - shadow->blur);
+                overflowBottom = max(overflowBottom, shadow->y + shadow->blur);
+            }
+
+            for (ShadowData* boxShadow = curr->object()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+                overflowTop = min(overflowTop, boxShadow->y - boxShadow->blur);
+                overflowBottom = max(overflowBottom, boxShadow->y + boxShadow->blur);
+            }
+
+            for (ShadowData* textShadow = curr->object()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) {
+                overflowTop = min(overflowTop, textShadow->y - textShadow->blur);
+                overflowBottom = max(overflowBottom, textShadow->y + textShadow->blur);
+            }
+
+            if (curr->object()->hasReflection()) {
+                overflowTop = min(overflowTop, curr->object()->reflectionBox().y());
+                overflowBottom = max(overflowBottom, curr->object()->reflectionBox().bottom());
+            }
+
+            if (curr->isInlineFlowBox()) {
+                newHeight += curr->object()->borderTop() + curr->object()->paddingTop() +
+                            curr->object()->borderBottom() + curr->object()->paddingBottom();
+                newY -= curr->object()->borderTop() + curr->object()->paddingTop();
+                newBaseline += curr->object()->borderTop() + curr->object()->paddingTop();
+            }
+        } else if (!curr->object()->isBR()) {
+            newY += curr->object()->marginTop();
+            newHeight = curr->height() - (curr->object()->marginTop() + curr->object()->marginBottom());
+            overflowTop = curr->object()->overflowTop(false);
+            overflowBottom = curr->object()->overflowHeight(false) - newHeight;
+        }
+
+        curr->setYPos(newY);
+        curr->setHeight(newHeight);
+        curr->setBaseline(newBaseline);
+
+        if (childAffectsTopBottomPos) {
+            selectionTop = min(selectionTop, newY);
+            selectionBottom = max(selectionBottom, newY + newHeight);
+            topPosition = min(topPosition, newY + overflowTop);
+            bottomPosition = max(bottomPosition, newY + newHeight + overflowBottom);
+        }
+    }
+
+    if (isRootInlineBox()) {
+        const Font& font = object()->style(m_firstLine)->font();
+        setHeight(font.ascent() + font.descent());
+        setYPos(yPos() + baseline() - font.ascent());
+        setBaseline(font.ascent());
+        if (hasTextChildren() || strictMode) {
+            selectionTop = min(selectionTop, yPos());
+            selectionBottom = max(selectionBottom, yPos() + height());
+        }
+    }
+}
+
+void InlineFlowBox::shrinkBoxesWithNoTextChildren(int topPos, int bottomPos)
+{
+    // First shrink our kids.
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->object()->isPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+        
+        if (curr->isInlineFlowBox())
+            static_cast<InlineFlowBox*>(curr)->shrinkBoxesWithNoTextChildren(topPos, bottomPos);
+    }
+
+    // See if we have text children. If not, then we need to shrink ourselves to fit on the line.
+    if (!hasTextChildren() && !object()->hasHorizontalBordersOrPadding()) {
+        if (yPos() < topPos)
+            setYPos(topPos);
+        if (yPos() + height() > bottomPos)
+            setHeight(bottomPos - yPos());
+        if (baseline() > height())
+            setBaseline(height());
+    }
+}
+
+bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+{
+    // Check children first.
+    for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
+        if (!curr->object()->hasLayer() && curr->nodeAtPoint(request, result, x, y, tx, ty)) {
+            object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
+            return true;
+        }
+    }
+
+    // Now check ourselves.
+    IntRect rect(tx + m_x, ty + m_y, m_width, m_height);
+    if (object()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
+        object()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); // Don't add in m_x or m_y here, we want coords in the containing block's space.
+        return true;
+    }
+    
+    return false;
+}
+
+void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
+{
+    int xPos = tx + m_x - object()->maximalOutlineSize(paintInfo.phase);
+    int w = width() + 2 * object()->maximalOutlineSize(paintInfo.phase);
+    int shadowLeft = 0;
+    int shadowRight = 0;
+    for (ShadowData* boxShadow = object()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+        shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft);
+        shadowRight = max(boxShadow->x + boxShadow->blur, shadowRight);
+    }
+    for (ShadowData* textShadow = object()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) {
+        shadowLeft = min(textShadow->x - textShadow->blur, shadowLeft);
+        shadowRight = max(textShadow->x + textShadow->blur, shadowRight);
+    }
+    xPos += shadowLeft;
+    w += -shadowLeft + shadowRight;
+    bool intersectsDamageRect = xPos < paintInfo.rect.right() && xPos + w > paintInfo.rect.x();
+
+    if (intersectsDamageRect && paintInfo.phase != PaintPhaseChildOutlines) {
+        if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
+            // Add ourselves to the paint info struct's list of inlines that need to paint their
+            // outlines.
+            if (object()->style()->visibility() == VISIBLE && object()->hasOutline() && !isRootInlineBox()) {
+                if ((object()->continuation() || object()->isInlineContinuation()) && !object()->hasLayer()) {
+                    // Add ourselves to the containing block of the entire continuation so that it can
+                    // paint us atomically.
+                    RenderBlock* block = object()->containingBlock()->containingBlock();
+                    block->addContinuationWithOutline(static_cast<RenderFlow*>(object()->element()->renderer()));
+                } else if (!object()->isInlineContinuation())
+                    paintInfo.outlineObjects->add(flowObject());
+            }
+        } else if (paintInfo.phase == PaintPhaseMask) {
+            paintMask(paintInfo, tx, ty);
+            return;
+        } else {
+            // 1. Paint our background, border and box-shadow.
+            paintBoxDecorations(paintInfo, tx, ty);
+
+            // 2. Paint our underline and overline.
+            paintTextDecorations(paintInfo, tx, ty, false);
+        }
+    }
+
+    if (paintInfo.phase == PaintPhaseMask)
+        return;
+
+    PaintPhase paintPhase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;
+    RenderObject::PaintInfo childInfo(paintInfo);
+    childInfo.phase = paintPhase;
+    childInfo.paintingRoot = object()->paintingRootForChildren(paintInfo);
+    
+    // 3. Paint our children.
+    if (paintPhase != PaintPhaseSelfOutline) {
+        for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+            if (!curr->object()->hasLayer())
+                curr->paint(childInfo, tx, ty);
+        }
+    }
+
+    // 4. Paint our strike-through
+    if (intersectsDamageRect && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
+        paintTextDecorations(paintInfo, tx, ty, true);
+}
+
+void InlineFlowBox::paintFillLayers(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
+                                    int my, int mh, int _tx, int _ty, int w, int h, CompositeOperator op)
+{
+    if (!fillLayer)
+        return;
+    paintFillLayers(paintInfo, c, fillLayer->next(), my, mh, _tx, _ty, w, h, op);
+    paintFillLayer(paintInfo, c, fillLayer, my, mh, _tx, _ty, w, h, op);
+}
+
+void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
+                                   int my, int mh, int tx, int ty, int w, int h, CompositeOperator op)
+{
+    StyleImage* img = fillLayer->image();
+    bool hasFillImage = img && img->canRender(object()->style()->effectiveZoom());
+    if ((!hasFillImage && !object()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
+        object()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, tx, ty, w, h, this, op);
+    else {
+        // We have a fill image that spans multiple lines.
+        // We need to adjust _tx and _ty by the width of all previous lines.
+        // Think of background painting on inlines as though you had one long line, a single continuous
+        // strip.  Even though that strip has been broken up across multiple lines, you still paint it
+        // as though you had one single line.  This means each line has to pick up the background where
+        // the previous line left off.
+        // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
+        // but it isn't even clear how this should work at all.
+        int xOffsetOnLine = 0;
+        for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
+            xOffsetOnLine += curr->width();
+        int startX = tx - xOffsetOnLine;
+        int totalWidth = xOffsetOnLine;
+        for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
+            totalWidth += curr->width();
+        paintInfo.context->save();
+        paintInfo.context->clip(IntRect(tx, ty, width(), height()));
+        object()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, startX, ty, totalWidth, h, this, op);
+        paintInfo.context->restore();
+    }
+}
+
+void InlineFlowBox::paintBoxShadow(GraphicsContext* context, RenderStyle* s, int tx, int ty, int w, int h)
+{
+    if ((!prevLineBox() && !nextLineBox()) || !parent())
+        object()->paintBoxShadow(context, tx, ty, w, h, s);
+    else {
+        // FIXME: We can do better here in the multi-line case. We want to push a clip so that the shadow doesn't
+        // protrude incorrectly at the edges, and we want to possibly include shadows cast from the previous/following lines
+        object()->paintBoxShadow(context, tx, ty, w, h, s, includeLeftEdge(), includeRightEdge());
+    }
+}
+
+void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int tx, int ty)
+{
+    if (!object()->shouldPaintWithinRoot(paintInfo) || object()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
+        return;
+
+    // Move x/y to our coordinates.
+    tx += m_x;
+    ty += m_y;
+    
+    int w = width();
+    int h = height();
+
+    int my = max(ty, paintInfo.rect.y());
+    int mh;
+    if (ty < paintInfo.rect.y())
+        mh = max(0, h - (paintInfo.rect.y() - ty));
+    else
+        mh = min(paintInfo.rect.height(), h);
+
+    GraphicsContext* context = paintInfo.context;
+    
+    // You can use p::first-line to specify a background. If so, the root line boxes for
+    // a line may actually have to paint a background.
+    RenderStyle* styleToUse = object()->style(m_firstLine);
+    if ((!parent() && m_firstLine && styleToUse != object()->style()) || (parent() && object()->hasBoxDecorations())) {
+        // Shadow comes first and is behind the background and border.
+        if (styleToUse->boxShadow())
+            paintBoxShadow(context, styleToUse, tx, ty, w, h);
+
+        Color c = styleToUse->backgroundColor();
+        paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), my, mh, tx, ty, w, h);
+
+        // :first-line cannot be used to put borders on a line. Always paint borders with our
+        // non-first-line style.
+        if (parent() && object()->style()->hasBorder()) {
+            StyleImage* borderImage = object()->style()->borderImage().image();
+            bool hasBorderImage = borderImage && borderImage->canRender(styleToUse->effectiveZoom());
+            if (hasBorderImage && !borderImage->isLoaded())
+                return; // Don't paint anything while we wait for the image to load.
+
+            // The simple case is where we either have no border image or we are the only box for this object.  In those
+            // cases only a single call to draw is required.
+            if (!hasBorderImage || (!prevLineBox() && !nextLineBox()))
+                object()->paintBorder(context, tx, ty, w, h, object()->style(), includeLeftEdge(), includeRightEdge());
+            else {
+                // We have a border image that spans multiple lines.
+                // We need to adjust _tx and _ty by the width of all previous lines.
+                // Think of border image painting on inlines as though you had one long line, a single continuous
+                // strip.  Even though that strip has been broken up across multiple lines, you still paint it
+                // as though you had one single line.  This means each line has to pick up the image where
+                // the previous line left off.
+                // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
+                // but it isn't even clear how this should work at all.
+                int xOffsetOnLine = 0;
+                for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
+                    xOffsetOnLine += curr->width();
+                int startX = tx - xOffsetOnLine;
+                int totalWidth = xOffsetOnLine;
+                for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
+                    totalWidth += curr->width();
+                context->save();
+                context->clip(IntRect(tx, ty, width(), height()));
+                object()->paintBorder(context, startX, ty, totalWidth, h, object()->style());
+                context->restore();
+            }
+        }
+    }
+}
+
+void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty)
+{
+    if (!object()->shouldPaintWithinRoot(paintInfo) || object()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+        return;
+
+    // Move x/y to our coordinates.
+    tx += m_x;
+    ty += m_y;
+    
+    int w = width();
+    int h = height();
+
+    int my = max(ty, paintInfo.rect.y());
+    int mh;
+    if (ty < paintInfo.rect.y())
+        mh = max(0, h - (paintInfo.rect.y() - ty));
+    else
+        mh = min(paintInfo.rect.height(), h);
+
+    
+    // Figure out if we need to push a transparency layer to render our mask.
+    bool pushTransparencyLayer = false;
+    const NinePieceImage& maskNinePieceImage = object()->style()->maskBoxImage();
+    StyleImage* maskBoxImage = object()->style()->maskBoxImage().image();
+    if ((maskBoxImage && object()->style()->maskLayers()->hasImage()) || object()->style()->maskLayers()->next())
+        pushTransparencyLayer = true;
+    
+    CompositeOperator compositeOp = CompositeDestinationIn;
+    if (pushTransparencyLayer) {
+        paintInfo.context->setCompositeOperation(CompositeDestinationIn);
+        paintInfo.context->beginTransparencyLayer(1.0f);
+        compositeOp = CompositeSourceOver;
+    }
+
+    paintFillLayers(paintInfo, Color(), object()->style()->maskLayers(), my, mh, tx, ty, w, h, compositeOp);
+    
+    bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(object()->style()->effectiveZoom());
+    if (!hasBoxImage || !maskBoxImage->isLoaded())
+        return; // Don't paint anything while we wait for the image to load.
+
+    // The simple case is where we are the only box for this object.  In those
+    // cases only a single call to draw is required.
+    if (!prevLineBox() && !nextLineBox()) {
+        object()->paintNinePieceImage(paintInfo.context, tx, ty, w, h, object()->style(), maskNinePieceImage, compositeOp);
+    } else {
+        // We have a mask image that spans multiple lines.
+        // We need to adjust _tx and _ty by the width of all previous lines.
+        int xOffsetOnLine = 0;
+        for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
+            xOffsetOnLine += curr->width();
+        int startX = tx - xOffsetOnLine;
+        int totalWidth = xOffsetOnLine;
+        for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
+            totalWidth += curr->width();
+        paintInfo.context->save();
+        paintInfo.context->clip(IntRect(tx, ty, width(), height()));
+        object()->paintNinePieceImage(paintInfo.context, startX, ty, totalWidth, h, object()->style(), maskNinePieceImage, compositeOp);
+        paintInfo.context->restore();
+    }
+    
+    if (pushTransparencyLayer)
+        paintInfo.context->endTransparencyLayer();
+}
+
+static bool shouldDrawTextDecoration(RenderObject* obj)
+{
+    for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling()) {
+        if (curr->isInlineFlow())
+            return true;
+        if (curr->isText() && !curr->isBR()) {
+            if (!curr->style()->collapseWhiteSpace())
+                return true;
+            Node* currElement = curr->element();
+            if (!currElement)
+                return true;
+            if (!currElement->isTextNode())
+                return true;
+            if (!static_cast<Text*>(currElement)->containsOnlyWhitespace())
+                return true;
+        }
+    }
+    return false;
+}
+
+void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int tx, int ty, bool paintedChildren)
+{
+    // Paint text decorations like underlines/overlines. We only do this if we aren't in quirks mode (i.e., in
+    // almost-strict mode or strict mode).
+    if (object()->style()->htmlHacks() || !object()->shouldPaintWithinRoot(paintInfo) ||
+        object()->style()->visibility() != VISIBLE)
+        return;
+    
+    // We don't want underlines or other decorations when we're trying to draw nothing but the selection as white text.
+    if (paintInfo.phase == PaintPhaseSelection && paintInfo.forceBlackText)
+        return;
+
+    GraphicsContext* context = paintInfo.context;
+    tx += m_x;
+    ty += m_y;
+    RenderStyle* styleToUse = object()->style(m_firstLine);
+    int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect();
+    if (deco != TDNONE && 
+        ((!paintedChildren && ((deco & UNDERLINE) || (deco & OVERLINE))) || (paintedChildren && (deco & LINE_THROUGH))) &&
+        shouldDrawTextDecoration(object())) {
+        int x = m_x + borderLeft() + paddingLeft();
+        int w = m_width - (borderLeft() + paddingLeft() + borderRight() + paddingRight());
+        RootInlineBox* rootLine = root();
+        if (rootLine->ellipsisBox()) {
+            int ellipsisX = rootLine->ellipsisBox()->xPos();
+            int ellipsisWidth = rootLine->ellipsisBox()->width();
+            
+            // FIXME: Will need to work with RTL
+            if (rootLine == this) {
+                if (x + w >= ellipsisX + ellipsisWidth)
+                    w -= (x + w - ellipsisX - ellipsisWidth);
+            } else {
+                if (x >= ellipsisX)
+                    return;
+                if (x + w >= ellipsisX)
+                    w -= (x + w - ellipsisX);
+            }
+        }
+
+        // We must have child boxes and have decorations defined.
+        tx += borderLeft() + paddingLeft();
+
+        Color underline, overline, linethrough;
+        underline = overline = linethrough = styleToUse->color();
+        if (!parent())
+            object()->getTextDecorationColors(deco, underline, overline, linethrough);
+
+        bool isPrinting = object()->document()->printing();
+        context->setStrokeThickness(1.0f); // FIXME: We should improve this rule and not always just assume 1.
+
+        bool paintUnderline = deco & UNDERLINE && !paintedChildren;
+        bool paintOverline = deco & OVERLINE && !paintedChildren;
+        bool paintLineThrough = deco & LINE_THROUGH && paintedChildren;
+
+        bool linesAreOpaque = !isPrinting && (!paintUnderline || underline.alpha() == 255) && (!paintOverline || overline.alpha() == 255) && (!paintLineThrough || linethrough.alpha() == 255);
+
+        bool setClip = false;
+        int extraOffset = 0;
+        ShadowData* shadow = styleToUse->textShadow();
+        if (!linesAreOpaque && shadow && shadow->next) {
+            IntRect clipRect(tx, ty, w, m_baseline + 2);
+            for (ShadowData* s = shadow; s; s = s->next) {
+                IntRect shadowRect(tx, ty, w, m_baseline + 2);
+                shadowRect.inflate(s->blur);
+                shadowRect.move(s->x, s->y);
+                clipRect.unite(shadowRect);
+                extraOffset = max(extraOffset, max(0, s->y) + s->blur);
+            }
+            context->save();
+            context->clip(clipRect);
+            extraOffset += m_baseline + 2;
+            ty += extraOffset;
+            setClip = true;
+        }
+
+        bool setShadow = false;
+        do {
+            if (shadow) {
+                if (!shadow->next) {
+                    // The last set of lines paints normally inside the clip.
+                    ty -= extraOffset;
+                    extraOffset = 0;
+                }
+                context->setShadow(IntSize(shadow->x, shadow->y - extraOffset), shadow->blur, shadow->color);
+                setShadow = true;
+                shadow = shadow->next;
+            }
+
+            if (paintUnderline) {
+                context->setStrokeColor(underline);
+                // Leave one pixel of white between the baseline and the underline.
+                context->drawLineForText(IntPoint(tx, ty + m_baseline + 1), w, isPrinting);
+            }
+            if (paintOverline) {
+                context->setStrokeColor(overline);
+                context->drawLineForText(IntPoint(tx, ty), w, isPrinting);
+            }
+            if (paintLineThrough) {
+                context->setStrokeColor(linethrough);
+                context->drawLineForText(IntPoint(tx, ty + 2 * m_baseline / 3), w, isPrinting);
+            }
+        } while (shadow);
+
+        if (setClip)
+            context->restore();
+        else if (setShadow)
+            context->clearShadow();
+    }
+}
+
+InlineBox* InlineFlowBox::firstLeafChild()
+{
+    return firstLeafChildAfterBox();
+}
+
+InlineBox* InlineFlowBox::lastLeafChild()
+{
+    return lastLeafChildBeforeBox();
+}
+
+InlineBox* InlineFlowBox::firstLeafChildAfterBox(InlineBox* start)
+{
+    InlineBox* leaf = 0;
+    for (InlineBox* box = start ? start->nextOnLine() : firstChild(); box && !leaf; box = box->nextOnLine())
+        leaf = box->firstLeafChild();
+    if (start && !leaf && parent())
+        return parent()->firstLeafChildAfterBox(this);
+    return leaf;
+}
+
+InlineBox* InlineFlowBox::lastLeafChildBeforeBox(InlineBox* start)
+{
+    InlineBox* leaf = 0;
+    for (InlineBox* box = start ? start->prevOnLine() : lastChild(); box && !leaf; box = box->prevOnLine())
+        leaf = box->lastLeafChild();
+    if (start && !leaf && parent())
+        return parent()->lastLeafChildBeforeBox(this);
+    return leaf;
+}
+
+RenderObject::SelectionState InlineFlowBox::selectionState()
+{
+    return RenderObject::SelectionNone;
+}
+
+bool InlineFlowBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth)
+{
+    for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {
+        if (!box->canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth))
+            return false;
+    }
+    return true;
+}
+
+int InlineFlowBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
+{
+    int result = -1;
+    for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {
+        int currResult = box->placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
+        if (currResult != -1 && result == -1)
+            result = currResult;
+    }
+    return result;
+}
+
+void InlineFlowBox::clearTruncation()
+{
+    for (InlineBox *box = firstChild(); box; box = box->nextOnLine())
+        box->clearTruncation();
+}
+
+#ifndef NDEBUG
+
+void InlineFlowBox::checkConsistency() const
+{
+#ifdef CHECK_CONSISTENCY
+    ASSERT(!m_hasBadChildList);
+    const InlineBox* prev = 0;
+    for (const InlineBox* child = m_firstChild; child; child = child->nextOnLine()) {
+        ASSERT(child->parent() == this);
+        ASSERT(child->prevOnLine() == prev);
+        prev = child;
+    }
+    ASSERT(prev == m_lastChild);
+#endif
+}
+
+#endif
+
+} // namespace WebCore
diff --git a/WebCore/rendering/InlineFlowBox.h b/WebCore/rendering/InlineFlowBox.h
new file mode 100644
index 0000000..9589603
--- /dev/null
+++ b/WebCore/rendering/InlineFlowBox.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef InlineFlowBox_h
+#define InlineFlowBox_h
+
+#include "InlineRunBox.h"
+
+namespace WebCore {
+
+class HitTestResult;
+
+struct HitTestRequest;
+
+class InlineFlowBox : public InlineRunBox {
+public:
+    InlineFlowBox(RenderObject* obj)
+        : InlineRunBox(obj)
+        , m_firstChild(0)
+        , m_lastChild(0)
+        , m_maxHorizontalVisualOverflow(0)
+#ifndef NDEBUG
+        , m_hasBadChildList(false)
+#endif
+    {
+        // Internet Explorer and Firefox always create a marker for list items, even when the list-style-type is none.  We do not make a marker
+        // in the list-style-type: none case, since it is wasteful to do so.  However, in order to match other browsers we have to pretend like
+        // an invisible marker exists.  The side effect of having an invisible marker is that the quirks mode behavior of shrinking lines with no
+        // text children must not apply.  This change also means that gaps will exist between image bullet list items.  Even when the list bullet
+        // is an image, the line is still considered to be immune from the quirk.
+        m_hasTextChildren = obj->style()->display() == LIST_ITEM;
+    }
+
+#ifndef NDEBUG
+    virtual ~InlineFlowBox();
+#endif
+
+    RenderFlow* flowObject();
+
+    virtual bool isInlineFlowBox() { return true; }
+
+    InlineFlowBox* prevFlowBox() const { return static_cast<InlineFlowBox*>(m_prevLine); }
+    InlineFlowBox* nextFlowBox() const { return static_cast<InlineFlowBox*>(m_nextLine); }
+
+    InlineBox* firstChild() { checkConsistency(); return m_firstChild; }
+    InlineBox* lastChild() { checkConsistency(); return m_lastChild; }
+
+    virtual InlineBox* firstLeafChild();
+    virtual InlineBox* lastLeafChild();
+    InlineBox* firstLeafChildAfterBox(InlineBox* start = 0);
+    InlineBox* lastLeafChildBeforeBox(InlineBox* start = 0);
+
+    virtual void setConstructed()
+    {
+        InlineBox::setConstructed();
+        if (firstChild())
+            firstChild()->setConstructed();
+    }
+
+    void addToLine(InlineBox* child);
+    virtual void deleteLine(RenderArena*);
+    virtual void extractLine();
+    virtual void attachLine();
+    virtual void adjustPosition(int dx, int dy);
+
+    virtual void clearTruncation();
+
+    virtual void paintBoxDecorations(RenderObject::PaintInfo&, int tx, int ty);
+    virtual void paintMask(RenderObject::PaintInfo&, int tx, int ty);
+    void paintFillLayers(const RenderObject::PaintInfo&, const Color&, const FillLayer*,
+                         int my, int mh, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
+    void paintFillLayer(const RenderObject::PaintInfo&, const Color&, const FillLayer*,
+                         int my, int mh, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
+    void paintBoxShadow(GraphicsContext*, RenderStyle*, int tx, int ty, int w, int h);
+    virtual void paintTextDecorations(RenderObject::PaintInfo&, int tx, int ty, bool paintedChildren = false);
+    virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
+
+    int marginBorderPaddingLeft();
+    int marginBorderPaddingRight();
+    int marginLeft();
+    int marginRight();
+    int borderLeft() { if (includeLeftEdge()) return object()->borderLeft(); return 0; }
+    int borderRight() { if (includeRightEdge()) return object()->borderRight(); return 0; }
+    int paddingLeft() { if (includeLeftEdge()) return object()->paddingLeft(); return 0; }
+    int paddingRight() { if (includeRightEdge()) return object()->paddingRight(); return 0; }
+
+    bool includeLeftEdge() { return m_includeLeftEdge; }
+    bool includeRightEdge() { return m_includeRightEdge; }
+    void setEdges(bool includeLeft, bool includeRight)
+    {
+        m_includeLeftEdge = includeLeft;
+        m_includeRightEdge = includeRight;
+    }
+
+    // Helper functions used during line construction and placement.
+    void determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject);
+    int getFlowSpacingWidth();
+    bool onEndChain(RenderObject* endObject);
+    virtual int placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing);
+    virtual void verticallyAlignBoxes(int& heightOfBlock);
+    void computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
+                                  int& maxAscent, int& maxDescent, bool strictMode);
+    void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
+                                   int maxPositionTop, int maxPositionBottom);
+    void placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode,
+                              int& topPosition, int& bottomPosition, int& selectionTop, int& selectionBottom);
+    void shrinkBoxesWithNoTextChildren(int topPosition, int bottomPosition);
+    
+    virtual void setVerticalOverflowPositions(int top, int bottom) { }
+    virtual void setVerticalSelectionPositions(int top, int bottom) { }
+    int maxHorizontalVisualOverflow() const { return m_maxHorizontalVisualOverflow; }
+
+    void removeChild(InlineBox* child);
+
+    virtual RenderObject::SelectionState selectionState();
+
+    virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth);
+    virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&);
+
+    void checkConsistency() const;
+    void setHasBadChildList();
+
+private:
+    InlineBox* m_firstChild;
+    InlineBox* m_lastChild;
+    int m_maxHorizontalVisualOverflow;
+
+#ifndef NDEBUG
+    bool m_hasBadChildList;
+#endif
+};
+
+#ifdef NDEBUG
+inline void InlineFlowBox::checkConsistency() const
+{
+}
+#endif
+
+inline void InlineFlowBox::setHasBadChildList()
+{
+#ifndef NDEBUG
+    m_hasBadChildList = true;
+#endif
+}
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showTree(const WebCore::InlineBox*);
+#endif
+
+#endif // InlineFlowBox_h
diff --git a/WebCore/rendering/InlineRunBox.h b/WebCore/rendering/InlineRunBox.h
new file mode 100644
index 0000000..a624a5b
--- /dev/null
+++ b/WebCore/rendering/InlineRunBox.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the line box implementation for KDE.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef InlineRunBox_h
+#define InlineRunBox_h
+
+#include "InlineBox.h"
+
+namespace WebCore {
+
+class InlineRunBox : public InlineBox {
+public:
+    InlineRunBox(RenderObject* obj)
+        : InlineBox(obj)
+        , m_prevLine(0)
+        , m_nextLine(0)
+    {
+    }
+
+    InlineRunBox* prevLineBox() const { return m_prevLine; }
+    InlineRunBox* nextLineBox() const { return m_nextLine; }
+    void setNextLineBox(InlineRunBox* n) { m_nextLine = n; }
+    void setPreviousLineBox(InlineRunBox* p) { m_prevLine = p; }
+
+    virtual void paintBoxDecorations(RenderObject::PaintInfo&, int tx, int ty) { }
+    virtual void paintTextDecorations(RenderObject::PaintInfo&, int tx, int ty, bool paintedChildren = false) { }
+    
+protected:
+    InlineRunBox* m_prevLine;  // The previous box that also uses our RenderObject
+    InlineRunBox* m_nextLine;  // The next box that also uses our RenderObject
+};
+
+} // namespace WebCore
+
+#endif // InlineRunBox_h
diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp
new file mode 100644
index 0000000..a30920a
--- /dev/null
+++ b/WebCore/rendering/InlineTextBox.cpp
@@ -0,0 +1,920 @@
+/*
+ * (C) 1999 Lars Knoll ([email protected])
+ * (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "InlineTextBox.h"
+
+#include "ChromeClient.h"
+#include "Document.h"
+#include "Editor.h"
+#include "Frame.h"
+#include "GraphicsContext.h"
+#include "HitTestResult.h"
+#include "Page.h"
+#include "RenderArena.h"
+#include "RenderBlock.h"
+#include "RenderTheme.h"
+#include "Text.h"
+#include "break_lines.h"
+#include <wtf/AlwaysInline.h>
+
+using namespace std;
+
+namespace WebCore {
+
+int InlineTextBox::selectionTop()
+{
+    return root()->selectionTop();
+}
+
+int InlineTextBox::selectionHeight()
+{
+    return root()->selectionHeight();
+}
+
+bool InlineTextBox::isSelected(int startPos, int endPos) const
+{
+    int sPos = max(startPos - m_start, 0);
+    int ePos = min(endPos - m_start, (int)m_len);
+    return (sPos < ePos);
+}
+
+RenderObject::SelectionState InlineTextBox::selectionState()
+{
+    RenderObject::SelectionState state = object()->selectionState();
+    if (state == RenderObject::SelectionStart || state == RenderObject::SelectionEnd || state == RenderObject::SelectionBoth) {
+        int startPos, endPos;
+        object()->selectionStartEnd(startPos, endPos);
+        // The position after a hard line break is considered to be past its end.
+        int lastSelectable = start() + len() - (isLineBreak() ? 1 : 0);
+
+        bool start = (state != RenderObject::SelectionEnd && startPos >= m_start && startPos < m_start + m_len);
+        bool end = (state != RenderObject::SelectionStart && endPos > m_start && endPos <= lastSelectable);
+        if (start && end)
+            state = RenderObject::SelectionBoth;
+        else if (start)
+            state = RenderObject::SelectionStart;
+        else if (end)
+            state = RenderObject::SelectionEnd;
+        else if ((state == RenderObject::SelectionEnd || startPos < m_start) &&
+                 (state == RenderObject::SelectionStart || endPos > lastSelectable))
+            state = RenderObject::SelectionInside;
+        else if (state == RenderObject::SelectionBoth)
+            state = RenderObject::SelectionNone;
+    }
+    return state;
+}
+
+IntRect InlineTextBox::selectionRect(int tx, int ty, int startPos, int endPos)
+{
+    int sPos = max(startPos - m_start, 0);
+    int ePos = min(endPos - m_start, (int)m_len);
+    
+    if (sPos >= ePos)
+        return IntRect();
+
+    RenderText* textObj = textObject();
+    int selTop = selectionTop();
+    int selHeight = selectionHeight();
+    const Font& f = textObj->style(m_firstLine)->font();
+
+    IntRect r = enclosingIntRect(f.selectionRectForText(TextRun(textObj->text()->characters() + m_start, m_len, textObj->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride),
+                                                        IntPoint(tx + m_x, ty + selTop), selHeight, sPos, ePos));
+    if (r.x() > tx + m_x + m_width)
+        r.setWidth(0);
+    else if (r.right() - 1 > tx + m_x + m_width)
+        r.setWidth(tx + m_x + m_width - r.x());
+    return r;
+}
+
+void InlineTextBox::deleteLine(RenderArena* arena)
+{
+    static_cast<RenderText*>(m_object)->removeTextBox(this);
+    destroy(arena);
+}
+
+void InlineTextBox::extractLine()
+{
+    if (m_extracted)
+        return;
+
+    static_cast<RenderText*>(m_object)->extractTextBox(this);
+}
+
+void InlineTextBox::attachLine()
+{
+    if (!m_extracted)
+        return;
+    
+    static_cast<RenderText*>(m_object)->attachTextBox(this);
+}
+
+int InlineTextBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
+{
+    if (foundBox) {
+        m_truncation = cFullTruncation;
+        return -1;
+    }
+
+    int ellipsisX = ltr ? blockEdge - ellipsisWidth : blockEdge + ellipsisWidth;
+    
+    // For LTR, if the left edge of the ellipsis is to the left of our text run, then we are the run that will get truncated.
+    if (ltr) {
+        if (ellipsisX <= m_x) {
+            // Too far.  Just set full truncation, but return -1 and let the ellipsis just be placed at the edge of the box.
+            m_truncation = cFullTruncation;
+            foundBox = true;
+            return -1;
+        }
+
+        if (ellipsisX < m_x + m_width) {
+            if (direction() == RTL)
+                return -1; // FIXME: Support LTR truncation when the last run is RTL someday.
+
+            foundBox = true;
+
+            int offset = offsetForPosition(ellipsisX, false);
+            if (offset == 0) {
+                // No characters should be rendered.  Set ourselves to full truncation and place the ellipsis at the min of our start
+                // and the ellipsis edge.
+                m_truncation = cFullTruncation;
+                return min(ellipsisX, m_x);
+            }
+            
+            // Set the truncation index on the text run.  The ellipsis needs to be placed just after the last visible character.
+            m_truncation = offset;
+            return m_x + static_cast<RenderText*>(m_object)->width(m_start, offset, textPos(), m_firstLine);
+        }
+    }
+    else {
+        // FIXME: Support RTL truncation someday, including both modes (when the leftmost run on the line is either RTL or LTR)
+    }
+    return -1;
+}
+
+Color correctedTextColor(Color textColor, Color backgroundColor) 
+{
+    // Adjust the text color if it is too close to the background color,
+    // by darkening or lightening it to move it further away.
+    
+    int d = differenceSquared(textColor, backgroundColor);
+    // semi-arbitrarily chose 65025 (255^2) value here after a few tests; 
+    if (d > 65025) {
+        return textColor;
+    }
+    
+    int distanceFromWhite = differenceSquared(textColor, Color::white);
+    int distanceFromBlack = differenceSquared(textColor, Color::black);
+
+    if (distanceFromWhite < distanceFromBlack) {
+        return textColor.dark();
+    }
+    
+    return textColor.light();
+}
+
+void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, const Color& strokeColor, float strokeThickness)
+{
+    int mode = context->textDrawingMode();
+    if (strokeThickness > 0) {
+        int newMode = mode | cTextStroke;
+        if (mode != newMode) {
+            context->setTextDrawingMode(newMode);
+            mode = newMode;
+        }
+    }
+    
+    if (mode & cTextFill && fillColor != context->fillColor())
+        context->setFillColor(fillColor);
+
+    if (mode & cTextStroke) {
+        if (strokeColor != context->strokeColor())
+            context->setStrokeColor(strokeColor);
+        if (strokeThickness != context->strokeThickness())
+            context->setStrokeThickness(strokeThickness);
+    }
+}
+
+bool InlineTextBox::isLineBreak() const
+{
+    return object()->isBR() || (object()->style()->preserveNewline() && len() == 1 && (*textObject()->text())[start()] == '\n');
+}
+
+bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+{
+    if (isLineBreak())
+        return false;
+
+    IntRect rect(tx + m_x, ty + m_y, m_width, m_height);
+    if (m_truncation != cFullTruncation && object()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
+        object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
+        return true;
+    }
+    return false;
+}
+
+static void paintTextWithShadows(GraphicsContext* context, const TextRun& textRun, int startOffset, int endOffset, const IntPoint& textOrigin, int x, int y, int w, int h, ShadowData* shadow, bool stroked)
+{
+    do {
+        IntSize extraOffset;
+
+        if (shadow) {
+            IntSize shadowOffset(shadow->x, shadow->y);
+            int shadowBlur = shadow->blur;
+            const Color& shadowColor = shadow->color;
+
+            if (shadow->next || stroked) {
+                IntRect shadowRect(x, y, w, h);
+                shadowRect.inflate(shadowBlur);
+                shadowRect.move(shadowOffset);
+                context->save();
+                context->clip(shadowRect);
+
+                extraOffset = IntSize(0, 2 * h + max(0, shadowOffset.height()) + shadowBlur);
+                shadowOffset -= extraOffset;
+            }
+            context->setShadow(shadowOffset, shadowBlur, shadowColor);
+        }
+
+        if (startOffset <= endOffset)
+            context->drawText(textRun, textOrigin + extraOffset, startOffset, endOffset);
+        else {
+            if (endOffset > 0)
+                context->drawText(textRun, textOrigin + extraOffset,  0, endOffset);
+            if (startOffset < textRun.length())
+                context->drawText(textRun, textOrigin + extraOffset, startOffset);
+        }
+
+        if (!shadow)
+            break;
+
+        if (shadow->next || stroked)
+            context->restore();
+        else
+            context->clearShadow();
+
+        shadow = shadow->next;
+    } while (shadow || stroked);
+}
+
+void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
+{
+    if (isLineBreak() || !object()->shouldPaintWithinRoot(paintInfo) || object()->style()->visibility() != VISIBLE ||
+        m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutline)
+        return;
+    
+    ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines);
+
+    int xPos = tx + m_x - parent()->maxHorizontalVisualOverflow();
+    int w = width() + 2 * parent()->maxHorizontalVisualOverflow();
+    if (xPos >= paintInfo.rect.right() || xPos + w <= paintInfo.rect.x())
+        return;
+
+    bool isPrinting = textObject()->document()->printing();
+    
+    // Determine whether or not we're selected.
+    bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && selectionState() != RenderObject::SelectionNone;
+    if (!haveSelection && paintInfo.phase == PaintPhaseSelection)
+        // When only painting the selection, don't bother to paint if there is none.
+        return;
+
+    GraphicsContext* context = paintInfo.context;
+
+    // Determine whether or not we have composition underlines to draw.
+    bool containsComposition = object()->document()->frame()->editor()->compositionNode() == object()->node();
+    bool useCustomUnderlines = containsComposition && object()->document()->frame()->editor()->compositionUsesCustomUnderlines();
+
+    // Set our font.
+    RenderStyle* styleToUse = object()->style(m_firstLine);
+    int d = styleToUse->textDecorationsInEffect();
+    const Font* font = &styleToUse->font();
+    if (*font != context->font())
+        context->setFont(*font);
+
+    // 1. Paint backgrounds behind text if needed. Examples of such backgrounds include selection
+    // and composition underlines.
+    if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseTextClip && !isPrinting) {
+#if PLATFORM(MAC)
+        // Custom highlighters go behind everything else.
+        if (styleToUse->highlight() != nullAtom && !context->paintingDisabled())
+            paintCustomHighlight(tx, ty, styleToUse->highlight());
+#endif
+
+        if (containsComposition && !useCustomUnderlines)
+            paintCompositionBackground(context, tx, ty, styleToUse, font,
+                object()->document()->frame()->editor()->compositionStart(),
+                object()->document()->frame()->editor()->compositionEnd());
+
+        paintDocumentMarkers(context, tx, ty, styleToUse, font, true);
+
+        if (haveSelection && !useCustomUnderlines)
+            paintSelection(context, tx, ty, styleToUse, font);
+    }
+
+    // 2. Now paint the foreground, including text and decorations like underline/overline (in quirks mode only).
+    if (m_len <= 0)
+        return;
+
+    Color textFillColor;
+    Color textStrokeColor;
+    float textStrokeWidth = styleToUse->textStrokeWidth();
+    ShadowData* textShadow = paintInfo.forceBlackText ? 0 : styleToUse->textShadow();
+
+    if (paintInfo.forceBlackText) {
+        textFillColor = Color::black;
+        textStrokeColor = Color::black;
+    } else {
+        textFillColor = styleToUse->textFillColor();
+        if (!textFillColor.isValid())
+            textFillColor = styleToUse->color();
+
+        // Make the text fill color legible against a white background
+        if (styleToUse->forceBackgroundsToWhite())
+            textFillColor = correctedTextColor(textFillColor, Color::white);
+
+        textStrokeColor = styleToUse->textStrokeColor();
+        if (!textStrokeColor.isValid())
+            textStrokeColor = styleToUse->color();
+
+        // Make the text stroke color legible against a white background
+        if (styleToUse->forceBackgroundsToWhite())
+            textStrokeColor = correctedTextColor(textStrokeColor, Color::white);
+    }
+
+    bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection);
+    bool paintSelectedTextSeparately = false;
+
+    Color selectionFillColor = textFillColor;
+    Color selectionStrokeColor = textStrokeColor;
+    float selectionStrokeWidth = textStrokeWidth;
+    ShadowData* selectionShadow = textShadow;
+    if (haveSelection) {
+        // Check foreground color first.
+        Color foreground = paintInfo.forceBlackText ? Color::black : object()->selectionForegroundColor();
+        if (foreground.isValid() && foreground != selectionFillColor) {
+            if (!paintSelectedTextOnly)
+                paintSelectedTextSeparately = true;
+            selectionFillColor = foreground;
+        }
+
+        if (RenderStyle* pseudoStyle = object()->getCachedPseudoStyle(RenderStyle::SELECTION)) {
+            ShadowData* shadow = paintInfo.forceBlackText ? 0 : pseudoStyle->textShadow();
+            if (shadow != selectionShadow) {
+                if (!paintSelectedTextOnly)
+                    paintSelectedTextSeparately = true;
+                selectionShadow = shadow;
+            }
+
+            float strokeWidth = pseudoStyle->textStrokeWidth();
+            if (strokeWidth != selectionStrokeWidth) {
+                if (!paintSelectedTextOnly)
+                    paintSelectedTextSeparately = true;
+                selectionStrokeWidth = strokeWidth;
+            }
+
+            Color stroke = paintInfo.forceBlackText ? Color::black : pseudoStyle->textStrokeColor();
+            if (!stroke.isValid())
+                stroke = pseudoStyle->color();
+            if (stroke != selectionStrokeColor) {
+                if (!paintSelectedTextOnly)
+                    paintSelectedTextSeparately = true;
+                selectionStrokeColor = stroke;
+            }
+        }
+    }
+
+    IntPoint textOrigin(m_x + tx, m_y + ty + m_baseline);
+    TextRun textRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || styleToUse->visuallyOrdered());
+
+    int sPos = 0;
+    int ePos = 0;
+    if (paintSelectedTextOnly || paintSelectedTextSeparately)
+        selectionStartEnd(sPos, ePos);
+
+    if (!paintSelectedTextOnly) {
+        // For stroked painting, we have to change the text drawing mode.  It's probably dangerous to leave that mutated as a side
+        // effect, so only when we know we're stroking, do a save/restore.
+        if (textStrokeWidth > 0)
+            context->save();
+
+        updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth);
+        if (!paintSelectedTextSeparately || ePos <= sPos) {
+            // FIXME: Truncate right-to-left text correctly.
+            paintTextWithShadows(context, textRun, 0, m_truncation == cNoTruncation ? m_len : m_truncation, textOrigin, m_x + tx, m_y + ty, width(), height(), textShadow, textStrokeWidth > 0);
+        } else
+            paintTextWithShadows(context, textRun, ePos, sPos, textOrigin, m_x + tx, m_y + ty, width(), height(), textShadow, textStrokeWidth > 0);
+
+        if (textStrokeWidth > 0)
+            context->restore();
+    }
+
+    if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) {
+        // paint only the text that is selected
+        if (selectionStrokeWidth > 0)
+            context->save();
+
+        updateGraphicsContext(context, selectionFillColor, selectionStrokeColor, selectionStrokeWidth);
+        paintTextWithShadows(context, textRun, sPos, ePos, textOrigin, m_x + tx, m_y + ty, width(), height(), selectionShadow, selectionStrokeWidth > 0);
+
+        if (selectionStrokeWidth > 0)
+            context->restore();
+    }
+
+    // Paint decorations
+    if (d != TDNONE && paintInfo.phase != PaintPhaseSelection && styleToUse->htmlHacks()) {
+        context->setStrokeColor(styleToUse->color());
+        paintDecoration(context, tx, ty, d, textShadow);
+    }
+
+    if (paintInfo.phase == PaintPhaseForeground) {
+        paintDocumentMarkers(context, tx, ty, styleToUse, font, false);
+
+        if (useCustomUnderlines) {
+            const Vector<CompositionUnderline>& underlines = object()->document()->frame()->editor()->customCompositionUnderlines();
+            size_t numUnderlines = underlines.size();
+
+            for (size_t index = 0; index < numUnderlines; ++index) {
+                const CompositionUnderline& underline = underlines[index];
+
+                if (underline.endOffset <= start())
+                    // underline is completely before this run.  This might be an underline that sits
+                    // before the first run we draw, or underlines that were within runs we skipped 
+                    // due to truncation.
+                    continue;
+                
+                if (underline.startOffset <= end()) {
+                    // underline intersects this run.  Paint it.
+                    paintCompositionUnderline(context, tx, ty, underline);
+                    if (underline.endOffset > end() + 1)
+                        // underline also runs into the next run. Bail now, no more marker advancement.
+                        break;
+                } else
+                    // underline is completely after this run, bail.  A later run will paint it.
+                    break;
+            }
+        }
+    }
+}
+
+void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
+{
+    int startPos, endPos;
+    if (object()->selectionState() == RenderObject::SelectionInside) {
+        startPos = 0;
+        endPos = textObject()->textLength();
+    } else {
+        textObject()->selectionStartEnd(startPos, endPos);
+        if (object()->selectionState() == RenderObject::SelectionStart)
+            endPos = textObject()->textLength();
+        else if (object()->selectionState() == RenderObject::SelectionEnd)
+            startPos = 0;
+    }
+
+    sPos = max(startPos - m_start, 0);
+    ePos = min(endPos - m_start, (int)m_len);
+}
+
+void InlineTextBox::paintSelection(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font* f)
+{
+    // See if we have a selection to paint at all.
+    int sPos, ePos;
+    selectionStartEnd(sPos, ePos);
+    if (sPos >= ePos)
+        return;
+#ifdef ANDROID_DO_NOT_DRAW_TEXTFIELD_SELECTION
+    Node* element = m_object->element();
+    if (element) {
+        Node* ancestor = element->shadowAncestorNode();
+        if (ancestor && ancestor->renderer()) {
+            RenderObject* renderer = ancestor->renderer();
+            if (renderer->isTextField() || renderer->isTextArea())
+                return;
+        }
+    }
+#endif
+
+    Color textColor = style->color();
+    Color c = object()->selectionBackgroundColor();
+    if (!c.isValid() || c.alpha() == 0)
+        return;
+
+    // If the text color ends up being the same as the selection background, invert the selection
+    // background.  This should basically never happen, since the selection has transparency.
+    if (textColor == c)
+        c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());
+
+    context->save();
+    updateGraphicsContext(context, c, c, 0);  // Don't draw text at all!
+    int y = selectionTop();
+    int h = selectionHeight();
+    context->clip(IntRect(m_x + tx, y + ty, m_width, h));
+    context->drawHighlightForText(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
+                            IntPoint(m_x + tx, y + ty), h, c, sPos, ePos);
+    context->restore();
+}
+
+void InlineTextBox::paintCompositionBackground(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font* f, int startPos, int endPos)
+{
+    int offset = m_start;
+    int sPos = max(startPos - offset, 0);
+    int ePos = min(endPos - offset, (int)m_len);
+
+    if (sPos >= ePos)
+        return;
+
+    context->save();
+
+    Color c = Color(225, 221, 85);
+    
+    updateGraphicsContext(context, c, c, 0); // Don't draw text at all!
+
+    int y = selectionTop();
+    int h = selectionHeight();
+    context->drawHighlightForText(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
+                            IntPoint(m_x + tx, y + ty), h, c, sPos, ePos);
+    context->restore();
+}
+
+#if PLATFORM(MAC)
+
+void InlineTextBox::paintCustomHighlight(int tx, int ty, const AtomicString& type)
+{
+    Frame* frame = object()->document()->frame();
+    if (!frame)
+        return;
+    Page* page = frame->page();
+    if (!page)
+        return;
+
+    RootInlineBox* r = root();
+    FloatRect rootRect(tx + r->xPos(), ty + selectionTop(), r->width(), selectionHeight());
+    FloatRect textRect(tx + xPos(), rootRect.y(), width(), rootRect.height());
+
+    page->chrome()->client()->paintCustomHighlight(object()->node(), type, textRect, rootRect, true, false);
+}
+
+#endif
+
+void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, int deco, ShadowData* shadow)
+{
+    tx += m_x;
+    ty += m_y;
+
+    if (m_truncation == cFullTruncation)
+        return;
+    
+    int width = (m_truncation == cNoTruncation) ? m_width
+        : static_cast<RenderText*>(m_object)->width(m_start, m_truncation, textPos(), m_firstLine);
+    
+    // Get the text decoration colors.
+    Color underline, overline, linethrough;
+    object()->getTextDecorationColors(deco, underline, overline, linethrough, true);
+    
+    // Use a special function for underlines to get the positioning exactly right.
+    bool isPrinting = textObject()->document()->printing();
+    context->setStrokeThickness(1.0f); // FIXME: We should improve this rule and not always just assume 1.
+
+    bool linesAreOpaque = !isPrinting && (!(deco & UNDERLINE) || underline.alpha() == 255) && (!(deco & OVERLINE) || overline.alpha() == 255) && (!(deco & LINE_THROUGH) || linethrough.alpha() == 255);
+
+    bool setClip = false;
+    int extraOffset = 0;
+    if (!linesAreOpaque && shadow && shadow->next) {
+        context->save();
+        IntRect clipRect(tx, ty, width, m_baseline + 2);
+        for (ShadowData* s = shadow; s; s = s->next) {
+            IntRect shadowRect(tx, ty, width, m_baseline + 2);
+            shadowRect.inflate(s->blur);
+            shadowRect.move(s->x, s->y);
+            clipRect.unite(shadowRect);
+            extraOffset = max(extraOffset, max(0, s->y) + s->blur);
+        }
+        context->save();
+        context->clip(clipRect);
+        extraOffset += m_baseline + 2;
+        ty += extraOffset;
+        setClip = true;
+    }
+
+    bool setShadow = false;
+    do {
+        if (shadow) {
+            if (!shadow->next) {
+                // The last set of lines paints normally inside the clip.
+                ty -= extraOffset;
+                extraOffset = 0;
+            }
+            context->setShadow(IntSize(shadow->x, shadow->y - extraOffset), shadow->blur, shadow->color);
+            setShadow = true;
+            shadow = shadow->next;
+        }
+
+        if (deco & UNDERLINE) {
+            context->setStrokeColor(underline);
+            // Leave one pixel of white between the baseline and the underline.
+            context->drawLineForText(IntPoint(tx, ty + m_baseline + 1), width, isPrinting);
+        }
+        if (deco & OVERLINE) {
+            context->setStrokeColor(overline);
+            context->drawLineForText(IntPoint(tx, ty), width, isPrinting);
+        }
+        if (deco & LINE_THROUGH) {
+            context->setStrokeColor(linethrough);
+            context->drawLineForText(IntPoint(tx, ty + 2 * m_baseline / 3), width, isPrinting);
+        }
+    } while (shadow);
+
+    if (setClip)
+        context->restore();
+    else if (setShadow)
+        context->clearShadow();
+}
+
+void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font* f, bool grammar)
+{
+    // Never print spelling/grammar markers (5327887)
+    if (textObject()->document()->printing())
+        return;
+
+    if (m_truncation == cFullTruncation)
+        return;
+
+    int start = 0;                  // start of line to draw, relative to tx
+    int width = m_width;            // how much line to draw
+
+    // Determine whether we need to measure text
+    bool markerSpansWholeBox = true;
+    if (m_start <= (int)marker.startOffset)
+        markerSpansWholeBox = false;
+    if ((end() + 1) != marker.endOffset)      // end points at the last char, not past it
+        markerSpansWholeBox = false;
+    if (m_truncation != cNoTruncation)
+        markerSpansWholeBox = false;
+
+    if (!markerSpansWholeBox || grammar) {
+        int startPosition = max<int>(marker.startOffset - m_start, 0);
+        int endPosition = min<int>(marker.endOffset - m_start, m_len);
+        
+        if (m_truncation != cNoTruncation)
+            endPosition = min<int>(endPosition, m_truncation);
+
+        // Calculate start & width
+        IntPoint startPoint(tx + m_x, ty + selectionTop());
+        TextRun run(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered());
+        int h = selectionHeight();
+        
+        IntRect markerRect = enclosingIntRect(f->selectionRectForText(run, startPoint, h, startPosition, endPosition));
+        start = markerRect.x() - startPoint.x();
+        width = markerRect.width();
+        
+        // Store rendered rects for bad grammar markers, so we can hit-test against it elsewhere in order to
+        // display a toolTip. We don't do this for misspelling markers.
+        if (grammar)
+            object()->document()->setRenderedRectForMarker(object()->node(), marker, markerRect);
+    }
+    
+    // IMPORTANT: The misspelling underline is not considered when calculating the text bounds, so we have to
+    // make sure to fit within those bounds.  This means the top pixel(s) of the underline will overlap the
+    // bottom pixel(s) of the glyphs in smaller font sizes.  The alternatives are to increase the line spacing (bad!!)
+    // or decrease the underline thickness.  The overlap is actually the most useful, and matches what AppKit does.
+    // So, we generally place the underline at the bottom of the text, but in larger fonts that's not so good so
+    // we pin to two pixels under the baseline.
+    int lineThickness = cMisspellingLineThickness;
+    int descent = m_height - m_baseline;
+    int underlineOffset;
+    if (descent <= (2 + lineThickness)) {
+        // place the underline at the very bottom of the text in small/medium fonts
+        underlineOffset = m_height - lineThickness;
+    } else {
+        // in larger fonts, tho, place the underline up near the baseline to prevent big gap
+        underlineOffset = m_baseline + 2;
+    }
+    pt->drawLineForMisspellingOrBadGrammar(IntPoint(tx + m_x + start, ty + m_y + underlineOffset), width, grammar);
+}
+
+void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font* f)
+{
+   // Use same y positioning and height as for selection, so that when the selection and this highlight are on
+   // the same word there are no pieces sticking out.
+    int y = selectionTop();
+    int h = selectionHeight();
+    
+    int sPos = max(marker.startOffset - m_start, (unsigned)0);
+    int ePos = min(marker.endOffset - m_start, (unsigned)m_len);    
+    TextRun run(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered());
+    IntPoint startPoint = IntPoint(m_x + tx, y + ty);
+    
+    // Always compute and store the rect associated with this marker
+    IntRect markerRect = enclosingIntRect(f->selectionRectForText(run, startPoint, h, sPos, ePos));
+    object()->document()->setRenderedRectForMarker(object()->node(), marker, markerRect);
+     
+    // Optionally highlight the text
+    if (object()->document()->frame()->markedTextMatchesAreHighlighted()) {
+        Color color = theme()->platformTextSearchHighlightColor();
+        pt->save();
+        updateGraphicsContext(pt, color, color, 0);  // Don't draw text at all!
+        pt->clip(IntRect(tx + m_x, ty + y, m_width, h));
+        pt->drawHighlightForText(run, startPoint, h, color, sPos, ePos);
+        pt->restore();
+    }
+}
+
+void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, int tx, int ty, RenderStyle* style, const Font* f, bool background)
+{
+    Vector<DocumentMarker> markers = object()->document()->markersForNode(object()->node());
+    Vector<DocumentMarker>::iterator markerIt = markers.begin();
+
+    // Give any document markers that touch this run a chance to draw before the text has been drawn.
+    // Note end() points at the last char, not one past it like endOffset and ranges do.
+    for ( ; markerIt != markers.end(); markerIt++) {
+        DocumentMarker marker = *markerIt;
+        
+        // Paint either the background markers or the foreground markers, but not both
+        switch (marker.type) {
+            case DocumentMarker::Grammar:
+            case DocumentMarker::Spelling:
+                if (background)
+                    continue;
+                break;
+                
+            case DocumentMarker::TextMatch:
+                if (!background)
+                    continue;
+                break;
+            
+            default:
+                ASSERT_NOT_REACHED();
+        }
+
+        if (marker.endOffset <= start())
+            // marker is completely before this run.  This might be a marker that sits before the
+            // first run we draw, or markers that were within runs we skipped due to truncation.
+            continue;
+        
+        if (marker.startOffset > end())
+            // marker is completely after this run, bail.  A later run will paint it.
+            break;
+        
+        // marker intersects this run.  Paint it.
+        switch (marker.type) {
+            case DocumentMarker::Spelling:
+                paintSpellingOrGrammarMarker(pt, tx, ty, marker, style, f, false);
+                break;
+            case DocumentMarker::Grammar:
+                paintSpellingOrGrammarMarker(pt, tx, ty, marker, style, f, true);
+                break;
+            case DocumentMarker::TextMatch:
+                paintTextMatchMarker(pt, tx, ty, marker, style, f);
+                break;
+            default:
+                ASSERT_NOT_REACHED();
+        }
+
+    }
+}
+
+
+void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, int tx, int ty, const CompositionUnderline& underline)
+{
+    tx += m_x;
+    ty += m_y;
+
+    if (m_truncation == cFullTruncation)
+        return;
+    
+    int start = 0;                 // start of line to draw, relative to tx
+    int width = m_width;           // how much line to draw
+    bool useWholeWidth = true;
+    unsigned paintStart = m_start;
+    unsigned paintEnd = end() + 1; // end points at the last char, not past it
+    if (paintStart <= underline.startOffset) {
+        paintStart = underline.startOffset;
+        useWholeWidth = false;
+        start = static_cast<RenderText*>(m_object)->width(m_start, paintStart - m_start, textPos(), m_firstLine);
+    }
+    if (paintEnd != underline.endOffset) {      // end points at the last char, not past it
+        paintEnd = min(paintEnd, (unsigned)underline.endOffset);
+        useWholeWidth = false;
+    }
+    if (m_truncation != cNoTruncation) {
+        paintEnd = min(paintEnd, (unsigned)m_start + m_truncation);
+        useWholeWidth = false;
+    }
+    if (!useWholeWidth) {
+        width = static_cast<RenderText*>(m_object)->width(paintStart, paintEnd - paintStart, textPos() + start, m_firstLine);
+    }
+
+    // Thick marked text underlines are 2px thick as long as there is room for the 2px line under the baseline.
+    // All other marked text underlines are 1px thick.
+    // If there's not enough space the underline will touch or overlap characters.
+    int lineThickness = 1;
+    if (underline.thick && m_height - m_baseline >= 2)
+        lineThickness = 2;
+
+    // We need to have some space between underlines of subsequent clauses, because some input methods do not use different underline styles for those.
+    // We make each line shorter, which has a harmless side effect of shortening the first and last clauses, too.
+    start += 1;
+    width -= 2;
+
+    ctx->setStrokeColor(underline.color);
+    ctx->setStrokeThickness(lineThickness);
+    ctx->drawLineForText(IntPoint(tx + start, ty + m_height - lineThickness), width, textObject()->document()->printing());
+}
+
+int InlineTextBox::caretMinOffset() const
+{
+    return m_start;
+}
+
+int InlineTextBox::caretMaxOffset() const
+{
+    return m_start + m_len;
+}
+
+unsigned InlineTextBox::caretMaxRenderedOffset() const
+{
+    return m_start + m_len;
+}
+
+int InlineTextBox::textPos() const
+{
+    if (xPos() == 0)
+        return 0;
+        
+    RenderBlock *blockElement = object()->containingBlock();
+    return direction() == RTL ? xPos() - blockElement->borderRight() - blockElement->paddingRight()
+                      : xPos() - blockElement->borderLeft() - blockElement->paddingLeft();
+}
+
+int InlineTextBox::offsetForPosition(int _x, bool includePartialGlyphs) const
+{
+    if (isLineBreak())
+        return 0;
+
+    RenderText* text = static_cast<RenderText*>(m_object);
+    RenderStyle *style = text->style(m_firstLine);
+    const Font* f = &style->font();
+    return f->offsetForPosition(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
+                                _x - m_x, includePartialGlyphs);
+}
+
+int InlineTextBox::positionForOffset(int offset) const
+{
+    ASSERT(offset >= m_start);
+    ASSERT(offset <= m_start + m_len);
+
+    if (isLineBreak())
+        return m_x;
+
+    RenderText* text = static_cast<RenderText*>(m_object);
+    const Font& f = text->style(m_firstLine)->font();
+    int from = direction() == RTL ? offset - m_start : 0;
+    int to = direction() == RTL ? m_len : offset - m_start;
+    // FIXME: Do we need to add rightBearing here?
+    return enclosingIntRect(f.selectionRectForText(TextRun(text->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride),
+                                                   IntPoint(m_x, 0), 0, from, to)).right();
+}
+
+bool InlineTextBox::containsCaretOffset(int offset) const
+{
+    // Offsets before the box are never "in".
+    if (offset < m_start)
+        return false;
+
+    int pastEnd = m_start + m_len;
+
+    // Offsets inside the box (not at either edge) are always "in".
+    if (offset < pastEnd)
+        return true;
+
+    // Offsets outside the box are always "out".
+    if (offset > pastEnd)
+        return false;
+
+    // Offsets at the end are "out" for line breaks (they are on the next line).
+    if (isLineBreak())
+        return false;
+
+    // Offsets at the end are "in" for normal boxes (but the caller has to check affinity).
+    return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/InlineTextBox.h b/WebCore/rendering/InlineTextBox.h
new file mode 100644
index 0000000..d8a250b
--- /dev/null
+++ b/WebCore/rendering/InlineTextBox.h
@@ -0,0 +1,139 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999 Lars Knoll ([email protected])
+ * (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef InlineTextBox_h
+#define InlineTextBox_h
+
+#include "DocumentMarker.h"
+#include "InlineRunBox.h"
+#include "RenderText.h"
+
+namespace WebCore {
+
+const unsigned short cNoTruncation = USHRT_MAX;
+const unsigned short cFullTruncation = USHRT_MAX - 1;
+
+class String;
+class StringImpl;
+class HitTestResult;
+class Position;
+
+struct CompositionUnderline;
+
+// Helper functions shared by InlineTextBox / SVGRootInlineBox
+void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, const Color& strokeColor, float strokeThickness);
+Color correctedTextColor(Color textColor, Color backgroundColor);
+
+class InlineTextBox : public InlineRunBox {
+public:
+    InlineTextBox(RenderObject* obj)
+        : InlineRunBox(obj)
+        , m_start(0)
+        , m_len(0)
+        , m_truncation(cNoTruncation)
+    {
+    }
+
+    InlineTextBox* nextTextBox() const { return static_cast<InlineTextBox*>(nextLineBox()); }
+    InlineTextBox* prevTextBox() const { return static_cast<InlineTextBox*>(prevLineBox()); }
+
+    unsigned start() const { return m_start; }
+    unsigned end() const { return m_len ? m_start + m_len - 1 : m_start; }
+    unsigned len() const { return m_len; }
+
+    void setStart(unsigned start) { m_start = start; }
+    void setLen(unsigned len) { m_len = len; }
+
+    void offsetRun(int d) { m_start += d; }
+
+    virtual int selectionTop();
+    virtual int selectionHeight();
+
+    virtual IntRect selectionRect(int absx, int absy, int startPos, int endPos);
+    bool isSelected(int startPos, int endPos) const;
+    void selectionStartEnd(int& sPos, int& ePos);
+
+    virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
+
+    RenderText* textObject() const;
+
+    virtual void deleteLine(RenderArena*);
+    virtual void extractLine();
+    virtual void attachLine();
+
+    virtual RenderObject::SelectionState selectionState();
+
+    virtual void clearTruncation() { m_truncation = cNoTruncation; }
+    virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox);
+
+    virtual bool isLineBreak() const;
+
+    void setSpaceAdd(int add) { m_width -= m_toAdd; m_toAdd = add; m_width += m_toAdd; }
+    int spaceAdd() { return m_toAdd; }
+
+    virtual bool isInlineTextBox() { return true; }    
+    virtual bool isText() const { return m_treatAsText; }
+    void setIsText(bool b) { m_treatAsText = b; }
+
+    virtual int caretMinOffset() const;
+    virtual int caretMaxOffset() const;
+    virtual unsigned caretMaxRenderedOffset() const;
+
+    int textPos() const;
+    virtual int offsetForPosition(int x, bool includePartialGlyphs = true) const;
+    virtual int positionForOffset(int offset) const;
+
+    bool containsCaretOffset(int offset) const; // false for offset after line break
+
+    int m_start;
+    unsigned short m_len;
+
+    unsigned short m_truncation; // Where to truncate when text overflow is applied.  We use special constants to
+                      // denote no truncation (the whole run paints) and full truncation (nothing paints at all).
+
+protected:
+    void paintCompositionBackground(GraphicsContext*, int tx, int ty, RenderStyle*, const Font*, int startPos, int endPos);
+    void paintDocumentMarkers(GraphicsContext*, int tx, int ty, RenderStyle*, const Font*, bool background);
+    void paintCompositionUnderline(GraphicsContext*, int tx, int ty, const CompositionUnderline&);
+#if PLATFORM(MAC)
+    void paintCustomHighlight(int tx, int ty, const AtomicString& type);
+#endif
+
+private:
+    void paintDecoration(GraphicsContext*, int tx, int ty, int decoration, ShadowData* shadow);
+    void paintSelection(GraphicsContext*, int tx, int ty, RenderStyle*, const Font*);
+    void paintSpellingOrGrammarMarker(GraphicsContext*, int tx, int ty, DocumentMarker, RenderStyle*, const Font*, bool grammar);
+    void paintTextMatchMarker(GraphicsContext*, int tx, int ty, DocumentMarker, RenderStyle*, const Font*);
+    friend class RenderText;
+};
+
+inline RenderText* InlineTextBox::textObject() const
+{
+    return static_cast<RenderText*>(m_object);
+}
+
+} // namespace WebCore
+
+#endif // InlineTextBox_h
diff --git a/WebCore/rendering/LayoutState.cpp b/WebCore/rendering/LayoutState.cpp
new file mode 100644
index 0000000..b473f99
--- /dev/null
+++ b/WebCore/rendering/LayoutState.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "LayoutState.h"
+
+#include "RenderArena.h"
+#include "RenderLayer.h"
+#include "RenderView.h"
+
+namespace WebCore {
+
+LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& offset)
+{
+    ASSERT(prev);
+
+    m_next = prev;
+
+    bool fixed = renderer->isPositioned() && renderer->style()->position() == FixedPosition;
+    if (fixed) {
+        int fixedX = 0;
+        int fixedY = 0;
+        renderer->view()->absolutePosition(fixedX, fixedY, true);
+        m_offset = IntSize(fixedX, fixedY) + offset;
+    } else
+        m_offset = prev->m_offset + offset;
+
+    if (renderer->isRelPositioned()) {
+        if (renderer->hasLayer()) {
+            int relX = 0;
+            int relY = 0;
+            renderer->layer()->relativePositionOffset(relX, relY);
+            m_offset += IntSize(relX, relY);
+        }
+    } else if (renderer->isPositioned() && !fixed) {
+        if (RenderObject* container = renderer->container())
+            m_offset += renderer->offsetForPositionedInContainer(container);
+    }
+
+    m_clipped = !fixed && prev->m_clipped;
+    if (m_clipped)
+        m_clipRect = prev->m_clipRect;
+    if (renderer->hasOverflowClip()) {
+        int x = m_offset.width();
+        int y = m_offset.height();
+        RenderLayer* layer = renderer->layer();
+        IntRect clipRect(x, y, layer->width(), layer->height());
+        clipRect.move(renderer->view()->layoutDelta());
+        if (m_clipped)
+            m_clipRect.intersect(clipRect);
+        else {
+            m_clipRect = clipRect;
+            m_clipped = true;
+        }
+        layer->subtractScrollOffset(x, y);
+        m_offset = IntSize(x, y);
+    }
+    // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
+}
+
+LayoutState::LayoutState(RenderObject* root)
+    : m_clipped(false)
+{
+    RenderObject* container = root->container();
+    int x = 0;
+    int y = 0;
+    container->absolutePositionForContent(x, y);
+    m_offset = IntSize(x, y);
+    m_next = 0;
+}
+
+#ifndef NDEBUG
+static bool inLayoutStateDestroy;
+#endif
+
+void LayoutState::destroy(RenderArena* renderArena)
+{
+#ifndef NDEBUG
+    inLayoutStateDestroy = true;
+#endif
+    delete this;
+#ifndef NDEBUG
+    inLayoutStateDestroy = false;
+#endif
+    renderArena->free(*(size_t*)this, this);
+}
+
+void* LayoutState::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void LayoutState::operator delete(void* ptr, size_t sz)
+{
+    ASSERT(inLayoutStateDestroy);
+    *(size_t*)ptr = sz;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/LayoutState.h b/WebCore/rendering/LayoutState.h
new file mode 100644
index 0000000..551c74a
--- /dev/null
+++ b/WebCore/rendering/LayoutState.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef LayoutState_h
+#define LayoutState_h
+
+#include "IntRect.h"
+#include "IntSize.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class RenderArena;
+class RenderBox;
+class RenderObject;
+
+class LayoutState : Noncopyable {
+public:
+    LayoutState()
+        : m_clipped(false)
+        , m_next(0)
+    {
+    }
+
+    LayoutState(LayoutState*, RenderBox*, const IntSize& offset);
+    LayoutState(RenderObject*);
+
+    void destroy(RenderArena*);
+
+    // Overloaded new operator.
+    void* operator new(size_t, RenderArena*) throw();
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void*, size_t);
+
+private:
+    // The normal operator new is disallowed.
+    void* operator new(size_t) throw();
+
+public:
+    bool m_clipped;
+    IntRect m_clipRect;
+    IntSize m_offset;
+    LayoutState* m_next;
+};
+
+} // namespace WebCore
+
+#endif // LayoutState_h
diff --git a/WebCore/rendering/ListMarkerBox.cpp b/WebCore/rendering/ListMarkerBox.cpp
new file mode 100644
index 0000000..0455eae
--- /dev/null
+++ b/WebCore/rendering/ListMarkerBox.cpp
@@ -0,0 +1,45 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Andrew Wellington ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ListMarkerBox.h"
+
+#include "InlineFlowBox.h"
+#include "RenderArena.h"
+#include "RenderListMarker.h"
+
+namespace WebCore {
+
+ListMarkerBox::ListMarkerBox(RenderObject* obj)
+    : InlineBox(obj)
+{
+}
+
+bool ListMarkerBox::isText() const
+{
+    return static_cast<RenderListMarker*>(object())->isText();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/ListMarkerBox.h b/WebCore/rendering/ListMarkerBox.h
new file mode 100644
index 0000000..47ae256
--- /dev/null
+++ b/WebCore/rendering/ListMarkerBox.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ListMarkerBox_h
+#define ListMarkerBox_h
+
+#include "InlineBox.h"
+
+namespace WebCore {
+
+class ListMarkerBox : public InlineBox {
+public:
+    ListMarkerBox(RenderObject*);
+
+    virtual bool isText() const;
+};
+
+} // namespace WebCore
+
+#endif // ListMarkerBox_h
diff --git a/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp
new file mode 100644
index 0000000..6164585
--- /dev/null
+++ b/WebCore/rendering/MediaControlElements.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(VIDEO)
+
+#include "MediaControlElements.h"
+
+#include "Event.h"
+#include "EventNames.h"
+#include "EventHandler.h"
+#include "FloatConversion.h"
+#include "Frame.h"
+#include "HTMLNames.h"
+#include "RenderSlider.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+// FIXME: These constants may need to be tweaked to better match the seeking in the QT plugin
+static const float cSeekRepeatDelay = 0.1f;
+static const float cStepTime = 0.07f;
+static const float cSeekTime = 0.2f;
+
+MediaControlShadowRootElement::MediaControlShadowRootElement(Document* doc, HTMLMediaElement* mediaElement) 
+    : HTMLDivElement(doc)
+    , m_mediaElement(mediaElement) 
+{
+    RefPtr<RenderStyle> rootStyle = RenderStyle::create();
+    rootStyle->inheritFrom(mediaElement->renderer()->style());
+    rootStyle->setDisplay(BLOCK);
+    rootStyle->setPosition(RelativePosition);
+    RenderMediaControlShadowRoot* renderer = new (mediaElement->renderer()->renderArena()) RenderMediaControlShadowRoot(this);
+    renderer->setParent(mediaElement->renderer());
+    renderer->setStyle(rootStyle.release());
+    setRenderer(renderer);
+    setAttached();
+    setInDocument(true);
+}
+
+// ----------------------------
+
+MediaControlInputElement::MediaControlInputElement(Document* doc, RenderStyle::PseudoId pseudo, const String& type, HTMLMediaElement* mediaElement) 
+    : HTMLInputElement(doc)
+    , m_mediaElement(mediaElement)
+{
+    setInputType(type);
+    RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(pseudo);
+    RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style);
+    if (renderer) {
+        setRenderer(renderer);
+        renderer->setStyle(style);
+    }
+    setAttached();
+    setInDocument(true);
+}
+
+void MediaControlInputElement::attachToParent(Element* parent)
+{
+    parent->addChild(this);
+    parent->renderer()->addChild(renderer());
+}
+
+void MediaControlInputElement::update()
+{
+    if (renderer())
+        renderer()->updateFromElement();
+}
+
+// ----------------------------
+
+MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document* doc, HTMLMediaElement* element)
+    : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_MUTE_BUTTON, "button", element)
+{
+}
+
+void MediaControlMuteButtonElement::defaultEventHandler(Event* event)
+{
+    if (event->type() == eventNames().clickEvent) {
+        m_mediaElement->setMuted(!m_mediaElement->muted());
+        event->setDefaultHandled();
+    }
+    HTMLInputElement::defaultEventHandler(event);
+}
+
+// ----------------------------
+
+MediaControlPlayButtonElement::MediaControlPlayButtonElement(Document* doc, HTMLMediaElement* element)
+    : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_PLAY_BUTTON, "button", element)
+{
+}
+
+void MediaControlPlayButtonElement::defaultEventHandler(Event* event)
+{
+    if (event->type() == eventNames().clickEvent) {
+        ExceptionCode ec;
+        if (m_mediaElement->canPlay())
+            m_mediaElement->play(ec);
+        else 
+            m_mediaElement->pause(ec);
+        event->setDefaultHandled();
+    }
+    HTMLInputElement::defaultEventHandler(event);
+}
+
+// ----------------------------
+
+MediaControlSeekButtonElement::MediaControlSeekButtonElement(Document* doc, HTMLMediaElement* element, bool forward)
+    : MediaControlInputElement(doc, forward ? RenderStyle::MEDIA_CONTROLS_SEEK_FORWARD_BUTTON : RenderStyle::MEDIA_CONTROLS_SEEK_BACK_BUTTON, "button", element)
+    , m_forward(forward)
+    , m_seeking(false)
+    , m_capturing(false)
+    , m_seekTimer(this, &MediaControlSeekButtonElement::seekTimerFired)
+{
+}
+
+void MediaControlSeekButtonElement::defaultEventHandler(Event* event)
+{
+    if (event->type() == eventNames().mousedownEvent) {
+        if (Frame* frame = document()->frame()) {
+            m_capturing = true;
+            frame->eventHandler()->setCapturingMouseEventsNode(this);
+        }
+        ExceptionCode ec;
+        m_mediaElement->pause(ec);
+        m_seekTimer.startRepeating(cSeekRepeatDelay);
+        event->setDefaultHandled();
+    } else if (event->type() == eventNames().mouseupEvent) {
+        if (m_capturing)
+            if (Frame* frame = document()->frame()) {
+                m_capturing = false;
+                frame->eventHandler()->setCapturingMouseEventsNode(0);
+            }
+        ExceptionCode ec;
+        if (m_seeking || m_seekTimer.isActive()) {
+            if (!m_seeking) {
+                float stepTime = m_forward ? cStepTime : -cStepTime;
+                m_mediaElement->setCurrentTime(m_mediaElement->currentTime() + stepTime, ec);
+            }
+            m_seekTimer.stop();
+            m_seeking = false;
+            event->setDefaultHandled();
+        }
+    }
+    HTMLInputElement::defaultEventHandler(event);
+}
+
+void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>*)
+{
+    ExceptionCode ec;
+    m_seeking = true;
+    float seekTime = m_forward ? cSeekTime : -cSeekTime;
+    m_mediaElement->setCurrentTime(m_mediaElement->currentTime() + seekTime, ec);
+}
+
+// ----------------------------
+
+MediaControlTimelineElement::MediaControlTimelineElement(Document* doc, HTMLMediaElement* element)
+    : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_TIMELINE, "range", element)
+{ 
+    setAttribute(precisionAttr, "float");
+}
+
+void MediaControlTimelineElement::defaultEventHandler(Event* event)
+{
+    RenderSlider* slider = static_cast<RenderSlider*>(renderer());
+    bool oldInDragMode = slider && slider->inDragMode();
+    float oldTime = narrowPrecisionToFloat(value().toDouble());
+    bool oldEnded = m_mediaElement->ended();
+
+    HTMLInputElement::defaultEventHandler(event);
+
+    float time = narrowPrecisionToFloat(value().toDouble());
+    if (oldTime != time || event->type() == eventNames().inputEvent) {
+        ExceptionCode ec;
+        m_mediaElement->setCurrentTime(time, ec);
+    }
+    // Media element stays in non-paused state when it reaches end. If the slider is now dragged
+    // to some other position the playback resumes which does not match usual media player UIs.
+    // Get the expected behavior by pausing explicitly in this case.
+    if (oldEnded && !m_mediaElement->ended() && !m_mediaElement->paused()) {
+        ExceptionCode ec;
+        m_mediaElement->pause(ec);
+    }
+    // Pause playback during drag, but do it without using DOM API which would generate events 
+    bool inDragMode = slider && slider->inDragMode();
+    if (inDragMode != oldInDragMode)
+        m_mediaElement->setPausedInternal(inDragMode);
+}
+
+void MediaControlTimelineElement::update(bool updateDuration) 
+{
+    if (updateDuration) {
+        float dur = m_mediaElement->duration();
+        setAttribute(maxAttr, String::number(isfinite(dur) ? dur : 0));
+    }
+    setValue(String::number(m_mediaElement->currentTime()));
+}
+
+// ----------------------------
+
+MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(Document* doc, HTMLMediaElement* element)
+    : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_FULLSCREEN_BUTTON, "button", element)
+{
+}
+
+void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event)
+{
+    if (event->type() == eventNames().clickEvent) {
+        event->setDefaultHandled();
+    }
+    HTMLInputElement::defaultEventHandler(event);
+}
+
+// ----------------------------
+
+} //namespace WebCore
+#endif // enable(video)
diff --git a/WebCore/rendering/MediaControlElements.h b/WebCore/rendering/MediaControlElements.h
new file mode 100644
index 0000000..8ff726b
--- /dev/null
+++ b/WebCore/rendering/MediaControlElements.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MediaControlElements_h
+#define MediaControlElements_h
+
+#if ENABLE(VIDEO)
+
+#include "HTMLDivElement.h"
+#include "HTMLInputElement.h"
+#include "HTMLMediaElement.h"
+#include "RenderBlock.h"
+
+// These are the shadow elements used in RenderMedia
+
+namespace WebCore {
+
+class Event;
+class Frame;
+
+class MediaControlShadowRootElement : public HTMLDivElement {
+public:
+    MediaControlShadowRootElement(Document*, HTMLMediaElement*);
+    
+    virtual bool isShadowNode() const { return true; }
+    virtual Node* shadowParentNode() { return m_mediaElement; }
+    
+private:
+    HTMLMediaElement* m_mediaElement;    
+};
+
+// ----------------------------
+
+class MediaControlInputElement : public HTMLInputElement {
+public:
+    MediaControlInputElement(Document*, RenderStyle::PseudoId, const String& type, HTMLMediaElement*);
+    void attachToParent(Element*);
+    void update();
+protected:
+    HTMLMediaElement* m_mediaElement;   
+};
+
+// ----------------------------
+
+class MediaControlMuteButtonElement : public MediaControlInputElement {
+public:
+    MediaControlMuteButtonElement(Document*, HTMLMediaElement*);
+    virtual void defaultEventHandler(Event*);
+};
+
+// ----------------------------
+
+class MediaControlPlayButtonElement : public MediaControlInputElement {
+public:
+    MediaControlPlayButtonElement(Document*, HTMLMediaElement*);
+    virtual void defaultEventHandler(Event*);
+};
+
+// ----------------------------
+
+class MediaControlSeekButtonElement : public MediaControlInputElement {
+public:
+    MediaControlSeekButtonElement(Document*, HTMLMediaElement*, bool forward);
+    virtual void defaultEventHandler(Event*);
+    void seekTimerFired(Timer<MediaControlSeekButtonElement>*);
+
+private:
+    bool m_forward;
+    bool m_seeking;
+    bool m_capturing;
+    Timer<MediaControlSeekButtonElement> m_seekTimer;
+};
+
+// ----------------------------
+
+class MediaControlTimelineElement : public MediaControlInputElement {
+public:
+    MediaControlTimelineElement(Document*, HTMLMediaElement*);
+    virtual void defaultEventHandler(Event*);
+    void update(bool updateDuration = true);
+};
+
+// ----------------------------
+
+class MediaControlFullscreenButtonElement : public MediaControlInputElement {
+public:
+    MediaControlFullscreenButtonElement(Document*, HTMLMediaElement*);
+    virtual void defaultEventHandler(Event*);
+};
+
+// ----------------------------
+
+class RenderMediaControlShadowRoot : public RenderBlock {
+public:
+    RenderMediaControlShadowRoot(Element* e) : RenderBlock(e) { }
+    void setParent(RenderObject* p) { RenderObject::setParent(p); }
+};
+
+// ----------------------------
+
+} //namespace WebCore
+#endif // enable(video)
+#endif // MediaControlElements_h
diff --git a/WebCore/rendering/PointerEventsHitRules.cpp b/WebCore/rendering/PointerEventsHitRules.cpp
new file mode 100644
index 0000000..bee13af
--- /dev/null
+++ b/WebCore/rendering/PointerEventsHitRules.cpp
@@ -0,0 +1,110 @@
+/*
+    Copyright (C) 2007 Rob Buis <[email protected]>
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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
+    aint with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#if ENABLE(SVG)
+#include "PointerEventsHitRules.h"
+
+namespace WebCore {
+
+PointerEventsHitRules::PointerEventsHitRules(ESVGHitTesting hitTesting, EPointerEvents pointerEvents)
+    : requireVisible(false)
+    , requireFill(false)
+    , requireStroke(false)
+    , canHitStroke(false)
+    , canHitFill(false)
+{
+    if (hitTesting == SVG_PATH_HITTESTING) {
+        switch (pointerEvents)
+        {
+            case PE_VISIBLE_PAINTED:
+                requireFill = true;
+                requireStroke = true;
+            case PE_VISIBLE:
+                requireVisible = true;
+                canHitFill = true;
+                canHitStroke = true;
+                break;
+            case PE_VISIBLE_FILL:
+                requireVisible = true;
+                canHitFill = true;
+                break;
+            case PE_VISIBLE_STROKE:
+                requireVisible = true;
+                canHitStroke = true;
+                break;
+            case PE_PAINTED:
+                requireFill = true;
+                requireStroke = true;
+            case PE_ALL:
+                canHitFill = true;
+                canHitStroke = true;
+                break;
+            case PE_FILL:
+                canHitFill = true;
+                break;
+            case PE_STROKE:
+                canHitStroke = true;
+                break;
+            case PE_NONE:
+                // nothing to do here, defaults are all false.
+                break;
+        }
+    } else {
+        switch (pointerEvents)
+        {
+            case PE_VISIBLE_PAINTED:
+                requireVisible = true;
+                requireFill = true;
+                requireStroke = true;
+                canHitFill = true;
+                canHitStroke = true;
+                break;
+            case PE_VISIBLE_FILL:
+            case PE_VISIBLE_STROKE:
+            case PE_VISIBLE:
+                requireVisible = true;
+                canHitFill = true;
+                canHitStroke = true;
+                break;
+            case PE_PAINTED:
+                requireFill = true;
+                requireStroke = true;
+                canHitFill = true;
+                canHitStroke = true;
+                break;
+            case PE_FILL:
+            case PE_STROKE:
+            case PE_ALL:
+                canHitFill = true;
+                canHitStroke = true;
+                break;
+            case PE_NONE:
+                // nothing to do here, defaults are all false.
+                break;
+        }
+    }
+}
+
+}
+
+// vim:ts=4:noet
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/PointerEventsHitRules.h b/WebCore/rendering/PointerEventsHitRules.h
new file mode 100644
index 0000000..825cae8
--- /dev/null
+++ b/WebCore/rendering/PointerEventsHitRules.h
@@ -0,0 +1,52 @@
+/*
+    Copyright (C) 2007 Rob Buis <[email protected]>
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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
+    aint with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef PointerEventsHitRules_h
+#define PointerEventsHitRules_h
+#if ENABLE(SVG)
+
+#include "SVGRenderStyle.h"
+
+namespace WebCore {
+
+class PointerEventsHitRules {
+public:
+    enum ESVGHitTesting {
+        SVG_IMAGE_HITTESTING,
+        SVG_PATH_HITTESTING,
+        SVG_TEXT_HITTESTING
+    };
+
+    PointerEventsHitRules(ESVGHitTesting, EPointerEvents);
+
+    bool requireVisible;
+    bool requireFill;
+    bool requireStroke;
+    bool canHitStroke;
+    bool canHitFill;  
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderApplet.cpp b/WebCore/rendering/RenderApplet.cpp
new file mode 100644
index 0000000..7483943
--- /dev/null
+++ b/WebCore/rendering/RenderApplet.cpp
@@ -0,0 +1,98 @@
+/**
+ * This file is part of the HTML widget for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderApplet.h"
+
+#include "Document.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "HTMLAppletElement.h"
+#include "HTMLNames.h"
+#include "HTMLParamElement.h"
+#include "Widget.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderApplet::RenderApplet(HTMLAppletElement* applet, const HashMap<String, String>& args)
+    : RenderWidget(applet)
+    , m_args(args)
+{
+    setInline(true);
+}
+
+RenderApplet::~RenderApplet()
+{
+}
+
+IntSize RenderApplet::intrinsicSize() const
+{
+    // FIXME: This doesn't make sense. We can't just start returning
+    // a different size once we've created the widget and expect
+    // layout and sizing to be correct. We should remove this and
+    // pass the appropriate intrinsic size in the constructor.
+    return m_widget ? IntSize(50, 50) : IntSize(150, 150);
+}
+
+void RenderApplet::createWidgetIfNecessary()
+{
+    HTMLAppletElement* element = static_cast<HTMLAppletElement*>(node());
+    if (m_widget || !element->isFinishedParsingChildren())
+        return;
+
+    // FIXME: Java applets can't be resized (this is a bug in Apple's Java implementation).
+    // In order to work around this problem and have a correct size from the start, we will
+    // use fixed widths/heights from the style system when we can, since the widget might
+    // not have an accurate m_width/m_height.
+    int width = style()->width().isFixed() ? style()->width().value() : 
+        m_width - borderLeft() - borderRight() - paddingLeft() - paddingRight();
+    int height = style()->height().isFixed() ? style()->height().value() :
+        m_height - borderTop() - borderBottom() - paddingTop() - paddingBottom();
+    for (Node* child = element->firstChild(); child; child = child->nextSibling()) {
+        if (child->hasTagName(paramTag)) {
+            HTMLParamElement* p = static_cast<HTMLParamElement*>(child);
+            if (!p->name().isEmpty())
+                m_args.set(p->name(), p->value());
+        }
+    }
+
+    Frame* frame = document()->frame();
+    ASSERT(frame);
+    setWidget(frame->loader()->createJavaAppletWidget(IntSize(width, height), element, m_args));
+}
+
+void RenderApplet::layout()
+{
+    ASSERT(needsLayout());
+
+    calcWidth();
+    calcHeight();
+
+    // The applet's widget gets created lazily upon first layout.
+    createWidgetIfNecessary();
+    setNeedsLayout(false);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderApplet.h b/WebCore/rendering/RenderApplet.h
new file mode 100644
index 0000000..6746c22
--- /dev/null
+++ b/WebCore/rendering/RenderApplet.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderApplet_h
+#define RenderApplet_h
+
+#include "RenderWidget.h"
+#include "StringHash.h"
+
+namespace WebCore {
+
+    class HTMLAppletElement;
+
+    class RenderApplet : public RenderWidget {
+    public:
+        RenderApplet(HTMLAppletElement*, const HashMap<String, String>& args);
+        virtual ~RenderApplet();
+
+        virtual const char* renderName() const { return "RenderApplet"; }
+
+        virtual bool isApplet() const { return true; }
+
+        virtual void layout();
+        virtual IntSize intrinsicSize() const;
+
+        void createWidgetIfNecessary();
+
+    private:
+        HashMap<String, String> m_args;
+    };
+
+} // namespace WebCore
+
+#endif // RenderApplet_h
diff --git a/WebCore/rendering/RenderArena.cpp b/WebCore/rendering/RenderArena.cpp
new file mode 100644
index 0000000..69d08a5
--- /dev/null
+++ b/WebCore/rendering/RenderArena.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above.  If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "config.h"
+#include "RenderArena.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <wtf/Assertions.h>
+
+#define ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
+
+namespace WebCore {
+
+#ifndef NDEBUG
+
+const int signature = 0xDBA00AEA;
+const int signatureDead = 0xDBA00AED;
+
+typedef struct {
+    RenderArena* arena;
+    size_t size;
+    int signature;
+} RenderArenaDebugHeader;
+
+#endif
+
+RenderArena::RenderArena(unsigned arenaSize)
+{
+    // Initialize the arena pool
+    INIT_ARENA_POOL(&m_pool, "RenderArena", arenaSize);
+
+    // Zero out the recyclers array
+    memset(m_recyclers, 0, sizeof(m_recyclers));
+}
+
+RenderArena::~RenderArena()
+{
+    FinishArenaPool(&m_pool);
+}
+
+void* RenderArena::allocate(size_t size)
+{
+#ifndef NDEBUG
+    // Use standard malloc so that memory debugging tools work.
+    ASSERT(this);
+    void* block = ::malloc(sizeof(RenderArenaDebugHeader) + size);
+    RenderArenaDebugHeader* header = (RenderArenaDebugHeader*)block;
+    header->arena = this;
+    header->size = size;
+    header->signature = signature;
+    return header + 1;
+#else
+    void* result = 0;
+
+    // Ensure we have correct alignment for pointers.  Important for Tru64
+    size = ROUNDUP(size, sizeof(void*));
+
+    // Check recyclers first
+    if (size < gMaxRecycledSize) {
+        const int index = size >> 2;
+
+        result = m_recyclers[index];
+        if (result) {
+            // Need to move to the next object
+            void* next = *((void**)result);
+            m_recyclers[index] = next;
+        }
+    }
+
+    if (!result) {
+        // Allocate a new chunk from the arena
+        ARENA_ALLOCATE(result, &m_pool, size);
+    }
+
+    return result;
+#endif
+}
+
+void RenderArena::free(size_t size, void* ptr)
+{
+#ifndef NDEBUG
+    // Use standard free so that memory debugging tools work.
+    RenderArenaDebugHeader* header = (RenderArenaDebugHeader*)ptr - 1;
+    ASSERT(header->signature == signature);
+    ASSERT(header->size == size);
+    ASSERT(header->arena == this);
+    header->signature = signatureDead;
+    ::free(header);
+#else
+    // Ensure we have correct alignment for pointers.  Important for Tru64
+    size = ROUNDUP(size, sizeof(void*));
+
+    // See if it's a size that we recycle
+    if (size < gMaxRecycledSize) {
+        const int index = size >> 2;
+        void* currentTop = m_recyclers[index];
+        m_recyclers[index] = ptr;
+        *((void**)ptr) = currentTop;
+    }
+#endif
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderArena.h b/WebCore/rendering/RenderArena.h
new file mode 100644
index 0000000..3c27d15
--- /dev/null
+++ b/WebCore/rendering/RenderArena.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above.  If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#ifndef RenderArena_h
+#define RenderArena_h
+
+#include "Arena.h"
+
+namespace WebCore {
+
+static const size_t gMaxRecycledSize = 400;
+
+class RenderArena {
+public:
+    RenderArena(unsigned arenaSize = 4096);
+    ~RenderArena();
+
+    // Memory management functions
+    void* allocate(size_t);
+    void free(size_t, void*);
+
+private:
+    // Underlying arena pool
+    ArenaPool m_pool;
+
+    // The recycler array is sparse with the indices being multiples of 4,
+    // i.e., 0, 4, 8, 12, 16, 20, ...
+    void* m_recyclers[gMaxRecycledSize >> 2];
+};
+
+} // namespace WebCore
+
+#endif // RenderArena_h
diff --git a/WebCore/rendering/RenderBR.cpp b/WebCore/rendering/RenderBR.cpp
new file mode 100644
index 0000000..82b008a
--- /dev/null
+++ b/WebCore/rendering/RenderBR.cpp
@@ -0,0 +1,111 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ * Copyright (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderBR.h"
+
+#include "Document.h"
+#include "InlineTextBox.h"
+#include "VisiblePosition.h"
+
+namespace WebCore {
+
+RenderBR::RenderBR(Node* node)
+    : RenderText(node, StringImpl::create("\n"))
+    , m_lineHeight(-1)
+{
+}
+
+RenderBR::~RenderBR()
+{
+}
+
+InlineBox* RenderBR::createInlineBox(bool makePlaceholder, bool isRootLineBox, bool isOnlyRun)
+{
+    // We only treat a box as text for a <br> if we are on a line by ourself or in strict mode
+    // (Note the use of strict mode.  In "almost strict" mode, we don't treat the box for <br> as text.)
+    InlineTextBox* box = static_cast<InlineTextBox*>(RenderText::createInlineBox(makePlaceholder, isRootLineBox, isOnlyRun));
+    box->setIsText(isOnlyRun || document()->inStrictMode());
+    return box;
+}
+
+int RenderBR::baselinePosition(bool firstLine, bool isRootLineBox) const
+{
+    if (firstTextBox() && !firstTextBox()->isText())
+        return 0;
+    return RenderText::baselinePosition(firstLine, isRootLineBox);
+}
+
+int RenderBR::lineHeight(bool firstLine, bool isRootLineBox) const
+{
+    if (firstTextBox() && !firstTextBox()->isText())
+        return 0;
+
+    if (firstLine) {
+        RenderStyle* s = style(firstLine);
+        Length lh = s->lineHeight();
+        if (lh.isNegative()) {
+            if (s == style()) {
+                if (m_lineHeight == -1)
+                    m_lineHeight = RenderObject::lineHeight(false);
+                return m_lineHeight;
+            }
+            return s->font().lineSpacing();
+        }
+        if (lh.isPercent())
+            return lh.calcMinValue(s->fontSize());
+        return lh.value();
+    }
+
+    if (m_lineHeight == -1)
+        m_lineHeight = RenderObject::lineHeight(false);
+    return m_lineHeight;
+}
+
+void RenderBR::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderText::styleDidChange(diff, oldStyle);
+    m_lineHeight = -1;
+}
+
+int RenderBR::caretMinOffset() const 
+{ 
+    return 0;
+}
+
+int RenderBR::caretMaxOffset() const 
+{ 
+    return 1;
+}
+
+unsigned RenderBR::caretMaxRenderedOffset() const
+{
+    return 1;
+}
+
+VisiblePosition RenderBR::positionForCoordinates(int /*x*/, int /*y*/)
+{
+    return VisiblePosition(element(), 0, DOWNSTREAM);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderBR.h b/WebCore/rendering/RenderBR.h
new file mode 100644
index 0000000..b65bb58
--- /dev/null
+++ b/WebCore/rendering/RenderBR.h
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderBR_h
+#define RenderBR_h
+
+#include "RenderText.h"
+
+/*
+ * The whole class here is a hack to get <br> working, as long as we don't have support for
+ * CSS2 :before and :after pseudo elements
+ */
+namespace WebCore {
+
+class Position;
+
+class RenderBR : public RenderText {
+public:
+    RenderBR(Node*);
+    virtual ~RenderBR();
+
+    virtual const char* renderName() const { return "RenderBR"; }
+ 
+    virtual IntRect selectionRect(bool) { return IntRect(); }
+
+    virtual unsigned width(unsigned /*from*/, unsigned /*len*/, const Font&, int /*xpos*/) const { return 0; }
+    virtual unsigned width(unsigned /*from*/, unsigned /*len*/, int /*xpos*/, bool /*firstLine = false*/) const { return 0; }
+
+    virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
+    virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
+
+    // overrides
+    virtual InlineBox* createInlineBox(bool, bool, bool isOnlyRun = false);
+
+    virtual bool isBR() const { return true; }
+
+    virtual int caretMinOffset() const;
+    virtual int caretMaxOffset() const;
+    virtual unsigned caretMaxRenderedOffset() const;
+
+    virtual VisiblePosition positionForCoordinates(int x, int y);
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+private:
+    mutable int m_lineHeight;
+};
+
+} // namespace WebCore
+
+#endif // RenderBR_h
diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp
new file mode 100644
index 0000000..9dabacd
--- /dev/null
+++ b/WebCore/rendering/RenderBlock.cpp
@@ -0,0 +1,4697 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ *           (C) 2007 David Smith ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RenderBlock.h"
+
+#include "Document.h"
+#include "Element.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "HitTestResult.h"
+#include "InlineTextBox.h"
+#include "RenderImage.h"
+#include "RenderMarquee.h"
+#include "RenderReplica.h"
+#include "RenderTableCell.h"
+#include "RenderTextFragment.h"
+#include "RenderTheme.h"
+#include "RenderView.h"
+#include "SelectionController.h"
+
+#ifdef ANDROID_LAYOUT
+#include "Settings.h"
+#endif
+
+using namespace std;
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+// Number of pixels to allow as a fudge factor when clicking above or below a line.
+// clicking up to verticalLineClickFudgeFactor pixels above a line will correspond to the closest point on the line.   
+const int verticalLineClickFudgeFactor= 3;
+
+using namespace HTMLNames;
+
+struct ColumnInfo {
+    ColumnInfo()
+        : m_desiredColumnWidth(0)
+        , m_desiredColumnCount(1)
+        { }
+    int m_desiredColumnWidth;
+    unsigned m_desiredColumnCount;
+    Vector<IntRect> m_columnRects;
+};
+
+typedef WTF::HashMap<const RenderBox*, ColumnInfo*> ColumnInfoMap;
+static ColumnInfoMap* gColumnInfoMap = 0;
+
+typedef WTF::HashMap<const RenderBlock*, HashSet<RenderBox*>*> PercentHeightDescendantsMap;
+static PercentHeightDescendantsMap* gPercentHeightDescendantsMap = 0;
+
+typedef WTF::HashMap<const RenderBox*, HashSet<RenderBlock*>*> PercentHeightContainerMap;
+static PercentHeightContainerMap* gPercentHeightContainerMap = 0;
+
+// Our MarginInfo state used when laying out block children.
+RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom)
+{
+    // Whether or not we can collapse our own margins with our children.  We don't do this
+    // if we had any border/padding (obviously), if we're the root or HTML elements, or if
+    // we're positioned, floating, a table cell.
+    m_canCollapseWithChildren = !block->isRenderView() && !block->isRoot() && !block->isPositioned() &&
+        !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable();
+
+    m_canCollapseTopWithChildren = m_canCollapseWithChildren && (top == 0) && block->style()->marginTopCollapse() != MSEPARATE;
+
+    // If any height other than auto is specified in CSS, then we don't collapse our bottom
+    // margins with our children's margins.  To do otherwise would be to risk odd visual
+    // effects when the children overflow out of the parent block and yet still collapse
+    // with it.  We also don't collapse if we have any bottom border/padding.
+    m_canCollapseBottomWithChildren = m_canCollapseWithChildren && (bottom == 0) &&
+        (block->style()->height().isAuto() && block->style()->height().value() == 0) && block->style()->marginBottomCollapse() != MSEPARATE;
+    
+    m_quirkContainer = block->isTableCell() || block->isBody() || block->style()->marginTopCollapse() == MDISCARD || 
+        block->style()->marginBottomCollapse() == MDISCARD;
+
+    m_atTopOfBlock = true;
+    m_atBottomOfBlock = false;
+
+    m_posMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(true) : 0;
+    m_negMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(false) : 0;
+
+    m_selfCollapsingBlockClearedFloat = false;
+    
+    m_topQuirk = m_bottomQuirk = m_determinedTopQuirk = false;
+}
+
+// -------------------------------------------------------------------------------------------------------
+
+RenderBlock::RenderBlock(Node* node)
+      : RenderFlow(node)
+      , m_floatingObjects(0)
+      , m_positionedObjects(0)
+      , m_maxMargin(0)
+      , m_overflowHeight(0)
+      , m_overflowWidth(0)
+      , m_overflowLeft(0)
+      , m_overflowTop(0)
+{
+}
+
+RenderBlock::~RenderBlock()
+{
+    delete m_floatingObjects;
+    delete m_positionedObjects;
+    delete m_maxMargin;
+    
+    if (m_hasColumns)
+        delete gColumnInfoMap->take(this);
+
+    if (gPercentHeightDescendantsMap) {
+        if (HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->take(this)) {
+            HashSet<RenderBox*>::iterator end = descendantSet->end();
+            for (HashSet<RenderBox*>::iterator descendant = descendantSet->begin(); descendant != end; ++descendant) {
+                HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->get(*descendant);
+                ASSERT(containerSet);
+                if (!containerSet)
+                    continue;
+                ASSERT(containerSet->contains(this));
+                containerSet->remove(this);
+                if (containerSet->isEmpty()) {
+                    gPercentHeightContainerMap->remove(*descendant);
+                    delete containerSet;
+                }
+            }
+            delete descendantSet;
+        }
+    }
+}
+
+void RenderBlock::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+{
+    setReplaced(newStyle->isDisplayReplacedType());
+    RenderFlow::styleWillChange(diff, newStyle);
+}
+
+void RenderBlock::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderFlow::styleDidChange(diff, oldStyle);
+
+    // FIXME: We could save this call when the change only affected non-inherited properties
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isAnonymousBlock()) {
+            RefPtr<RenderStyle> newStyle = RenderStyle::create();
+            newStyle->inheritFrom(style());
+            newStyle->setDisplay(BLOCK);
+            child->setStyle(newStyle.release());
+        }
+    }
+
+    m_lineHeight = -1;
+
+    // Update pseudos for :before and :after now.
+    if (!isAnonymous() && canHaveChildren()) {
+        updateBeforeAfterContent(RenderStyle::BEFORE);
+        updateBeforeAfterContent(RenderStyle::AFTER);
+    }
+    updateFirstLetter();
+}
+
+void RenderBlock::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild)
+{
+    // Make sure we don't append things after :after-generated content if we have it.
+    if (!beforeChild && isAfterContent(lastChild()))
+        beforeChild = lastChild();
+
+    bool madeBoxesNonInline = false;
+
+    // If the requested beforeChild is not one of our children, then this is because
+    // there is an anonymous container within this object that contains the beforeChild.
+    if (beforeChild && beforeChild->parent() != this) {
+        RenderObject* anonymousChild = beforeChild->parent();
+        ASSERT(anonymousChild);
+
+        while (anonymousChild->parent() != this)
+            anonymousChild = anonymousChild->parent();
+
+        ASSERT(anonymousChild->isAnonymous());
+
+        if (anonymousChild->isAnonymousBlock()) {
+            // Insert the child into the anonymous block box instead of here.
+            if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
+                beforeChild->parent()->addChild(newChild, beforeChild);
+            else
+                addChildToFlow(newChild, beforeChild->parent());
+            return;
+        }
+
+        ASSERT(anonymousChild->isTable());
+        if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP
+                || newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION
+                || newChild->isTableSection()
+                || newChild->isTableRow()
+                || newChild->isTableCell()) {
+            // Insert into the anonymous table.
+            anonymousChild->addChild(newChild, beforeChild);
+            return;
+        }
+
+        // Go on to insert before the anonymous table.
+        beforeChild = anonymousChild;
+    }
+
+    // A block has to either have all of its children inline, or all of its children as blocks.
+    // So, if our children are currently inline and a block child has to be inserted, we move all our
+    // inline children into anonymous block boxes.
+    if (m_childrenInline && !newChild->isInline() && !newChild->isFloatingOrPositioned()) {
+        // This is a block with inline content. Wrap the inline content in anonymous blocks.
+        makeChildrenNonInline(beforeChild);
+        madeBoxesNonInline = true;
+
+        if (beforeChild && beforeChild->parent() != this) {
+            beforeChild = beforeChild->parent();
+            ASSERT(beforeChild->isAnonymousBlock());
+            ASSERT(beforeChild->parent() == this);
+        }
+    } else if (!m_childrenInline && (newChild->isFloatingOrPositioned() || newChild->isInline())) {
+        // If we're inserting an inline child but all of our children are blocks, then we have to make sure
+        // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
+        // a new one is created and inserted into our list of children in the appropriate position.
+        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : lastChild();
+
+        if (afterChild && afterChild->isAnonymousBlock()) {
+            afterChild->addChild(newChild);
+            return;
+        }
+
+        if (newChild->isInline()) {
+            // No suitable existing anonymous box - create a new one.
+            RenderBlock* newBox = createAnonymousBlock();
+            RenderContainer::addChild(newBox, beforeChild);
+            newBox->addChild(newChild);
+            return;
+        }
+    }
+
+    RenderContainer::addChild(newChild, beforeChild);
+    // ### care about aligned stuff
+
+    if (madeBoxesNonInline && parent() && isAnonymousBlock())
+        parent()->removeLeftoverAnonymousBlock(this);
+    // this object may be dead here
+}
+
+static void getInlineRun(RenderObject* start, RenderObject* boundary,
+                         RenderObject*& inlineRunStart,
+                         RenderObject*& inlineRunEnd)
+{
+    // Beginning at |start| we find the largest contiguous run of inlines that
+    // we can.  We denote the run with start and end points, |inlineRunStart|
+    // and |inlineRunEnd|.  Note that these two values may be the same if
+    // we encounter only one inline.
+    //
+    // We skip any non-inlines we encounter as long as we haven't found any
+    // inlines yet.
+    //
+    // |boundary| indicates a non-inclusive boundary point.  Regardless of whether |boundary|
+    // is inline or not, we will not include it in a run with inlines before it.  It's as though we encountered
+    // a non-inline.
+    
+    // Start by skipping as many non-inlines as we can.
+    RenderObject * curr = start;
+    bool sawInline;
+    do {
+        while (curr && !(curr->isInline() || curr->isFloatingOrPositioned()))
+            curr = curr->nextSibling();
+        
+        inlineRunStart = inlineRunEnd = curr;
+        
+        if (!curr)
+            return; // No more inline children to be found.
+        
+        sawInline = curr->isInline();
+        
+        curr = curr->nextSibling();
+        while (curr && (curr->isInline() || curr->isFloatingOrPositioned()) && (curr != boundary)) {
+            inlineRunEnd = curr;
+            if (curr->isInline())
+                sawInline = true;
+            curr = curr->nextSibling();
+        }
+    } while (!sawInline);
+}
+
+void RenderBlock::deleteLineBoxTree()
+{
+    InlineFlowBox* line = m_firstLineBox;
+    InlineFlowBox* nextLine;
+    while (line) {
+        nextLine = line->nextFlowBox();
+        line->deleteLine(renderArena());
+        line = nextLine;
+    }
+    m_firstLineBox = m_lastLineBox = 0;
+}
+
+void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
+{    
+    // makeChildrenNonInline takes a block whose children are *all* inline and it
+    // makes sure that inline children are coalesced under anonymous
+    // blocks.  If |insertionPoint| is defined, then it represents the insertion point for
+    // the new block child that is causing us to have to wrap all the inlines.  This
+    // means that we cannot coalesce inlines before |insertionPoint| with inlines following
+    // |insertionPoint|, because the new child is going to be inserted in between the inlines,
+    // splitting them.
+    ASSERT(isInlineBlockOrInlineTable() || !isInline());
+    ASSERT(!insertionPoint || insertionPoint->parent() == this);
+
+    m_childrenInline = false;
+
+    RenderObject *child = firstChild();
+    if (!child)
+        return;
+
+    deleteLineBoxTree();
+
+    while (child) {
+        RenderObject *inlineRunStart, *inlineRunEnd;
+        getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
+
+        if (!inlineRunStart)
+            break;
+
+        child = inlineRunEnd->nextSibling();
+
+        RenderBlock* box = createAnonymousBlock();
+        insertChildNode(box, inlineRunStart);
+        RenderObject* o = inlineRunStart;
+        while(o != inlineRunEnd)
+        {
+            RenderObject* no = o;
+            o = no->nextSibling();
+            box->moveChildNode(no);
+        }
+        box->moveChildNode(inlineRunEnd);
+    }
+
+#ifndef NDEBUG
+    for (RenderObject *c = firstChild(); c; c = c->nextSibling())
+        ASSERT(!c->isInline());
+#endif
+
+    repaint();
+}
+
+void RenderBlock::removeChild(RenderObject *oldChild)
+{
+    // If this child is a block, and if our previous and next siblings are
+    // both anonymous blocks with inline content, then we can go ahead and
+    // fold the inline content back together.
+    RenderObject* prev = oldChild->previousSibling();
+    RenderObject* next = oldChild->nextSibling();
+    bool canDeleteAnonymousBlocks = !documentBeingDestroyed() && !isInline() && !oldChild->isInline() && 
+                                    !oldChild->continuation() && 
+                                    (!prev || (prev->isAnonymousBlock() && prev->childrenInline())) &&
+                                    (!next || (next->isAnonymousBlock() && next->childrenInline()));
+    if (canDeleteAnonymousBlocks && prev && next) {
+        // Take all the children out of the |next| block and put them in
+        // the |prev| block.
+        prev->setNeedsLayoutAndPrefWidthsRecalc();
+        RenderObject* o = next->firstChild();
+        while (o) {
+            RenderObject* no = o;
+            o = no->nextSibling();
+            prev->moveChildNode(no);
+        }
+ 
+        RenderBlock* nextBlock = static_cast<RenderBlock*>(next);
+        nextBlock->deleteLineBoxTree();
+        
+        // Nuke the now-empty block.
+        next->destroy();
+    }
+
+    RenderFlow::removeChild(oldChild);
+
+    RenderObject* child = prev ? prev : next;
+    if (canDeleteAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && !isFlexibleBox()) {
+        // The removal has knocked us down to containing only a single anonymous
+        // box.  We can go ahead and pull the content right back up into our
+        // box.
+        setNeedsLayoutAndPrefWidthsRecalc();
+        RenderBlock* anonBlock = static_cast<RenderBlock*>(removeChildNode(child, false));
+        m_childrenInline = true;
+        RenderObject* o = anonBlock->firstChild();
+        while (o) {
+            RenderObject* no = o;
+            o = no->nextSibling();
+            moveChildNode(no);
+        }
+
+        // Delete the now-empty block's lines and nuke it.
+        anonBlock->deleteLineBoxTree();
+        anonBlock->destroy();
+    }
+}
+
+int RenderBlock::overflowHeight(bool includeInterior) const
+{
+    if (!includeInterior && hasOverflowClip()) {
+        int shadowHeight = 0;
+        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
+            shadowHeight = max(boxShadow->y + boxShadow->blur, shadowHeight);
+        int height = m_height + shadowHeight;
+        if (hasReflection())
+            height = max(height, reflectionBox().bottom());
+        return height;
+    }
+    return m_overflowHeight;
+}
+
+int RenderBlock::overflowWidth(bool includeInterior) const
+{
+    if (!includeInterior && hasOverflowClip()) {
+        int shadowWidth = 0;
+        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
+            shadowWidth = max(boxShadow->x + boxShadow->blur, shadowWidth);
+        int width = m_width + shadowWidth;
+        if (hasReflection())
+            width = max(width, reflectionBox().right());
+        return width;
+    }
+    return m_overflowWidth;
+}
+
+int RenderBlock::overflowLeft(bool includeInterior) const
+{
+    if (!includeInterior && hasOverflowClip()) {
+        int shadowLeft = 0;
+        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
+            shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft);
+        int left = shadowLeft;
+        if (hasReflection())
+            left = min(left, reflectionBox().x());
+        return left;
+    }
+    return m_overflowLeft;
+}
+
+int RenderBlock::overflowTop(bool includeInterior) const
+{
+    if (!includeInterior && hasOverflowClip()) {
+        int shadowTop = 0;
+        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
+            shadowTop = min(boxShadow->y - boxShadow->blur, shadowTop);
+        int top = shadowTop;
+        if (hasReflection())
+            top = min(top, reflectionBox().y());
+        return top;
+    }
+    return m_overflowTop;
+}
+
+IntRect RenderBlock::overflowRect(bool includeInterior) const
+{
+    if (!includeInterior && hasOverflowClip()) {
+        IntRect box = borderBox();
+        int shadowLeft = 0;
+        int shadowRight = 0;
+        int shadowTop = 0;
+        int shadowBottom = 0;
+
+        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+            shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft);
+            shadowRight = max(boxShadow->x + boxShadow->blur, shadowRight);
+            shadowTop = min(boxShadow->y - boxShadow->blur, shadowTop);
+            shadowBottom = max(boxShadow->y + boxShadow->blur, shadowBottom);
+        }
+
+        box.move(shadowLeft, shadowTop);
+        box.setWidth(box.width() - shadowLeft + shadowRight);
+        box.setHeight(box.height() - shadowTop + shadowBottom);
+
+        if (hasReflection()) {
+            IntRect reflection(reflectionBox());
+            int reflectTop = min(box.y(), reflection.y());
+            int reflectBottom = max(box.bottom(), reflection.bottom());
+            box.setHeight(reflectBottom - reflectTop);
+            box.setY(reflectTop);
+            
+            int reflectLeft = min(box.x(), reflection.x());
+            int reflectRight = max(box.right(), reflection.right());
+            box.setWidth(reflectRight - reflectLeft);
+            box.setX(reflectLeft);
+        }
+        return box;
+    }
+
+    if (!includeInterior && hasOverflowClip())
+        return borderBox();
+    int l = overflowLeft(includeInterior);
+    int t = min(overflowTop(includeInterior), -borderTopExtra());
+    return IntRect(l, t, overflowWidth(includeInterior) - l, max(overflowHeight(includeInterior), height() + borderBottomExtra()) - t);
+}
+
+bool RenderBlock::isSelfCollapsingBlock() const
+{
+    // We are not self-collapsing if we
+    // (a) have a non-zero height according to layout (an optimization to avoid wasting time)
+    // (b) are a table,
+    // (c) have border/padding,
+    // (d) have a min-height
+    // (e) have specified that one of our margins can't collapse using a CSS extension
+    if (m_height > 0 ||
+        isTable() || (borderBottom() + paddingBottom() + borderTop() + paddingTop()) != 0 ||
+        style()->minHeight().isPositive() || 
+        style()->marginTopCollapse() == MSEPARATE || style()->marginBottomCollapse() == MSEPARATE)
+        return false;
+
+    bool hasAutoHeight = style()->height().isAuto();
+    if (style()->height().isPercent() && !style()->htmlHacks()) {
+        hasAutoHeight = true;
+        for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) {
+            if (cb->style()->height().isFixed() || cb->isTableCell())
+                hasAutoHeight = false;
+        }
+    }
+
+    // If the height is 0 or auto, then whether or not we are a self-collapsing block depends
+    // on whether we have content that is all self-collapsing or not.
+    if (hasAutoHeight || ((style()->height().isFixed() || style()->height().isPercent()) && style()->height().isZero())) {
+        // If the block has inline children, see if we generated any line boxes.  If we have any
+        // line boxes, then we can't be self-collapsing, since we have content.
+        if (childrenInline())
+            return !firstLineBox();
+        
+        // Whether or not we collapse is dependent on whether all our normal flow children
+        // are also self-collapsing.
+        for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+            if (child->isFloatingOrPositioned())
+                continue;
+            if (!child->isSelfCollapsingBlock())
+                return false;
+        }
+        return true;
+    }
+    return false;
+}
+
+void RenderBlock::layout()
+{
+    // Update our first letter info now.
+    updateFirstLetter();
+
+    // Table cells call layoutBlock directly, so don't add any logic here.  Put code into
+    // layoutBlock().
+    layoutBlock(false);
+    
+    // It's safe to check for control clip here, since controls can never be table cells.
+    if (hasControlClip()) {
+        // Because of the lightweight clip, there can never be any overflow from children.
+        m_overflowWidth = m_width;
+        m_overflowHeight = m_height;
+        m_overflowLeft = 0;
+        m_overflowTop = 0;
+    }
+}
+
+void RenderBlock::layoutBlock(bool relayoutChildren)
+{
+    ASSERT(needsLayout());
+
+    if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can
+        return;                                      // cause us to come in here.  Just bail.
+
+    if (!relayoutChildren && layoutOnlyPositionedObjects())
+        return;
+
+    IntRect oldBounds;
+    IntRect oldOutlineBox;
+    bool checkForRepaint = m_everHadLayout && checkForRepaintDuringLayout();
+    if (checkForRepaint) {
+        oldBounds = absoluteClippedOverflowRect();
+        oldOutlineBox = absoluteOutlineBox();
+    }
+
+    bool hadColumns = m_hasColumns;
+    if (!hadColumns && !hasReflection())
+        view()->pushLayoutState(this, IntSize(xPos(), yPos()));
+    else
+        view()->disableLayoutState();
+
+    int oldWidth = m_width;
+    int oldColumnWidth = desiredColumnWidth();
+
+#ifdef ANDROID_LAYOUT
+    int oldVisibleWidth = m_visibleWidth;
+#endif
+
+    calcWidth();
+    calcColumnWidth();
+
+    m_overflowWidth = m_width;
+    m_overflowLeft = 0;
+
+    if (oldWidth != m_width || oldColumnWidth != desiredColumnWidth())
+        relayoutChildren = true;
+
+#ifdef ANDROID_LAYOUT
+    const Settings* settings = document()->settings();
+    ASSERT(settings);
+    if (oldVisibleWidth != m_visibleWidth
+            && settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
+        relayoutChildren = true;
+#endif
+
+    clearFloats();
+
+    int previousHeight = m_height;
+    m_height = 0;
+    m_overflowHeight = 0;
+
+    // We use four values, maxTopPos, maxPosNeg, maxBottomPos, and maxBottomNeg, to track
+    // our current maximal positive and negative margins.  These values are used when we
+    // are collapsed with adjacent blocks, so for example, if you have block A and B
+    // collapsing together, then you'd take the maximal positive margin from both A and B
+    // and subtract it from the maximal negative margin from both A and B to get the
+    // true collapsed margin.  This algorithm is recursive, so when we finish layout()
+    // our block knows its current maximal positive/negative values.
+    //
+    // Start out by setting our margin values to our current margins.  Table cells have
+    // no margins, so we don't fill in the values for table cells.
+    bool isCell = isTableCell();
+    if (!isCell) {
+        initMaxMarginValues();
+
+        m_topMarginQuirk = style()->marginTop().quirk();
+        m_bottomMarginQuirk = style()->marginBottom().quirk();
+
+        Node* node = element();
+        if (node && node->hasTagName(formTag) && static_cast<HTMLFormElement*>(node)->isMalformed()) {
+            // See if this form is malformed (i.e., unclosed). If so, don't give the form
+            // a bottom margin.
+            setMaxBottomMargins(0, 0);
+        }
+    }
+
+    // For overflow:scroll blocks, ensure we have both scrollbars in place always.
+    if (scrollsOverflow()) {
+        if (style()->overflowX() == OSCROLL)
+            m_layer->setHasHorizontalScrollbar(true);
+        if (style()->overflowY() == OSCROLL)
+            m_layer->setHasVerticalScrollbar(true);
+    }
+
+    int repaintTop = 0;
+    int repaintBottom = 0;
+    int maxFloatBottom = 0;
+    if (childrenInline())
+        layoutInlineChildren(relayoutChildren, repaintTop, repaintBottom);
+    else
+        layoutBlockChildren(relayoutChildren, maxFloatBottom);
+
+    // Expand our intrinsic height to encompass floats.
+    int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
+    if (floatBottom() > (m_height - toAdd) && (isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() ||
+                                    (parent() && parent()->isFlexibleBox() || m_hasColumns)))
+        m_height = floatBottom() + toAdd;
+    
+    // Now lay out our columns within this intrinsic height, since they can slightly affect the intrinsic height as
+    // we adjust for clean column breaks.
+    int singleColumnBottom = layoutColumns();
+
+    // Calculate our new height.
+    int oldHeight = m_height;
+    calcHeight();
+    if (oldHeight != m_height) {
+        if (oldHeight > m_height && maxFloatBottom > m_height && !childrenInline()) {
+            // One of our children's floats may have become an overhanging float for us. We need to look for it.
+            for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+                if (child->isBlockFlow() && !child->isFloatingOrPositioned()) {
+                    RenderBlock* block = static_cast<RenderBlock*>(child);
+                    if (block->floatBottom() + block->yPos() > m_height)
+                        addOverhangingFloats(block, -block->xPos(), -block->yPos(), false);
+                }
+            }
+        }
+        // We have to rebalance columns to the new height.
+        layoutColumns(singleColumnBottom);
+
+        // If the block got expanded in size, then increase our overflowheight to match.
+        if (m_overflowHeight > m_height)
+            m_overflowHeight -= toAdd;
+        if (m_overflowHeight < m_height)
+            m_overflowHeight = m_height;
+    }
+    if (previousHeight != m_height)
+        relayoutChildren = true;
+
+    // Some classes of objects (floats and fieldsets with no specified heights and table cells) expand to encompass
+    // overhanging floats.
+    if (hasOverhangingFloats() && expandsToEncloseOverhangingFloats()) {
+        m_height = floatBottom();
+        m_height += borderBottom() + paddingBottom();
+    }
+
+    if ((isCell || isInline() || isFloatingOrPositioned() || isRoot()) && !hasOverflowClip() && !hasControlClip())
+        addVisualOverflow(floatRect());
+
+    layoutPositionedObjects(relayoutChildren || isRoot());
+
+    positionListMarker();
+
+    // Always ensure our overflow width/height are at least as large as our width/height.
+    m_overflowWidth = max(m_overflowWidth, m_width);
+    m_overflowHeight = max(m_overflowHeight, m_height);
+
+    if (!hasOverflowClip()) {
+        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+            m_overflowLeft = min(m_overflowLeft, boxShadow->x - boxShadow->blur);
+            m_overflowWidth = max(m_overflowWidth, m_width + boxShadow->x + boxShadow->blur);
+            m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur);
+            m_overflowHeight = max(m_overflowHeight, m_height + boxShadow->y + boxShadow->blur);
+        }
+        
+        if (hasReflection()) {
+            m_overflowTop = min(m_overflowTop, reflectionBox().y());
+            m_overflowHeight = max(m_overflowHeight, reflectionBox().bottom());
+        }
+    }
+
+    if (!hadColumns && !hasReflection())
+        view()->popLayoutState();
+    else
+        view()->enableLayoutState();
+
+    // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
+    // we overflow or not.
+    if (hasOverflowClip())
+        m_layer->updateScrollInfoAfterLayout();
+
+    // Repaint with our new bounds if they are different from our old bounds.
+    bool didFullRepaint = false;
+    if (checkForRepaint)
+        didFullRepaint = repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+    if (!didFullRepaint && repaintTop != repaintBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
+        IntRect repaintRect(m_overflowLeft, repaintTop, m_overflowWidth - m_overflowLeft, repaintBottom - repaintTop);
+
+        // FIXME: Deal with multiple column repainting.  We have to split the repaint
+        // rect up into multiple rects if it spans columns.
+
+        repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline));
+        
+        if (hasOverflowClip()) {
+            // Adjust repaint rect for scroll offset
+            int x = repaintRect.x();
+            int y = repaintRect.y();
+            layer()->subtractScrollOffset(x, y);
+            repaintRect.setX(x);
+            repaintRect.setY(y);
+
+            // Don't allow this rect to spill out of our overflow box.
+            repaintRect.intersect(IntRect(0, 0, m_width, m_height));
+        }
+
+        // Make sure the rect is still non-empty after intersecting for overflow above
+        if (!repaintRect.isEmpty()) {
+            repaintRectangle(repaintRect); // We need to do a partial repaint of our content.
+            if (hasReflection())
+                layer()->reflection()->repaintRectangle(repaintRect);
+        }
+    }
+    setNeedsLayout(false);
+}
+
+void RenderBlock::adjustPositionedBlock(RenderObject* child, const MarginInfo& marginInfo)
+{
+    if (child->hasStaticX()) {
+        if (style()->direction() == LTR)
+            child->setStaticX(borderLeft() + paddingLeft());
+        else
+            child->setStaticX(borderRight() + paddingRight());
+    }
+
+    if (child->hasStaticY()) {
+        int y = m_height;
+        if (!marginInfo.canCollapseWithTop()) {
+            child->calcVerticalMargins();
+            int marginTop = child->marginTop();
+            int collapsedTopPos = marginInfo.posMargin();
+            int collapsedTopNeg = marginInfo.negMargin();
+            if (marginTop > 0) {
+                if (marginTop > collapsedTopPos)
+                    collapsedTopPos = marginTop;
+            } else {
+                if (-marginTop > collapsedTopNeg)
+                    collapsedTopNeg = -marginTop;
+            }
+            y += (collapsedTopPos - collapsedTopNeg) - marginTop;
+        }
+        child->setStaticY(y);
+    }
+}
+
+void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
+{
+    // The float should be positioned taking into account the bottom margin
+    // of the previous flow.  We add that margin into the height, get the
+    // float positioned properly, and then subtract the margin out of the
+    // height again.  In the case of self-collapsing blocks, we always just
+    // use the top margins, since the self-collapsing block collapsed its
+    // own bottom margin into its top margin.
+    //
+    // Note also that the previous flow may collapse its margin into the top of
+    // our block.  If this is the case, then we do not add the margin in to our
+    // height when computing the position of the float.   This condition can be tested
+    // for by simply calling canCollapseWithTop.  See
+    // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
+    // an example of this scenario.
+    int marginOffset = marginInfo.canCollapseWithTop() ? 0 : marginInfo.margin();
+    m_height += marginOffset;
+    positionNewFloats();
+    m_height -= marginOffset;
+}
+
+RenderObject* RenderBlock::handleSpecialChild(RenderObject* child, const MarginInfo& marginInfo, CompactInfo& compactInfo, bool& handled)
+{
+    // Handle positioned children first.
+    RenderObject* next = handlePositionedChild(child, marginInfo, handled);
+    if (handled) return next;
+    
+    // Handle floating children next.
+    next = handleFloatingChild(child, marginInfo, handled);
+    if (handled) return next;
+
+    // See if we have a compact element.  If we do, then try to tuck the compact element into the margin space of the next block.
+    next = handleCompactChild(child, compactInfo, handled);
+    if (handled) return next;
+
+    // Finally, see if we have a run-in element.
+    return handleRunInChild(child, handled);
+}
+
+
+RenderObject* RenderBlock::handlePositionedChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
+{
+    if (child->isPositioned()) {
+        handled = true;
+        child->containingBlock()->insertPositionedObject(child);
+        adjustPositionedBlock(child, marginInfo);
+        return child->nextSibling();
+    }
+
+    return 0;
+}
+
+RenderObject* RenderBlock::handleFloatingChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
+{
+    if (child->isFloating()) {
+        handled = true;
+        insertFloatingObject(child);
+        adjustFloatingBlock(marginInfo);
+        return child->nextSibling();
+    }
+    
+    return 0;
+}
+
+RenderObject* RenderBlock::handleCompactChild(RenderObject* child, CompactInfo& compactInfo, bool& handled)
+{
+    // FIXME: We only deal with one compact at a time.  It is unclear what should be
+    // done if multiple contiguous compacts are encountered.  For now we assume that
+    // compact A followed by another compact B should simply be treated as block A.
+    if (child->isCompact() && !compactInfo.compact() && (child->childrenInline() || child->isReplaced())) {
+        // Get the next non-positioned/non-floating RenderBlock.
+        RenderObject* next = child->nextSibling();
+        RenderObject* curr = next;
+        while (curr && curr->isFloatingOrPositioned())
+            curr = curr->nextSibling();
+        if (curr && curr->isRenderBlock() && !curr->isCompact() && !curr->isRunIn()) {
+            curr->calcWidth(); // So that horizontal margins are correct.
+                               
+            child->setInline(true); // Need to compute the margins/width for the child as though it is an inline, so that it won't try to puff up the margins to
+                                    // fill the containing block width.
+            child->calcWidth();
+            int childMargins = child->marginLeft() + child->marginRight();
+            int margin = style()->direction() == LTR ? curr->marginLeft() : curr->marginRight();
+            if (margin >= (childMargins + child->maxPrefWidth())) {
+                // The compact will fit in the margin.
+                handled = true;
+                compactInfo.set(child, curr);
+                child->setPos(0,0); // This position will be updated to reflect the compact's
+                                    // desired position and the line box for the compact will
+                                    // pick that position up.
+                
+                // Remove the child.
+                RenderObject* next = child->nextSibling();
+                removeChildNode(child);
+                
+                // Now insert the child under |curr|.
+                curr->insertChildNode(child, curr->firstChild());
+                return next;
+            }
+            else
+                child->setInline(false); // We didn't fit, so we remain a block-level element.
+        }
+    }
+    return 0;
+}
+
+void RenderBlock::insertCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo)
+{
+    if (compactInfo.matches(child)) {
+        // We have a compact child to squeeze in.
+        RenderObject* compactChild = compactInfo.compact();
+        int compactXPos = borderLeft() + paddingLeft() + compactChild->marginLeft();
+        if (style()->direction() == RTL) {
+            compactChild->calcWidth(); // have to do this because of the capped maxwidth
+            compactXPos = width() - borderRight() - paddingRight() - marginRight() -
+                compactChild->width() - compactChild->marginRight();
+        }
+        compactXPos -= child->xPos(); // Put compactXPos into the child's coordinate space.
+        compactChild->setPos(compactXPos, compactChild->yPos()); // Set the x position.
+        compactInfo.clear();
+    }
+}
+
+RenderObject* RenderBlock::handleRunInChild(RenderObject* child, bool& handled)
+{
+    // See if we have a run-in element with inline children.  If the
+    // children aren't inline, then just treat the run-in as a normal
+    // block.
+    if (child->isRunIn() && (child->childrenInline() || child->isReplaced())) {
+        // Get the next non-positioned/non-floating RenderBlock.
+        RenderObject* curr = child->nextSibling();
+        while (curr && curr->isFloatingOrPositioned())
+            curr = curr->nextSibling();
+        if (curr && (curr->isRenderBlock() && curr->childrenInline() && !curr->isCompact() && !curr->isRunIn())) {
+            // The block acts like an inline, so just null out its
+            // position.
+            handled = true;
+            child->setInline(true);
+            child->setPos(0,0);
+            
+            // Remove the child.
+            RenderObject* next = child->nextSibling();
+            removeChildNode(child);
+            
+            // Now insert the child under |curr|.
+            curr->insertChildNode(child, curr->firstChild());
+            return next;
+        }
+    }
+    return 0;
+}
+
+void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, int yPosEstimate)
+{
+    // Get our max pos and neg top margins.
+    int posTop = child->maxTopMargin(true);
+    int negTop = child->maxTopMargin(false);
+
+    // For self-collapsing blocks, collapse our bottom margins into our
+    // top to get new posTop and negTop values.
+    if (child->isSelfCollapsingBlock()) {
+        posTop = max(posTop, child->maxBottomMargin(true));
+        negTop = max(negTop, child->maxBottomMargin(false));
+    }
+    
+    // See if the top margin is quirky. We only care if this child has
+    // margins that will collapse with us.
+    bool topQuirk = child->isTopMarginQuirk() || style()->marginTopCollapse() == MDISCARD;
+
+    if (marginInfo.canCollapseWithTop()) {
+        // This child is collapsing with the top of the
+        // block.  If it has larger margin values, then we need to update
+        // our own maximal values.
+        if (!style()->htmlHacks() || !marginInfo.quirkContainer() || !topQuirk)
+            setMaxTopMargins(max(posTop, maxTopPosMargin()), max(negTop, maxTopNegMargin()));
+
+        // The minute any of the margins involved isn't a quirk, don't
+        // collapse it away, even if the margin is smaller (www.webreference.com
+        // has an example of this, a <dt> with 0.8em author-specified inside
+        // a <dl> inside a <td>.
+        if (!marginInfo.determinedTopQuirk() && !topQuirk && (posTop-negTop)) {
+            m_topMarginQuirk = false;
+            marginInfo.setDeterminedTopQuirk(true);
+        }
+
+        if (!marginInfo.determinedTopQuirk() && topQuirk && marginTop() == 0)
+            // We have no top margin and our top child has a quirky margin.
+            // We will pick up this quirky margin and pass it through.
+            // This deals with the <td><div><p> case.
+            // Don't do this for a block that split two inlines though.  You do
+            // still apply margins in this case.
+            m_topMarginQuirk = true;
+    }
+
+    if (marginInfo.quirkContainer() && marginInfo.atTopOfBlock() && (posTop - negTop))
+        marginInfo.setTopQuirk(topQuirk);
+
+    int ypos = m_height;
+    if (child->isSelfCollapsingBlock()) {
+        // This child has no height.  We need to compute our
+        // position before we collapse the child's margins together,
+        // so that we can get an accurate position for the zero-height block.
+        int collapsedTopPos = max(marginInfo.posMargin(), child->maxTopMargin(true));
+        int collapsedTopNeg = max(marginInfo.negMargin(), child->maxTopMargin(false));
+        marginInfo.setMargin(collapsedTopPos, collapsedTopNeg);
+        
+        // Now collapse the child's margins together, which means examining our
+        // bottom margin values as well. 
+        marginInfo.setPosMarginIfLarger(child->maxBottomMargin(true));
+        marginInfo.setNegMarginIfLarger(child->maxBottomMargin(false));
+
+        if (!marginInfo.canCollapseWithTop())
+            // We need to make sure that the position of the self-collapsing block
+            // is correct, since it could have overflowing content
+            // that needs to be positioned correctly (e.g., a block that
+            // had a specified height of 0 but that actually had subcontent).
+            ypos = m_height + collapsedTopPos - collapsedTopNeg;
+    }
+    else {
+        if (child->style()->marginTopCollapse() == MSEPARATE) {
+            m_height += marginInfo.margin() + child->marginTop();
+            ypos = m_height;
+        }
+        else if (!marginInfo.atTopOfBlock() ||
+            (!marginInfo.canCollapseTopWithChildren()
+             && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.topQuirk()))) {
+            // We're collapsing with a previous sibling's margins and not
+            // with the top of the block.
+            m_height += max(marginInfo.posMargin(), posTop) - max(marginInfo.negMargin(), negTop);
+            ypos = m_height;
+        }
+
+        marginInfo.setPosMargin(child->maxBottomMargin(true));
+        marginInfo.setNegMargin(child->maxBottomMargin(false));
+
+        if (marginInfo.margin())
+            marginInfo.setBottomQuirk(child->isBottomMarginQuirk() || style()->marginBottomCollapse() == MDISCARD);
+
+        marginInfo.setSelfCollapsingBlockClearedFloat(false);
+    }
+
+    view()->addLayoutDelta(IntSize(0, yPosEstimate - ypos));
+    child->setPos(child->xPos(), ypos);
+    if (ypos != yPosEstimate) {
+        if (child->shrinkToAvoidFloats())
+            // The child's width depends on the line width.
+            // When the child shifts to clear an item, its width can
+            // change (because it has more available line width).
+            // So go ahead and mark the item as dirty.
+            child->setChildNeedsLayout(true, false);
+
+        if (!child->avoidsFloats() && child->containsFloats())
+            child->markAllDescendantsWithFloatsForLayout();
+
+        // Our guess was wrong. Make the child lay itself out again.
+        child->layoutIfNeeded();
+    }
+}
+
+void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin)
+{
+    int heightIncrease = getClearDelta(child);
+    if (!heightIncrease)
+        return;
+
+    // The child needs to be lowered.  Move the child so that it just clears the float.
+    view()->addLayoutDelta(IntSize(0, -heightIncrease));
+    child->setPos(child->xPos(), child->yPos() + heightIncrease);
+
+    if (child->isSelfCollapsingBlock()) {
+        // For self-collapsing blocks that clear, they can still collapse their
+        // margins with following siblings.  Reset the current margins to represent
+        // the self-collapsing block's margins only.
+        marginInfo.setPosMargin(max(child->maxTopMargin(true), child->maxBottomMargin(true)));
+        marginInfo.setNegMargin(max(child->maxTopMargin(false), child->maxBottomMargin(false)));
+        
+        // Adjust our height such that we are ready to be collapsed with subsequent siblings.
+        m_height = child->yPos() - max(0, marginInfo.margin());
+        
+        // Set a flag that we cleared a float so that we know both to increase the height of the block
+        // to compensate for the clear and to avoid collapsing our margins with the parent block's
+        // bottom margin.
+        marginInfo.setSelfCollapsingBlockClearedFloat(true);
+    } else
+        // Increase our height by the amount we had to clear.
+        m_height += heightIncrease;
+    
+    if (marginInfo.canCollapseWithTop()) {
+        // We can no longer collapse with the top of the block since a clear
+        // occurred.  The empty blocks collapse into the cleared block.
+        // FIXME: This isn't quite correct.  Need clarification for what to do
+        // if the height the cleared block is offset by is smaller than the
+        // margins involved.
+        setMaxTopMargins(oldTopPosMargin, oldTopNegMargin);
+        marginInfo.setAtTopOfBlock(false);
+    }
+
+    // If our value of clear caused us to be repositioned vertically to be
+    // underneath a float, we might have to do another layout to take into account
+    // the extra space we now have available.
+    if (child->shrinkToAvoidFloats())
+        // The child's width depends on the line width.
+        // When the child shifts to clear an item, its width can
+        // change (because it has more available line width).
+        // So go ahead and mark the item as dirty.
+        child->setChildNeedsLayout(true, false);
+    if (!child->avoidsFloats() && child->containsFloats())
+        child->markAllDescendantsWithFloatsForLayout();
+    child->layoutIfNeeded();
+}
+
+int RenderBlock::estimateVerticalPosition(RenderObject* child, const MarginInfo& marginInfo)
+{
+    // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological
+    // relayout if there are intruding floats.
+    int yPosEstimate = m_height;
+    if (!marginInfo.canCollapseWithTop()) {
+        int childMarginTop = child->selfNeedsLayout() ? child->marginTop() : child->collapsedMarginTop();
+        yPosEstimate += max(marginInfo.margin(), childMarginTop);
+    }
+    return yPosEstimate;
+}
+
+void RenderBlock::determineHorizontalPosition(RenderObject* child)
+{
+    if (style()->direction() == LTR) {
+        int xPos = borderLeft() + paddingLeft();
+        
+        // Add in our left margin.
+        int chPos = xPos + child->marginLeft();
+        
+        // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats.  They need
+        // to shift over as necessary to dodge any floats that might get in the way.
+        if (child->avoidsFloats()) {
+            int leftOff = leftOffset(m_height);
+            if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginLeft().type() != Auto) {
+                if (child->marginLeft() < 0)
+                    leftOff += child->marginLeft();
+                chPos = max(chPos, leftOff); // Let the float sit in the child's margin if it can fit.
+            }
+            else if (leftOff != xPos) {
+                // The object is shifting right. The object might be centered, so we need to
+                // recalculate our horizontal margins. Note that the containing block content
+                // width computation will take into account the delta between |leftOff| and |xPos|
+                // so that we can just pass the content width in directly to the |calcHorizontalMargins|
+                // function.
+                static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
+                chPos = leftOff + child->marginLeft();
+            }
+        }
+        view()->addLayoutDelta(IntSize(child->xPos() - chPos, 0));
+        child->setPos(chPos, child->yPos());
+    } else {
+        int xPos = m_width - borderRight() - paddingRight() - verticalScrollbarWidth();
+        int chPos = xPos - (child->width() + child->marginRight());
+        if (child->avoidsFloats()) {
+            int rightOff = rightOffset(m_height);
+            if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginRight().type() != Auto) {
+                if (child->marginRight() < 0)
+                    rightOff -= child->marginRight();
+                chPos = min(chPos, rightOff - child->width()); // Let the float sit in the child's margin if it can fit.
+            } else if (rightOff != xPos) {
+                // The object is shifting left. The object might be centered, so we need to
+                // recalculate our horizontal margins. Note that the containing block content
+                // width computation will take into account the delta between |rightOff| and |xPos|
+                // so that we can just pass the content width in directly to the |calcHorizontalMargins|
+                // function.
+                static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
+                chPos = rightOff - child->marginRight() - child->width();
+            }
+        }
+        view()->addLayoutDelta(IntSize(child->xPos() - chPos, 0));
+        child->setPos(chPos, child->yPos());
+    }
+}
+
+void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
+{
+    if (marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()) {
+        // Update our max pos/neg bottom margins, since we collapsed our bottom margins
+        // with our children.
+        setMaxBottomMargins(max(maxBottomPosMargin(), marginInfo.posMargin()), max(maxBottomNegMargin(), marginInfo.negMargin()));
+
+        if (!marginInfo.bottomQuirk())
+            m_bottomMarginQuirk = false;
+
+        if (marginInfo.bottomQuirk() && marginBottom() == 0)
+            // We have no bottom margin and our last child has a quirky margin.
+            // We will pick up this quirky margin and pass it through.
+            // This deals with the <td><div><p> case.
+            m_bottomMarginQuirk = true;
+    }
+}
+
+void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo)
+{
+    // If our last flow was a self-collapsing block that cleared a float, then we don't
+    // collapse it with the bottom of the block.
+    if (!marginInfo.selfCollapsingBlockClearedFloat())
+        marginInfo.setAtBottomOfBlock(true);
+    else {
+        // We have to special case the negative margin situation (where the collapsed
+        // margin of the self-collapsing block is negative), since there's no need
+        // to make an adjustment in that case.
+        if (marginInfo.margin() < 0)
+            marginInfo.clearMargin();
+    }
+
+    // If we can't collapse with children then go ahead and add in the bottom margin.
+    if (!marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()
+        && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.bottomQuirk()))
+        m_height += marginInfo.margin();
+        
+    // Now add in our bottom border/padding.
+    m_height += bottom;
+
+    // Negative margins can cause our height to shrink below our minimal height (border/padding).
+    // If this happens, ensure that the computed height is increased to the minimal height.
+    m_height = max(m_height, top + bottom);
+
+    // Always make sure our overflow height is at least our height.
+    m_overflowHeight = max(m_height, m_overflowHeight);
+
+    // Update our bottom collapsed margin info.
+    setCollapsedBottomMargin(marginInfo);
+}
+
+void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom)
+{
+    if (gPercentHeightDescendantsMap) {
+        if (HashSet<RenderBox*>* descendants = gPercentHeightDescendantsMap->get(this)) {
+            HashSet<RenderBox*>::iterator end = descendants->end();
+            for (HashSet<RenderBox*>::iterator it = descendants->begin(); it != end; ++it) {
+                RenderBox* box = *it;
+                while (box != this) {
+                    if (box->normalChildNeedsLayout())
+                        break;
+                    box->setChildNeedsLayout(true, false);
+                    box = box->containingBlock();
+                    ASSERT(box);
+                    if (!box)
+                        break;
+                }
+            }
+        }
+    }
+
+    int top = borderTop() + paddingTop();
+    int bottom = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
+
+    m_height = m_overflowHeight = top;
+
+    // The margin struct caches all our current margin collapsing state.  The compact struct caches state when we encounter compacts,
+    MarginInfo marginInfo(this, top, bottom);
+    CompactInfo compactInfo;
+
+    // Fieldsets need to find their legend and position it inside the border of the object.
+    // The legend then gets skipped during normal layout.
+    RenderObject* legend = layoutLegend(relayoutChildren);
+
+    int previousFloatBottom = 0;
+    maxFloatBottom = 0;
+
+    RenderObject* child = firstChild();
+    while (child) {
+        if (legend == child) {
+            child = child->nextSibling();
+            continue; // Skip the legend, since it has already been positioned up in the fieldset's border.
+        }
+
+        int oldTopPosMargin = maxTopPosMargin();
+        int oldTopNegMargin = maxTopNegMargin();
+
+        // Make sure we layout children if they need it.
+        // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
+        // an auto value.  Add a method to determine this, so that we can avoid the relayout.
+        if (relayoutChildren || ((child->style()->height().isPercent() || child->style()->minHeight().isPercent() || child->style()->maxHeight().isPercent()) && !isRenderView()))
+            child->setChildNeedsLayout(true, false);
+
+        // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
+        if (relayoutChildren && (child->style()->paddingLeft().isPercent() || child->style()->paddingRight().isPercent()))
+            child->setPrefWidthsDirty(true, false);
+
+        // Handle the four types of special elements first.  These include positioned content, floating content, compacts and
+        // run-ins.  When we encounter these four types of objects, we don't actually lay them out as normal flow blocks.
+        bool handled = false;
+        RenderObject* next = handleSpecialChild(child, marginInfo, compactInfo, handled);
+        if (handled) {
+            child = next;
+            continue;
+        }
+
+        // The child is a normal flow object.  Compute its vertical margins now.
+        child->calcVerticalMargins();
+
+        // Do not allow a collapse if the margin top collapse style is set to SEPARATE.
+        if (child->style()->marginTopCollapse() == MSEPARATE) {
+            marginInfo.setAtTopOfBlock(false);
+            marginInfo.clearMargin();
+        }
+
+        // Try to guess our correct y position.  In most cases this guess will
+        // be correct.  Only if we're wrong (when we compute the real y position)
+        // will we have to potentially relayout.
+        int yPosEstimate = estimateVerticalPosition(child, marginInfo);
+
+        // Cache our old rect so that we can dirty the proper repaint rects if the child moves.
+        IntRect oldRect(child->xPos(), child->yPos() , child->width(), child->height());
+          
+        // Go ahead and position the child as though it didn't collapse with the top.
+        view()->addLayoutDelta(IntSize(0, child->yPos() - yPosEstimate));
+        child->setPos(child->xPos(), yPosEstimate);
+
+        bool markDescendantsWithFloats = false;
+        if (yPosEstimate != oldRect.y() && !child->avoidsFloats() && child->containsFloats())
+            markDescendantsWithFloats = true;
+        else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) {
+            // If an element might be affected by the presence of floats, then always mark it for
+            // layout.
+            int fb = max(previousFloatBottom, floatBottom());
+            if (fb > m_height || fb > yPosEstimate)
+                markDescendantsWithFloats = true;
+        }
+
+        if (markDescendantsWithFloats)
+            child->markAllDescendantsWithFloatsForLayout();
+
+        if (child->isRenderBlock())
+            previousFloatBottom = max(previousFloatBottom, oldRect.y() + static_cast<RenderBlock*>(child)->floatBottom());
+
+        bool childHadLayout = child->m_everHadLayout;
+        bool childNeededLayout = child->needsLayout();
+        if (childNeededLayout)
+            child->layout();
+
+        // Now determine the correct ypos based off examination of collapsing margin
+        // values.
+        collapseMargins(child, marginInfo, yPosEstimate);
+
+        // Now check for clear.
+        clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin);
+
+        // We are no longer at the top of the block if we encounter a non-empty child.  
+        // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
+        if (marginInfo.atTopOfBlock() && !child->isSelfCollapsingBlock())
+            marginInfo.setAtTopOfBlock(false);
+
+        // Now place the child in the correct horizontal position
+        determineHorizontalPosition(child);
+
+        // Update our height now that the child has been placed in the correct position.
+        m_height += child->height();
+        if (child->style()->marginBottomCollapse() == MSEPARATE) {
+            m_height += child->marginBottom();
+            marginInfo.clearMargin();
+        }
+        // If the child has overhanging floats that intrude into following siblings (or possibly out
+        // of this block), then the parent gets notified of the floats now.
+        maxFloatBottom = max(maxFloatBottom, addOverhangingFloats(static_cast<RenderBlock *>(child), -child->xPos(), -child->yPos(), !childNeededLayout));
+
+        // Update our overflow in case the child spills out the block.
+        m_overflowTop = min(m_overflowTop, child->yPos() + child->overflowTop(false));
+        m_overflowHeight = max(m_overflowHeight, m_height + child->overflowHeight(false) - child->height());
+        m_overflowWidth = max(child->xPos() + child->overflowWidth(false), m_overflowWidth);
+        m_overflowLeft = min(child->xPos() + child->overflowLeft(false), m_overflowLeft);
+        
+        // Insert our compact into the block margin if we have one.
+        insertCompactIfNeeded(child, compactInfo);
+
+        IntSize childOffset(child->xPos() - oldRect.x(), child->yPos() - oldRect.y());
+        if (childOffset.width() || childOffset.height()) {
+            view()->addLayoutDelta(childOffset);
+
+            // If the child moved, we have to repaint it as well as any floating/positioned
+            // descendants.  An exception is if we need a layout.  In this case, we know we're going to
+            // repaint ourselves (and the child) anyway.
+            if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout())
+                child->repaintDuringLayoutIfMoved(oldRect);
+        }
+
+        if (!childHadLayout && child->checkForRepaintDuringLayout())
+            child->repaint();
+
+        child = child->nextSibling();
+    }
+
+    // Now do the handling of the bottom of the block, adding in our bottom border/padding and
+    // determining the correct collapsed bottom margin information.
+    handleBottomOfBlock(top, bottom, marginInfo);
+}
+
+bool RenderBlock::layoutOnlyPositionedObjects()
+{
+    if (!posChildNeedsLayout() || normalChildNeedsLayout() || selfNeedsLayout())
+        return false;
+
+    if (!m_hasColumns)
+        view()->pushLayoutState(this, IntSize(xPos(), yPos()));
+    else
+        view()->disableLayoutState();
+
+    if (needsPositionedMovementLayout()) {
+        tryLayoutDoingPositionedMovementOnly();
+        if (needsLayout())
+            return false;
+    }
+
+    // All we have to is lay out our positioned objects.
+    layoutPositionedObjects(false);
+
+    if (!m_hasColumns)
+        view()->popLayoutState();
+    else
+        view()->enableLayoutState();
+
+    if (hasOverflowClip())
+        m_layer->updateScrollInfoAfterLayout();
+
+    setNeedsLayout(false);
+    return true;
+}
+
+void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
+{
+    if (m_positionedObjects) {
+        RenderObject* r;
+        Iterator end = m_positionedObjects->end();
+        for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
+            r = *it;
+            // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the
+            // non-positioned block.  Rather than trying to detect all of these movement cases, we just always lay out positioned
+            // objects that are positioned implicitly like this.  Such objects are rare, and so in typical DHTML menu usage (where everything is
+            // positioned explicitly) this should not incur a performance penalty.
+            if (relayoutChildren || (r->hasStaticY() && r->parent() != this && r->parent()->isBlockFlow()))
+                r->setChildNeedsLayout(true, false);
+                
+            // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
+            if (relayoutChildren && (r->style()->paddingLeft().isPercent() || r->style()->paddingRight().isPercent()))
+                r->setPrefWidthsDirty(true, false);
+            
+            // We don't have to do a full layout.  We just have to update our position. Try that first. If we have shrink-to-fit width
+            // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout.
+            if (r->needsPositionedMovementLayoutOnly())
+                r->tryLayoutDoingPositionedMovementOnly();
+            r->layoutIfNeeded();
+        }
+    }
+}
+
+void RenderBlock::markPositionedObjectsForLayout()
+{
+    if (m_positionedObjects) {
+        RenderObject* r;
+        Iterator end = m_positionedObjects->end();
+        for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
+            r = *it;
+            r->setChildNeedsLayout(true);
+        }
+    }
+}
+
+void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
+{
+    // Repaint any overhanging floats (if we know we're the one to paint them).
+    if (hasOverhangingFloats()) {
+        // We think that we must be in a bad state if m_floatingObjects is nil at this point, so 
+        // we assert on Debug builds and nil-check Release builds.
+        ASSERT(m_floatingObjects);
+        if (!m_floatingObjects)
+            return;
+        
+        FloatingObject* r;
+        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+
+        // FIXME: Avoid disabling LayoutState. At the very least, don't disable it for floats originating
+        // in this block. Better yet would be to push extra state for the containers of other floats.
+        view()->disableLayoutState();
+        for ( ; (r = it.current()); ++it) {
+            // Only repaint the object if it is overhanging, is not in its own layer, and
+            // is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
+            // condition is replaced with being a descendant of us.
+            if (r->m_bottom > m_height && (paintAllDescendants && r->m_renderer->isDescendantOf(this) || r->m_shouldPaint) && !r->m_renderer->hasLayer()) {                
+                r->m_renderer->repaint();
+                r->m_renderer->repaintOverhangingFloats();
+            }
+        }
+        view()->enableLayoutState();
+    }
+}
+
+void RenderBlock::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    tx += m_x;
+    ty += m_y;
+    
+    PaintPhase phase = paintInfo.phase;
+
+    // Check if we need to do anything at all.
+    // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
+    // paints the root's background.
+    if (!isInlineFlow() && !isRoot()) {
+        IntRect overflowBox = overflowRect(false);
+        overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
+        overflowBox.move(tx, ty);
+        if (!overflowBox.intersects(paintInfo.rect))
+            return;
+    }
+
+    bool useControlClip = phase != PaintPhaseBlockBackground && phase != PaintPhaseSelfOutline && phase != PaintPhaseMask && hasControlClip();
+
+    // Push a clip.
+    if (useControlClip) {
+        if (phase == PaintPhaseOutline)
+            paintInfo.phase = PaintPhaseChildOutlines;
+        else if (phase == PaintPhaseChildBlockBackground) {
+            paintInfo.phase = PaintPhaseBlockBackground;
+            paintObject(paintInfo, tx, ty);
+            paintInfo.phase = PaintPhaseChildBlockBackgrounds;
+        }
+        IntRect clipRect(controlClipRect(tx, ty));
+        if (clipRect.isEmpty())
+            return;
+        paintInfo.context->save();
+        paintInfo.context->clip(clipRect);
+    }
+
+    paintObject(paintInfo, tx, ty);
+    
+    // Pop the clip.
+    if (useControlClip) {
+        paintInfo.context->restore();
+        if (phase == PaintPhaseOutline) {
+            paintInfo.phase = PaintPhaseSelfOutline;
+            paintObject(paintInfo, tx, ty);
+            paintInfo.phase = phase;
+        } else if (phase == PaintPhaseChildBlockBackground)
+            paintInfo.phase = phase;
+    }
+}
+
+void RenderBlock::paintColumns(PaintInfo& paintInfo, int tx, int ty, bool paintingFloats)
+{
+    // We need to do multiple passes, breaking up our child painting into strips.
+    GraphicsContext* context = paintInfo.context;
+    int currXOffset = 0;
+    int currYOffset = 0;
+    int ruleAdd = borderLeft() + paddingLeft();
+    int ruleX = 0;
+    int colGap = columnGap();
+    const Color& ruleColor = style()->columnRuleColor();
+    bool ruleTransparent = style()->columnRuleIsTransparent();
+    EBorderStyle ruleStyle = style()->columnRuleStyle();
+    int ruleWidth = style()->columnRuleWidth();
+    bool renderRule = !paintingFloats && ruleStyle > BHIDDEN && !ruleTransparent && ruleWidth <= colGap;
+    Vector<IntRect>* colRects = columnRects();
+    unsigned colCount = colRects->size();
+    for (unsigned i = 0; i < colCount; i++) {
+        // For each rect, we clip to the rect, and then we adjust our coords.
+        IntRect colRect = colRects->at(i);
+        colRect.move(tx, ty);
+        context->save();
+        
+        // Each strip pushes a clip, since column boxes are specified as being
+        // like overflow:hidden.
+        context->clip(colRect);
+        
+        // Adjust tx and ty to change where we paint.
+        PaintInfo info(paintInfo);
+        info.rect.intersect(colRect);
+        
+        // Adjust our x and y when painting.
+        int finalX = tx + currXOffset;
+        int finalY = ty + currYOffset;
+        if (paintingFloats)
+            paintFloats(info, finalX, finalY, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip);
+        else
+            paintContents(info, finalX, finalY);
+
+        // Move to the next position.
+        if (style()->direction() == LTR) {
+            ruleX += colRect.width() + colGap / 2;
+            currXOffset += colRect.width() + colGap;
+        } else {
+            ruleX -= (colRect.width() + colGap / 2);
+            currXOffset -= (colRect.width() + colGap);
+        }
+
+        currYOffset -= colRect.height();
+        
+        context->restore();
+        
+        // Now paint the column rule.
+        if (renderRule && paintInfo.phase == PaintPhaseForeground && i < colCount - 1) {
+            int ruleStart = ruleX - ruleWidth / 2 + ruleAdd;
+            int ruleEnd = ruleStart + ruleWidth;
+            drawBorder(paintInfo.context, tx + ruleStart, ty + borderTop() + paddingTop(), tx + ruleEnd, ty + borderTop() + paddingTop() + contentHeight(),
+                       style()->direction() == LTR ? BSLeft : BSRight, ruleColor, style()->color(), ruleStyle, 0, 0);
+        }
+        
+        ruleX = currXOffset;
+    }
+}
+
+void RenderBlock::paintContents(PaintInfo& paintInfo, int tx, int ty)
+{
+    // Avoid painting descendants of the root element when stylesheets haven't loaded.  This eliminates FOUC.
+    // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
+    // will do a full repaint().
+    if (document()->didLayoutWithPendingStylesheets() && !isRenderView())
+        return;
+
+    if (childrenInline())
+        paintLines(paintInfo, tx, ty);
+    else
+        paintChildren(paintInfo, tx, ty);
+}
+
+void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty)
+{
+    PaintPhase newPhase = (paintInfo.phase == PaintPhaseChildOutlines) ? PaintPhaseOutline : paintInfo.phase;
+    newPhase = (newPhase == PaintPhaseChildBlockBackgrounds) ? PaintPhaseChildBlockBackground : newPhase;
+    
+    // We don't paint our own background, but we do let the kids paint their backgrounds.
+    PaintInfo info(paintInfo);
+    info.phase = newPhase;
+    info.paintingRoot = paintingRootForChildren(paintInfo);
+    bool isPrinting = document()->printing();
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {        
+        // Check for page-break-before: always, and if it's set, break and bail.
+        if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS &&
+            inRootBlockContext() && (ty + child->yPos()) > paintInfo.rect.y() && 
+            (ty + child->yPos()) < paintInfo.rect.bottom()) {
+            view()->setBestTruncatedAt(ty + child->yPos(), this, true);
+            return;
+        }
+
+        if (!child->hasLayer() && !child->isFloating())
+            child->paint(info, tx, ty);
+
+        // Check for page-break-after: always, and if it's set, break and bail.
+        if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS && 
+            inRootBlockContext() && (ty + child->yPos() + child->height()) > paintInfo.rect.y() && 
+            (ty + child->yPos() + child->height()) < paintInfo.rect.bottom()) {
+            view()->setBestTruncatedAt(ty + child->yPos() + child->height() + max(0, child->collapsedMarginBottom()), this, true);
+            return;
+        }
+    }
+}
+
+void RenderBlock::paintCaret(PaintInfo& paintInfo, CaretType type)
+{
+    SelectionController* selection = type == CursorCaret ? document()->frame()->selection() : document()->frame()->dragCaretController();
+    Node* caretNode = selection->start().node();
+    RenderObject* renderer = caretNode ? caretNode->renderer() : 0;
+    if (!renderer)
+        return;
+    // if caretNode is a block and caret is inside it then caret should be painted by that block
+    bool cursorInsideBlockCaretNode = renderer->isBlockFlow() && selection->isInsideNode();
+    if ((cursorInsideBlockCaretNode ? renderer : renderer->containingBlock()) == this && selection->isContentEditable()) {
+        if (type == CursorCaret)
+            document()->frame()->paintCaret(paintInfo.context, paintInfo.rect);
+        else
+            document()->frame()->paintDragCaret(paintInfo.context, paintInfo.rect);
+    }
+}
+
+void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
+{
+    PaintPhase paintPhase = paintInfo.phase;
+
+    // If we're a repositioned run-in or a compact, don't paint background/borders.
+    bool inlineFlow = isInlineFlow();
+
+    // 1. paint background, borders etc
+    if (!inlineFlow &&
+        (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) &&
+        hasBoxDecorations() && style()->visibility() == VISIBLE) {
+        paintBoxDecorations(paintInfo, tx, ty);
+    }
+
+    if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) {
+        paintMask(paintInfo, tx, ty);
+        return;
+    }
+
+    // We're done.  We don't bother painting any children.
+    if (paintPhase == PaintPhaseBlockBackground)
+        return;
+
+    // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).s
+    int scrolledX = tx;
+    int scrolledY = ty;
+    if (hasOverflowClip())
+        m_layer->subtractScrollOffset(scrolledX, scrolledY);
+
+    // 2. paint contents
+    if (paintPhase != PaintPhaseSelfOutline) {
+        if (m_hasColumns)
+            paintColumns(paintInfo, scrolledX, scrolledY);
+        else
+            paintContents(paintInfo, scrolledX, scrolledY);
+    }
+
+    // 3. paint selection
+    // FIXME: Make this work with multi column layouts.  For now don't fill gaps.
+    bool isPrinting = document()->printing();
+    if (!inlineFlow && !isPrinting && !m_hasColumns)
+        paintSelection(paintInfo, scrolledX, scrolledY); // Fill in gaps in selection on lines and between blocks.
+
+    // 4. paint floats.
+    if (!inlineFlow && (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip)) {
+        if (m_hasColumns)
+            paintColumns(paintInfo, scrolledX, scrolledY, true);
+        else
+            paintFloats(paintInfo, scrolledX, scrolledY, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip);
+    }
+
+    // 5. paint outline.
+    if (!inlineFlow && (paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
+        RenderObject::paintOutline(paintInfo.context, tx, ty, width(), height(), style());
+
+    // 6. paint continuation outlines.
+    if (!inlineFlow && (paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
+        if (continuation() && continuation()->hasOutline() && continuation()->style()->visibility() == VISIBLE) {
+            RenderFlow* inlineFlow = static_cast<RenderFlow*>(continuation()->element()->renderer());
+            if (!inlineFlow->hasLayer())
+                containingBlock()->addContinuationWithOutline(inlineFlow);
+            else if (!inlineFlow->firstLineBox())
+                inlineFlow->paintOutline(paintInfo.context, tx - xPos() + inlineFlow->containingBlock()->xPos(),
+                                         ty - yPos() + inlineFlow->containingBlock()->yPos());
+        }
+        paintContinuationOutlines(paintInfo, tx, ty);
+    }
+
+    // 7. paint caret.
+    // If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
+    // then paint the caret.
+    if (!inlineFlow && paintPhase == PaintPhaseForeground) {        
+        paintCaret(paintInfo, CursorCaret);
+        paintCaret(paintInfo, DragCaret);
+    }
+}
+
+void RenderBlock::paintFloats(PaintInfo& paintInfo, int tx, int ty, bool preservePhase)
+{
+    if (!m_floatingObjects)
+        return;
+
+    FloatingObject* r;
+    DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+    for (; (r = it.current()); ++it) {
+        // Only paint the object if our m_shouldPaint flag is set.
+        if (r->m_shouldPaint && !r->m_renderer->hasLayer()) {
+            PaintInfo currentPaintInfo(paintInfo);
+            currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
+            int currentTX = tx + r->m_left - r->m_renderer->xPos() + r->m_renderer->marginLeft();
+            int currentTY = ty + r->m_top - r->m_renderer->yPos() + r->m_renderer->marginTop();
+            r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
+            if (!preservePhase) {
+                currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
+                r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
+                currentPaintInfo.phase = PaintPhaseFloat;
+                r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
+                currentPaintInfo.phase = PaintPhaseForeground;
+                r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
+                currentPaintInfo.phase = PaintPhaseOutline;
+                r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
+            }
+        }
+    }
+}
+
+void RenderBlock::paintEllipsisBoxes(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (!shouldPaintWithinRoot(paintInfo) || !firstLineBox())
+        return;
+
+    if (style()->visibility() == VISIBLE && paintInfo.phase == PaintPhaseForeground) {
+        // We can check the first box and last box and avoid painting if we don't
+        // intersect.
+        int yPos = ty + firstLineBox()->yPos();
+        int h = lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
+        if (yPos >= paintInfo.rect.bottom() || yPos + h <= paintInfo.rect.y())
+            return;
+
+        // See if our boxes intersect with the dirty rect.  If so, then we paint
+        // them.  Note that boxes can easily overlap, so we can't make any assumptions
+        // based off positions of our first line box or our last line box.
+        for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+            yPos = ty + curr->yPos();
+            h = curr->height();
+            if (curr->ellipsisBox() && yPos < paintInfo.rect.bottom() && yPos + h > paintInfo.rect.y())
+                curr->paintEllipsisBox(paintInfo, tx, ty);
+        }
+    }
+}
+
+HashMap<RenderBlock*, RenderFlowSequencedSet*>* continuationOutlineTable()
+{
+    static HashMap<RenderBlock*, RenderFlowSequencedSet*> table;
+    return &table;
+}
+
+void RenderBlock::addContinuationWithOutline(RenderFlow* flow)
+{
+    // We can't make this work if the inline is in a layer.  We'll just rely on the broken
+    // way of painting.
+    ASSERT(!flow->layer());
+    
+    HashMap<RenderBlock*, RenderFlowSequencedSet*>* table = continuationOutlineTable();
+    RenderFlowSequencedSet* continuations = table->get(this);
+    if (!continuations) {
+        continuations = new RenderFlowSequencedSet;
+        table->set(this, continuations);
+    }
+    
+    continuations->add(flow);
+}
+
+void RenderBlock::paintContinuationOutlines(PaintInfo& info, int tx, int ty)
+{
+    HashMap<RenderBlock*, RenderFlowSequencedSet*>* table = continuationOutlineTable();
+    if (table->isEmpty())
+        return;
+        
+    RenderFlowSequencedSet* continuations = table->get(this);
+    if (!continuations)
+        return;
+        
+    // Paint each continuation outline.
+    RenderFlowSequencedSet::iterator end = continuations->end();
+    for (RenderFlowSequencedSet::iterator it = continuations->begin(); it != end; ++it) {
+        // Need to add in the coordinates of the intervening blocks.
+        RenderFlow* flow = *it;
+        RenderBlock* block = flow->containingBlock();
+        for ( ; block && block != this; block = block->containingBlock()) {
+            tx += block->xPos();
+            ty += block->yPos();
+        }
+        ASSERT(block);   
+        flow->paintOutline(info.context, tx, ty);
+    }
+    
+    // Delete
+    delete continuations;
+    table->remove(this);
+}
+
+void RenderBlock::setSelectionState(SelectionState s)
+{
+    if (selectionState() == s)
+        return;
+    
+    if (s == SelectionInside && selectionState() != SelectionNone)
+        return;
+
+    if ((s == SelectionStart && selectionState() == SelectionEnd) ||
+        (s == SelectionEnd && selectionState() == SelectionStart))
+        m_selectionState = SelectionBoth;
+    else
+        m_selectionState = s;
+    
+    RenderBlock* cb = containingBlock();
+    if (cb && !cb->isRenderView())
+        cb->setSelectionState(s);
+}
+
+bool RenderBlock::shouldPaintSelectionGaps() const
+{
+    return m_selectionState != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
+}
+
+bool RenderBlock::isSelectionRoot() const
+{
+    if (!element())
+        return false;
+        
+    // FIXME: Eventually tables should have to learn how to fill gaps between cells, at least in simple non-spanning cases.
+    if (isTable())
+        return false;
+        
+    if (isBody() || isRoot() || hasOverflowClip() || isRelPositioned() ||
+        isFloatingOrPositioned() || isTableCell() || isInlineBlockOrInlineTable() || hasTransform() ||
+        hasReflection() || hasMask())
+        return true;
+    
+    if (view() && view()->selectionStart()) {
+        Node* startElement = view()->selectionStart()->element();
+        if (startElement && startElement->rootEditableElement() == element())
+            return true;
+    }
+    
+    return false;
+}
+
+GapRects RenderBlock::selectionGapRects()
+{
+    ASSERT(!needsLayout());
+
+    if (!shouldPaintSelectionGaps())
+        return GapRects();
+
+    int tx, ty;
+    absolutePositionForContent(tx, ty);
+    if (hasOverflowClip())
+        layer()->subtractScrollOffset(tx, ty);
+
+    int lastTop = -borderTopExtra();
+    int lastLeft = leftSelectionOffset(this, lastTop);
+    int lastRight = rightSelectionOffset(this, lastTop);
+    
+    return fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight);
+}
+
+void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (shouldPaintSelectionGaps() && paintInfo.phase == PaintPhaseForeground) {
+        int lastTop = -borderTopExtra();
+        int lastLeft = leftSelectionOffset(this, lastTop);
+        int lastRight = rightSelectionOffset(this, lastTop);
+        paintInfo.context->save();
+        fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight, &paintInfo);
+        paintInfo.context->restore();
+    }
+}
+
+static void clipOutPositionedObjects(const RenderObject::PaintInfo* paintInfo, int tx, int ty, ListHashSet<RenderObject*>* positionedObjects)
+{
+    if (!positionedObjects)
+        return;
+    
+    ListHashSet<RenderObject*>::const_iterator end = positionedObjects->end();
+    for (ListHashSet<RenderObject*>::const_iterator it = positionedObjects->begin(); it != end; ++it) {
+        RenderObject* r = *it;
+        paintInfo->context->clipOut(IntRect(tx + r->xPos(), ty + r->yPos(), r->width(), r->height()));
+    }
+}
+
+GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
+                                        int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* paintInfo)
+{
+    // IMPORTANT: Callers of this method that intend for painting to happen need to do a save/restore.
+    // Clip out floating and positioned objects when painting selection gaps.
+    if (paintInfo) {
+        // Note that we don't clip out overflow for positioned objects.  We just stick to the border box.
+        clipOutPositionedObjects(paintInfo, tx, ty, m_positionedObjects);
+        if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects.
+            for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock())
+                clipOutPositionedObjects(paintInfo, cb->xPos(), cb->yPos(), cb->m_positionedObjects);
+        if (m_floatingObjects) {
+            for (DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); it.current(); ++it) {
+                FloatingObject* r = it.current();
+                paintInfo->context->clipOut(IntRect(tx + r->m_left + r->m_renderer->marginLeft(), 
+                                                    ty + r->m_top + r->m_renderer->marginTop(),
+                                                    r->m_renderer->width(), r->m_renderer->height()));
+            }
+        }
+    }
+
+    // FIXME: overflow: auto/scroll regions need more math here, since painting in the border box is different from painting in the padding box (one is scrolled, the other is
+    // fixed).
+    GapRects result;
+#ifdef ANDROID_DO_NOT_DRAW_TEXTFIELD_SELECTION
+    Node* node = element();
+    if (node) {
+        Node* ancestor = node->shadowAncestorNode();
+        if (ancestor && ancestor->renderer()) {
+            RenderObject* renderer = ancestor->renderer();
+            if (renderer->isTextField() || renderer->isTextArea())
+                return result;
+        }
+    }
+#endif
+    if (!isBlockFlow()) // FIXME: Make multi-column selection gap filling work someday.
+        return result;
+
+    if (m_hasColumns || hasTransform()) {
+        // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
+        lastTop = (ty - blockY) + height();
+        lastLeft = leftSelectionOffset(rootBlock, height());
+        lastRight = rightSelectionOffset(rootBlock, height());
+        return result;
+    }
+
+    if (childrenInline())
+        result = fillInlineSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, paintInfo);
+    else
+        result = fillBlockSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, paintInfo);
+
+    // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
+    if (rootBlock == this && (m_selectionState != SelectionBoth && m_selectionState != SelectionEnd))
+        result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + height() + borderBottomExtra(),
+                                                    rootBlock, blockX, blockY, paintInfo));
+    return result;
+}
+
+GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, 
+                                              int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* paintInfo)
+{
+    GapRects result;
+
+    bool containsStart = selectionState() == SelectionStart || selectionState() == SelectionBoth;
+
+    if (!firstLineBox()) {
+        if (containsStart) {
+            // Go ahead and update our lastY to be the bottom of the block.  <hr>s or empty blocks with height can trip this
+            // case.
+            lastTop = (ty - blockY) + height();
+            lastLeft = leftSelectionOffset(rootBlock, height());
+            lastRight = rightSelectionOffset(rootBlock, height());
+        }
+        return result;
+    }
+
+    RootInlineBox* lastSelectedLine = 0;
+    RootInlineBox* curr;
+    for (curr = firstRootBox(); curr && !curr->hasSelectedChildren(); curr = curr->nextRootBox()) { }
+
+    // Now paint the gaps for the lines.
+    for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) {
+        int selTop =  curr->selectionTop();
+        int selHeight = curr->selectionHeight();
+
+        if (!containsStart && !lastSelectedLine &&
+            selectionState() != SelectionStart && selectionState() != SelectionBoth)
+            result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + selTop,
+                                                        rootBlock, blockX, blockY, paintInfo));
+
+        if (!paintInfo || ty + selTop < paintInfo->rect.bottom() && ty + selTop + selHeight > paintInfo->rect.y())
+            result.unite(curr->fillLineSelectionGap(selTop, selHeight, rootBlock, blockX, blockY, tx, ty, paintInfo));
+
+        lastSelectedLine = curr;
+    }
+
+    if (containsStart && !lastSelectedLine)
+        // Selection must start just after our last line.
+        lastSelectedLine = lastRootBox();
+
+    if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
+        // Go ahead and update our lastY to be the bottom of the last selected line.
+        lastTop = (ty - blockY) + lastSelectedLine->bottomOverflow();
+        lastLeft = leftSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow());
+        lastRight = rightSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow());
+    }
+    return result;
+}
+
+GapRects RenderBlock::fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
+                                             int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* paintInfo)
+{
+    GapRects result;
+
+    // Go ahead and jump right to the first block child that contains some selected objects.
+    RenderObject* curr;
+    for (curr = firstChild(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSibling()) { }
+
+    for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSibling()) {
+        SelectionState childState = curr->selectionState();
+        if (childState == SelectionBoth || childState == SelectionEnd)
+            sawSelectionEnd = true;
+
+        if (curr->isFloatingOrPositioned())
+            continue; // We must be a normal flow object in order to even be considered.
+
+        if (curr->isRelPositioned() && curr->hasLayer()) {
+            // If the relposition offset is anything other than 0, then treat this just like an absolute positioned element.
+            // Just disregard it completely.
+            int x = 0;
+            int y = 0;
+            curr->layer()->relativePositionOffset(x, y);
+            if (x || y)
+                continue;
+        }
+
+        bool paintsOwnSelection = curr->shouldPaintSelectionGaps() || curr->isTable(); // FIXME: Eventually we won't special-case table like this.
+        bool fillBlockGaps = paintsOwnSelection || (curr->canBeSelectionLeaf() && childState != SelectionNone);
+        if (fillBlockGaps) {
+            // We need to fill the vertical gap above this object.
+            if (childState == SelectionEnd || childState == SelectionInside)
+                // Fill the gap above the object.
+                result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, 
+                                                            ty + curr->yPos(), rootBlock, blockX, blockY, paintInfo));
+
+            // Only fill side gaps for objects that paint their own selection if we know for sure the selection is going to extend all the way *past*
+            // our object.  We know this if the selection did not end inside our object.
+            if (paintsOwnSelection && (childState == SelectionStart || sawSelectionEnd))
+                childState = SelectionNone;
+
+            // Fill side gaps on this object based off its state.
+            bool leftGap, rightGap;
+            getHorizontalSelectionGapInfo(childState, leftGap, rightGap);
+
+            if (leftGap)
+                result.uniteLeft(fillLeftSelectionGap(this, curr->xPos(), curr->yPos(), curr->height(), rootBlock, blockX, blockY, tx, ty, paintInfo));
+            if (rightGap)
+                result.uniteRight(fillRightSelectionGap(this, curr->xPos() + curr->width(), curr->yPos(), curr->height(), rootBlock, blockX, blockY, tx, ty, paintInfo));
+
+            // Update lastTop to be just underneath the object.  lastLeft and lastRight extend as far as
+            // they can without bumping into floating or positioned objects.  Ideally they will go right up
+            // to the border of the root selection block.
+            lastTop = (ty - blockY) + (curr->yPos() + curr->height());
+            lastLeft = leftSelectionOffset(rootBlock, curr->yPos() + curr->height());
+            lastRight = rightSelectionOffset(rootBlock, curr->yPos() + curr->height());
+        } else if (childState != SelectionNone)
+            // We must be a block that has some selected object inside it.  Go ahead and recur.
+            result.unite(static_cast<RenderBlock*>(curr)->fillSelectionGaps(rootBlock, blockX, blockY, tx + curr->xPos(), ty + curr->yPos(), 
+                                                                            lastTop, lastLeft, lastRight, paintInfo));
+    }
+    return result;
+}
+
+IntRect RenderBlock::fillHorizontalSelectionGap(RenderObject* selObj, int xPos, int yPos, int width, int height, const PaintInfo* paintInfo)
+{
+    if (width <= 0 || height <= 0)
+        return IntRect();
+    IntRect gapRect(xPos, yPos, width, height);
+    if (paintInfo && selObj->style()->visibility() == VISIBLE)
+        paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor());
+    return gapRect;
+}
+
+IntRect RenderBlock::fillVerticalSelectionGap(int lastTop, int lastLeft, int lastRight, int bottomY, RenderBlock* rootBlock,
+                                              int blockX, int blockY, const PaintInfo* paintInfo)
+{
+    int top = blockY + lastTop;
+    int height = bottomY - top;
+    if (height <= 0)
+        return IntRect();
+
+    // Get the selection offsets for the bottom of the gap
+    int left = blockX + max(lastLeft, leftSelectionOffset(rootBlock, bottomY));
+    int right = blockX + min(lastRight, rightSelectionOffset(rootBlock, bottomY));
+    int width = right - left;
+    if (width <= 0)
+        return IntRect();
+
+    IntRect gapRect(left, top, width, height);
+    if (paintInfo)
+        paintInfo->context->fillRect(gapRect, selectionBackgroundColor());
+    return gapRect;
+}
+
+IntRect RenderBlock::fillLeftSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
+                                          int blockX, int blockY, int tx, int ty, const PaintInfo* paintInfo)
+{
+    int top = yPos + ty;
+    int left = blockX + max(leftSelectionOffset(rootBlock, yPos), leftSelectionOffset(rootBlock, yPos + height));
+    int right = min(xPos + tx, blockX + min(rightSelectionOffset(rootBlock, yPos), rightSelectionOffset(rootBlock, yPos + height)));
+    int width = right - left;
+    if (width <= 0)
+        return IntRect();
+
+    IntRect gapRect(left, top, width, height);
+    if (paintInfo)
+        paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor());
+    return gapRect;
+}
+
+IntRect RenderBlock::fillRightSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
+                                           int blockX, int blockY, int tx, int ty, const PaintInfo* paintInfo)
+{
+    int left = max(xPos + tx, blockX + max(leftSelectionOffset(rootBlock, yPos), leftSelectionOffset(rootBlock, yPos + height)));
+    int top = yPos + ty;
+    int right = blockX + min(rightSelectionOffset(rootBlock, yPos), rightSelectionOffset(rootBlock, yPos + height));
+    int width = right - left;
+    if (width <= 0)
+        return IntRect();
+
+    IntRect gapRect(left, top, width, height);
+    if (paintInfo)
+        paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor());
+    return gapRect;
+}
+
+void RenderBlock::getHorizontalSelectionGapInfo(SelectionState state, bool& leftGap, bool& rightGap)
+{
+    bool ltr = style()->direction() == LTR;
+    leftGap = (state == RenderObject::SelectionInside) ||
+              (state == RenderObject::SelectionEnd && ltr) ||
+              (state == RenderObject::SelectionStart && !ltr);
+    rightGap = (state == RenderObject::SelectionInside) ||
+               (state == RenderObject::SelectionStart && ltr) ||
+               (state == RenderObject::SelectionEnd && !ltr);
+}
+
+int RenderBlock::leftSelectionOffset(RenderBlock* rootBlock, int y)
+{
+    int left = leftOffset(y);
+    if (left == borderLeft() + paddingLeft()) {
+        if (rootBlock != this)
+            // The border can potentially be further extended by our containingBlock().
+            return containingBlock()->leftSelectionOffset(rootBlock, y + yPos());
+        return left;
+    }
+    else {
+        RenderBlock* cb = this;
+        while (cb != rootBlock) {
+            left += cb->xPos();
+            cb = cb->containingBlock();
+        }
+    }
+    
+    return left;
+}
+
+int RenderBlock::rightSelectionOffset(RenderBlock* rootBlock, int y)
+{
+    int right = rightOffset(y);
+    if (right == (contentWidth() + (borderLeft() + paddingLeft()))) {
+        if (rootBlock != this)
+            // The border can potentially be further extended by our containingBlock().
+            return containingBlock()->rightSelectionOffset(rootBlock, y + yPos());
+        return right;
+    }
+    else {
+        RenderBlock* cb = this;
+        while (cb != rootBlock) {
+            right += cb->xPos();
+            cb = cb->containingBlock();
+        }
+    }
+    return right;
+}
+
+void RenderBlock::insertPositionedObject(RenderObject *o)
+{
+    // Create the list of special objects if we don't aleady have one
+    if (!m_positionedObjects)
+        m_positionedObjects = new ListHashSet<RenderObject*>;
+
+    m_positionedObjects->add(o);
+}
+
+void RenderBlock::removePositionedObject(RenderObject *o)
+{
+    if (m_positionedObjects)
+        m_positionedObjects->remove(o);
+}
+
+void RenderBlock::removePositionedObjects(RenderBlock* o)
+{
+    if (!m_positionedObjects)
+        return;
+    
+    RenderObject* r;
+    
+    Iterator end = m_positionedObjects->end();
+    
+    Vector<RenderObject*, 16> deadObjects;
+
+    for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
+        r = *it;
+        if (!o || r->isDescendantOf(o)) {
+            if (o)
+                r->setChildNeedsLayout(true, false);
+            
+            // It is parent blocks job to add positioned child to positioned objects list of its containing block
+            // Parent layout needs to be invalidated to ensure this happens.
+            RenderObject* p = r->parent();
+            while (p && !p->isRenderBlock())
+                p = p->parent();
+            if (p)
+                p->setChildNeedsLayout(true);
+            
+            deadObjects.append(r);
+        }
+    }
+    
+    for (unsigned i = 0; i < deadObjects.size(); i++)
+        m_positionedObjects->remove(deadObjects.at(i));
+}
+
+void RenderBlock::insertFloatingObject(RenderObject *o)
+{
+    ASSERT(o->isFloating());
+
+    // Create the list of special objects if we don't aleady have one
+    if (!m_floatingObjects) {
+        m_floatingObjects = new DeprecatedPtrList<FloatingObject>;
+        m_floatingObjects->setAutoDelete(true);
+    } else {
+        // Don't insert the object again if it's already in the list
+        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+        FloatingObject* f;
+        while ( (f = it.current()) ) {
+            if (f->m_renderer == o) return;
+            ++it;
+        }
+    }
+
+    // Create the special object entry & append it to the list
+
+    o->layoutIfNeeded();
+
+    FloatingObject* newObj = new FloatingObject(o->style()->floating() == FLEFT ? FloatingObject::FloatLeft : FloatingObject::FloatRight);
+
+    newObj->m_top = -1;
+    newObj->m_bottom = -1;
+    newObj->m_width = o->width() + o->marginLeft() + o->marginRight();
+    newObj->m_shouldPaint = !o->hasLayer(); // If a layer exists, the float will paint itself.  Otherwise someone else will.
+    newObj->m_isDescendant = true;
+    newObj->m_renderer = o;
+
+    m_floatingObjects->append(newObj);
+}
+
+void RenderBlock::removeFloatingObject(RenderObject *o)
+{
+    if (m_floatingObjects) {
+        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+        while (it.current()) {
+            if (it.current()->m_renderer == o) {
+                if (childrenInline())
+                    markLinesDirtyInVerticalRange(0, it.current()->m_bottom);
+                m_floatingObjects->removeRef(it.current());
+            }
+            ++it;
+        }
+    }
+}
+
+bool RenderBlock::positionNewFloats()
+{
+    if (!m_floatingObjects)
+        return false;
+    
+    FloatingObject* f = m_floatingObjects->last();
+
+    // If all floats have already been positioned, then we have no work to do.
+    if (!f || f->m_top != -1)
+        return false;
+
+    // Move backwards through our floating object list until we find a float that has
+    // already been positioned.  Then we'll be able to move forward, positioning all of
+    // the new floats that need it.
+    FloatingObject* lastFloat = m_floatingObjects->getPrev();
+    while (lastFloat && lastFloat->m_top == -1) {
+        f = m_floatingObjects->prev();
+        lastFloat = m_floatingObjects->getPrev();
+    }
+
+    int y = m_height;
+    
+    // The float cannot start above the y position of the last positioned float.
+    if (lastFloat)
+        y = max(lastFloat->m_top, y);
+
+    // Now walk through the set of unpositioned floats and place them.
+    while (f) {
+        // The containing block is responsible for positioning floats, so if we have floats in our
+        // list that come from somewhere else, do not attempt to position them.
+        if (f->m_renderer->containingBlock() != this) {
+            f = m_floatingObjects->next();
+            continue;
+        }
+
+        RenderObject* o = f->m_renderer;
+        int _height = o->height() + o->marginTop() + o->marginBottom();
+
+        int ro = rightOffset(); // Constant part of right offset.
+        int lo = leftOffset(); // Constat part of left offset.
+        int fwidth = f->m_width; // The width we look for.
+        if (ro - lo < fwidth)
+            fwidth = ro - lo; // Never look for more than what will be available.
+        
+        IntRect oldRect(o->xPos(), o->yPos() , o->width(), o->height());
+        
+        if (o->style()->clear() & CLEFT)
+            y = max(leftBottom(), y);
+        if (o->style()->clear() & CRIGHT)
+            y = max(rightBottom(), y);
+
+        if (o->style()->floating() == FLEFT) {
+            int heightRemainingLeft = 1;
+            int heightRemainingRight = 1;
+            int fx = leftRelOffset(y,lo, false, &heightRemainingLeft);
+            while (rightRelOffset(y,ro, false, &heightRemainingRight)-fx < fwidth) {
+                y += min(heightRemainingLeft, heightRemainingRight);
+                fx = leftRelOffset(y,lo, false, &heightRemainingLeft);
+            }
+            fx = max(0, fx);
+            f->m_left = fx;
+            o->setPos(fx + o->marginLeft(), y + o->marginTop());
+        } else {
+            int heightRemainingLeft = 1;
+            int heightRemainingRight = 1;
+            int fx = rightRelOffset(y,ro, false, &heightRemainingRight);
+            while (fx - leftRelOffset(y,lo, false, &heightRemainingLeft) < fwidth) {
+                y += min(heightRemainingLeft, heightRemainingRight);
+                fx = rightRelOffset(y, ro, false, &heightRemainingRight);
+            }
+            f->m_left = fx - f->m_width;
+            o->setPos(fx - o->marginRight() - o->width(), y + o->marginTop());
+        }
+
+        f->m_top = y;
+        f->m_bottom = f->m_top + _height;
+
+        // If the child moved, we have to repaint it.
+        if (o->checkForRepaintDuringLayout())
+            o->repaintDuringLayoutIfMoved(oldRect);
+
+        f = m_floatingObjects->next();
+    }
+    return true;
+}
+
+void RenderBlock::newLine(EClear clear)
+{
+    positionNewFloats();
+    // set y position
+    int newY = 0;
+    switch(clear)
+    {
+        case CLEFT:
+            newY = leftBottom();
+            break;
+        case CRIGHT:
+            newY = rightBottom();
+            break;
+        case CBOTH:
+            newY = floatBottom();
+        default:
+            break;
+    }
+    if (m_height < newY)
+        m_height = newY;
+}
+
+void RenderBlock::addPercentHeightDescendant(RenderBox* descendant)
+{
+    if (!gPercentHeightDescendantsMap) {
+        gPercentHeightDescendantsMap = new PercentHeightDescendantsMap;
+        gPercentHeightContainerMap = new PercentHeightContainerMap;
+    }
+
+    HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->get(this);
+    if (!descendantSet) {
+        descendantSet = new HashSet<RenderBox*>;
+        gPercentHeightDescendantsMap->set(this, descendantSet);
+    }
+    bool added = descendantSet->add(descendant).second;
+    if (!added) {
+        ASSERT(gPercentHeightContainerMap->get(descendant));
+        ASSERT(gPercentHeightContainerMap->get(descendant)->contains(this));
+        return;
+    }
+
+    HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->get(descendant);
+    if (!containerSet) {
+        containerSet = new HashSet<RenderBlock*>;
+        gPercentHeightContainerMap->set(descendant, containerSet);
+    }
+    ASSERT(!containerSet->contains(this));
+    containerSet->add(this);
+}
+
+void RenderBlock::removePercentHeightDescendant(RenderBox* descendant)
+{
+    if (!gPercentHeightContainerMap)
+        return;
+
+    HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->take(descendant);
+    if (!containerSet)
+        return;
+
+    HashSet<RenderBlock*>::iterator end = containerSet->end();
+    for (HashSet<RenderBlock*>::iterator it = containerSet->begin(); it != end; ++it) {
+        RenderBlock* container = *it;
+        HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->get(container);
+        ASSERT(descendantSet);
+        if (!descendantSet)
+            continue;
+        ASSERT(descendantSet->contains(descendant));
+        descendantSet->remove(descendant);
+        if (descendantSet->isEmpty()) {
+            gPercentHeightDescendantsMap->remove(container);
+            delete descendantSet;
+        }
+    }
+
+    delete containerSet;
+}
+
+int
+RenderBlock::leftOffset() const
+{
+    return borderLeft()+paddingLeft();
+}
+
+int
+RenderBlock::leftRelOffset(int y, int fixedOffset, bool applyTextIndent,
+                           int *heightRemaining ) const
+{
+    int left = fixedOffset;
+    if (m_floatingObjects) {
+        if ( heightRemaining ) *heightRemaining = 1;
+        FloatingObject* r;
+        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+        for ( ; (r = it.current()); ++it )
+        {
+            if (r->m_top <= y && r->m_bottom > y &&
+                r->type() == FloatingObject::FloatLeft &&
+                r->m_left + r->m_width > left) {
+                left = r->m_left + r->m_width;
+                if ( heightRemaining ) *heightRemaining = r->m_bottom - y;
+            }
+        }
+    }
+
+    if (applyTextIndent && m_firstLine && style()->direction() == LTR) {
+        int cw=0;
+        if (style()->textIndent().isPercent())
+            cw = containingBlock()->availableWidth();
+        left += style()->textIndent().calcMinValue(cw);
+    }
+
+    //kdDebug( 6040 ) << "leftOffset(" << y << ") = " << left << endl;
+    return left;
+}
+
+int
+RenderBlock::rightOffset() const
+{
+    return borderLeft() + paddingLeft() + availableWidth();
+}
+
+int
+RenderBlock::rightRelOffset(int y, int fixedOffset, bool applyTextIndent,
+                            int *heightRemaining ) const
+{
+    int right = fixedOffset;
+
+    if (m_floatingObjects) {
+        if (heightRemaining) *heightRemaining = 1;
+        FloatingObject* r;
+        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+        for ( ; (r = it.current()); ++it )
+        {
+            if (r->m_top <= y && r->m_bottom > y &&
+                r->type() == FloatingObject::FloatRight &&
+                r->m_left < right) {
+                right = r->m_left;
+                if ( heightRemaining ) *heightRemaining = r->m_bottom - y;
+            }
+        }
+    }
+    
+    if (applyTextIndent && m_firstLine && style()->direction() == RTL) {
+        int cw=0;
+        if (style()->textIndent().isPercent())
+            cw = containingBlock()->availableWidth();
+        right -= style()->textIndent().calcMinValue(cw);
+    }
+    
+    //kdDebug( 6040 ) << "rightOffset(" << y << ") = " << right << endl;
+    return right;
+}
+
+int
+RenderBlock::lineWidth(int y) const
+{
+    //kdDebug( 6040 ) << "lineWidth(" << y << ")=" << rightOffset(y) - leftOffset(y) << endl;
+    int result = rightOffset(y) - leftOffset(y);
+    return (result < 0) ? 0 : result;
+}
+
+int RenderBlock::nextFloatBottomBelow(int height) const
+{
+    if (!m_floatingObjects)
+        return 0;
+
+    int bottom = INT_MAX;
+    FloatingObject* r;
+    DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+    for ( ; (r = it.current()); ++it) {
+        if (r->m_bottom > height)
+            bottom = min(r->m_bottom, bottom);
+    }
+
+    return bottom == INT_MAX ? 0 : bottom;
+}
+
+int
+RenderBlock::floatBottom() const
+{
+    if (!m_floatingObjects) return 0;
+    int bottom=0;
+    FloatingObject* r;
+    DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+    for ( ; (r = it.current()); ++it )
+        if (r->m_bottom>bottom)
+            bottom=r->m_bottom;
+    return bottom;
+}
+
+IntRect RenderBlock::floatRect() const
+{
+    IntRect result;
+    if (!m_floatingObjects || hasOverflowClip())
+        return result;
+    FloatingObject* r;
+    DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+    for (; (r = it.current()); ++it) {
+        if (r->m_shouldPaint && !r->m_renderer->hasLayer()) {
+            IntRect childRect = r->m_renderer->overflowRect(false);
+            childRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop());
+            result.unite(childRect);
+        }
+    }
+
+    return result;
+}
+
+int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    int bottom = RenderFlow::lowestPosition(includeOverflowInterior, includeSelf);
+    if (!includeOverflowInterior && hasOverflowClip())
+        return bottom;
+
+    int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetY() : 0;
+
+    if (includeSelf)
+        bottom = max(bottom, m_overflowHeight + relativeOffset);
+        
+    if (m_positionedObjects) {
+        RenderObject* r;
+        Iterator end = m_positionedObjects->end();
+        for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
+            r = *it;
+            // Fixed positioned objects do not scroll and thus should not constitute
+            // part of the lowest position.
+            if (r->style()->position() != FixedPosition) {
+                // FIXME: Should work for overflow sections too.
+                // If a positioned object lies completely to the left of the root it will be unreachable via scrolling.
+                // Therefore we should not allow it to contribute to the lowest position.
+                if (!isRenderView() || r->xPos() + r->width() > 0 || r->xPos() + r->rightmostPosition(false) > 0) {
+                    int lp = r->yPos() + r->lowestPosition(false);
+                    bottom = max(bottom, lp + relativeOffset);
+                }
+            }
+        }
+    }
+
+    if (m_hasColumns) {
+        Vector<IntRect>* colRects = columnRects();
+        for (unsigned i = 0; i < colRects->size(); i++)
+            bottom = max(bottom, colRects->at(i).bottom() + relativeOffset);
+        return bottom;
+    }
+
+    if (m_floatingObjects) {
+        FloatingObject* r;
+        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+        for ( ; (r = it.current()); ++it ) {
+            if (r->m_shouldPaint || r->m_renderer->hasLayer()) {
+                int lp = r->m_top + r->m_renderer->marginTop() + r->m_renderer->lowestPosition(false);
+                bottom = max(bottom, lp + relativeOffset);
+            }
+        }
+    }
+
+
+    if (!includeSelf && lastLineBox()) {
+        int lp = lastLineBox()->yPos() + lastLineBox()->height();
+        bottom = max(bottom, lp);
+    }
+    
+    return bottom;
+}
+
+int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    int right = RenderFlow::rightmostPosition(includeOverflowInterior, includeSelf);
+    if (!includeOverflowInterior && hasOverflowClip())
+        return right;
+
+    int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetX() : 0;
+
+    if (includeSelf)
+        right = max(right, m_overflowWidth + relativeOffset);
+
+    if (m_positionedObjects) {
+        RenderObject* r;
+        Iterator end = m_positionedObjects->end();
+        for (Iterator it = m_positionedObjects->begin() ; it != end; ++it) {
+            r = *it;
+            // Fixed positioned objects do not scroll and thus should not constitute
+            // part of the rightmost position.
+            if (r->style()->position() != FixedPosition) {
+                // FIXME: Should work for overflow sections too.
+                // If a positioned object lies completely above the root it will be unreachable via scrolling.
+                // Therefore we should not allow it to contribute to the rightmost position.
+                if (!isRenderView() || r->yPos() + r->height() > 0 || r->yPos() + r->lowestPosition(false) > 0) {
+                    int rp = r->xPos() + r->rightmostPosition(false);
+                    right = max(right, rp + relativeOffset);
+                }
+            }
+        }
+    }
+
+    if (m_hasColumns) {
+        // This only matters for LTR
+        if (style()->direction() == LTR)
+            right = max(columnRects()->last().right() + relativeOffset, right);
+        return right;
+    }
+
+    if (m_floatingObjects) {
+        FloatingObject* r;
+        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+        for ( ; (r = it.current()); ++it ) {
+            if (r->m_shouldPaint || r->m_renderer->hasLayer()) {
+                int rp = r->m_left + r->m_renderer->marginLeft() + r->m_renderer->rightmostPosition(false);
+                right = max(right, rp + relativeOffset);
+            }
+        }
+    }
+
+    if (!includeSelf && firstLineBox()) {
+        for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) {
+            int rp = currBox->xPos() + currBox->width();
+            // If this node is a root editable element, then the rightmostPosition should account for a caret at the end.
+            // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
+            if (node()->isContentEditable() && node() == node()->rootEditableElement() && style()->direction() == LTR)
+                rp += 1;
+            right = max(right, rp);
+        }
+    }
+    
+    return right;
+}
+
+int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    int left = RenderFlow::leftmostPosition(includeOverflowInterior, includeSelf);
+    if (!includeOverflowInterior && hasOverflowClip())
+        return left;
+    
+    int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetX() : 0;
+
+    if (includeSelf)
+        left = min(left, m_overflowLeft + relativeOffset);
+
+    if (m_positionedObjects) {
+        RenderObject* r;
+        Iterator end = m_positionedObjects->end();
+        for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
+            r = *it;
+            // Fixed positioned objects do not scroll and thus should not constitute
+            // part of the leftmost position.
+            if (r->style()->position() != FixedPosition) {
+                // FIXME: Should work for overflow sections too.
+                // If a positioned object lies completely above the root it will be unreachable via scrolling.
+                // Therefore we should not allow it to contribute to the leftmost position.
+                if (!isRenderView() || r->yPos() + r->height() > 0 || r->yPos() + r->lowestPosition(false) > 0) {
+                    int lp = r->xPos() + r->leftmostPosition(false);
+                    left = min(left, lp + relativeOffset);
+                }
+            }
+        }
+    }
+
+    if (m_hasColumns) {
+        // This only matters for RTL
+        if (style()->direction() == RTL)
+            left = min(columnRects()->last().x() + relativeOffset, left);
+        return left;
+    }
+
+    if (m_floatingObjects) {
+        FloatingObject* r;
+        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+        for ( ; (r = it.current()); ++it ) {
+            if (r->m_shouldPaint || r->m_renderer->hasLayer()) {
+                int lp = r->m_left + r->m_renderer->marginLeft() + r->m_renderer->leftmostPosition(false);
+                left = min(left, lp + relativeOffset);
+            }
+        }
+    }
+
+    if (!includeSelf && firstLineBox()) {
+        for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox())
+            left = min(left, (int)currBox->xPos());
+    }
+    
+    return left;
+}
+
+int
+RenderBlock::leftBottom()
+{
+    if (!m_floatingObjects) return 0;
+    int bottom=0;
+    FloatingObject* r;
+    DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+    for ( ; (r = it.current()); ++it )
+        if (r->m_bottom > bottom && r->type() == FloatingObject::FloatLeft)
+            bottom=r->m_bottom;
+
+    return bottom;
+}
+
+int
+RenderBlock::rightBottom()
+{
+    if (!m_floatingObjects) return 0;
+    int bottom=0;
+    FloatingObject* r;
+    DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+    for ( ; (r = it.current()); ++it )
+        if (r->m_bottom>bottom && r->type() == FloatingObject::FloatRight)
+            bottom=r->m_bottom;
+
+    return bottom;
+}
+
+void RenderBlock::markLinesDirtyInVerticalRange(int top, int bottom)
+{
+    if (top >= bottom)
+        return;
+
+    RootInlineBox* lowestDirtyLine = lastRootBox();
+    RootInlineBox* afterLowest = lowestDirtyLine;
+    while (lowestDirtyLine && lowestDirtyLine->blockHeight() >= bottom) {
+        afterLowest = lowestDirtyLine;
+        lowestDirtyLine = lowestDirtyLine->prevRootBox();
+    }
+
+    while (afterLowest && afterLowest->blockHeight() >= top) {
+        afterLowest->markDirty();
+        afterLowest = afterLowest->prevRootBox();
+    }
+}
+
+void RenderBlock::clearFloats()
+{
+    // Inline blocks are covered by the isReplaced() check in the avoidFloats method.
+    if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrPositioned() || isTableCell()) {
+        if (m_floatingObjects)
+            m_floatingObjects->clear();
+        return;
+    }
+
+    typedef HashMap<RenderObject*, FloatingObject*> RendererToFloatInfoMap;
+    RendererToFloatInfoMap floatMap;
+
+    if (m_floatingObjects) {
+        if (childrenInline()) {
+            m_floatingObjects->first();
+            while (FloatingObject* f = m_floatingObjects->take())
+                floatMap.add(f->m_renderer, f);
+        } else
+            m_floatingObjects->clear();
+    }
+
+    // Attempt to locate a previous sibling with overhanging floats.  We skip any elements that are
+    // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
+    // to avoid floats.
+    bool parentHasFloats = false;
+    RenderObject *prev = previousSibling();
+    while (prev && (!prev->isRenderBlock() || prev->avoidsFloats() || prev->isFloatingOrPositioned())) {
+        if (prev->isFloating())
+            parentHasFloats = true;
+         prev = prev->previousSibling();
+    }
+
+    // First add in floats from the parent.
+    int offset = m_y;
+    if (parentHasFloats)
+        addIntrudingFloats(static_cast<RenderBlock *>(parent()),
+                           parent()->borderLeft() + parent()->paddingLeft(), offset);
+
+    int xoffset = 0;
+    if (prev)
+        offset -= prev->yPos();
+    else {
+        prev = parent();
+        xoffset += prev->borderLeft() + prev->paddingLeft();
+    }
+
+    // Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.
+    if (!prev->isRenderBlock()) return;
+    RenderBlock* block = static_cast<RenderBlock *>(prev);
+
+    if (block->m_floatingObjects && block->floatBottom() > offset)
+        addIntrudingFloats(block, xoffset, offset);
+
+    if (childrenInline()) {
+        int changeTop = INT_MAX;
+        int changeBottom = INT_MIN;
+        if (m_floatingObjects) {
+            for (FloatingObject* f = m_floatingObjects->first(); f; f = m_floatingObjects->next()) {
+                FloatingObject* oldFloatingObject = floatMap.get(f->m_renderer);
+                if (oldFloatingObject) {
+                    if (f->m_width != oldFloatingObject->m_width || f->m_left != oldFloatingObject->m_left) {
+                        changeTop = 0;
+                        changeBottom = max(changeBottom, max(f->m_bottom, oldFloatingObject->m_bottom));
+                    } else if (f->m_bottom != oldFloatingObject->m_bottom) {
+                        changeTop = min(changeTop, min(f->m_bottom, oldFloatingObject->m_bottom));
+                        changeBottom = max(changeBottom, max(f->m_bottom, oldFloatingObject->m_bottom));
+                    }
+
+                    floatMap.remove(f->m_renderer);
+                    delete oldFloatingObject;
+                } else {
+                    changeTop = 0;
+                    changeBottom = max(changeBottom, f->m_bottom);
+                }
+            }
+        }
+
+        RendererToFloatInfoMap::iterator end = floatMap.end();
+        for (RendererToFloatInfoMap::iterator it = floatMap.begin(); it != end; ++it) {
+            FloatingObject* floatingObject = (*it).second;
+            if (!floatingObject->m_isDescendant) {
+                changeTop = 0;
+                changeBottom = max(changeBottom, floatingObject->m_bottom);
+            }
+        }
+        deleteAllValues(floatMap);
+
+        markLinesDirtyInVerticalRange(changeTop, changeBottom);
+    }
+}
+
+int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bool makeChildPaintOtherFloats)
+{
+    // Prevent floats from being added to the canvas by the root element, e.g., <html>.
+    if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot())
+        return 0;
+
+    int lowestFloatBottom = 0;
+
+    // Floats that will remain the child's responsiblity to paint should factor into its
+    // visual overflow.
+    IntRect floatsOverflowRect;
+    DeprecatedPtrListIterator<FloatingObject> it(*child->m_floatingObjects);
+    for (FloatingObject* r; (r = it.current()); ++it) {
+        int bottom = child->yPos() + r->m_bottom;
+        lowestFloatBottom = max(lowestFloatBottom, bottom);
+
+        if (bottom > height()) {
+            // If the object is not in the list, we add it now.
+            if (!containsFloat(r->m_renderer)) {
+                FloatingObject *floatingObj = new FloatingObject(r->type());
+                floatingObj->m_top = r->m_top - yoff;
+                floatingObj->m_bottom = r->m_bottom - yoff;
+                floatingObj->m_left = r->m_left - xoff;
+                floatingObj->m_width = r->m_width;
+                floatingObj->m_renderer = r->m_renderer;
+
+                // The nearest enclosing layer always paints the float (so that zindex and stacking
+                // behaves properly).  We always want to propagate the desire to paint the float as
+                // far out as we can, to the outermost block that overlaps the float, stopping only
+                // if we hit a layer boundary.
+                if (r->m_renderer->enclosingLayer() == enclosingLayer())
+                    r->m_shouldPaint = false;
+                else
+                    floatingObj->m_shouldPaint = false;
+                
+                // We create the floating object list lazily.
+                if (!m_floatingObjects) {
+                    m_floatingObjects = new DeprecatedPtrList<FloatingObject>;
+                    m_floatingObjects->setAutoDelete(true);
+                }
+                m_floatingObjects->append(floatingObj);
+            }
+        } else if (makeChildPaintOtherFloats && !r->m_shouldPaint && !r->m_renderer->hasLayer() && r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingLayer() == child->enclosingLayer())
+            // The float is not overhanging from this block, so if it is a descendant of the child, the child should
+            // paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing
+            // layer.
+            // If makeChildPaintOtherFloats is false, it means that the child must already know about all the floats
+            // it should paint.
+            r->m_shouldPaint = true;
+
+        if (r->m_shouldPaint && !r->m_renderer->hasLayer()) {
+            IntRect floatOverflowRect = r->m_renderer->overflowRect(false);
+            floatOverflowRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop());
+            floatsOverflowRect.unite(floatOverflowRect);
+        }
+    }
+    child->addVisualOverflow(floatsOverflowRect);
+    return lowestFloatBottom;
+}
+
+void RenderBlock::addIntrudingFloats(RenderBlock* prev, int xoff, int yoff)
+{
+    // If the parent or previous sibling doesn't have any floats to add, don't bother.
+    if (!prev->m_floatingObjects)
+        return;
+
+    DeprecatedPtrListIterator<FloatingObject> it(*prev->m_floatingObjects);
+    for (FloatingObject *r; (r = it.current()); ++it) {
+        if (r->m_bottom > yoff) {
+            // The object may already be in our list. Check for it up front to avoid
+            // creating duplicate entries.
+            FloatingObject* f = 0;
+            if (m_floatingObjects) {
+                DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+                while ((f = it.current())) {
+                    if (f->m_renderer == r->m_renderer) break;
+                    ++it;
+                }
+            }
+            if (!f) {
+                FloatingObject *floatingObj = new FloatingObject(r->type());
+                floatingObj->m_top = r->m_top - yoff;
+                floatingObj->m_bottom = r->m_bottom - yoff;
+                floatingObj->m_left = r->m_left - xoff;
+                // Applying the child's margin makes no sense in the case where the child was passed in.
+                // since his own margin was added already through the subtraction of the |xoff| variable
+                // above.  |xoff| will equal -flow->marginLeft() in this case, so it's already been taken
+                // into account.  Only apply this code if |child| is false, since otherwise the left margin
+                // will get applied twice.
+                if (prev != parent())
+                    floatingObj->m_left += prev->marginLeft();
+                floatingObj->m_left -= marginLeft();
+                floatingObj->m_shouldPaint = false;  // We are not in the direct inheritance chain for this float. We will never paint it.
+                floatingObj->m_width = r->m_width;
+                floatingObj->m_renderer = r->m_renderer;
+                
+                // We create the floating object list lazily.
+                if (!m_floatingObjects) {
+                    m_floatingObjects = new DeprecatedPtrList<FloatingObject>;
+                    m_floatingObjects->setAutoDelete(true);
+                }
+                m_floatingObjects->append(floatingObj);
+            }
+        }
+    }
+}
+
+bool RenderBlock::avoidsFloats() const
+{
+    // Floats can't intrude into our box if we have a non-auto column count or width.
+    return RenderFlow::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();
+}
+
+bool RenderBlock::containsFloat(RenderObject* o)
+{
+    if (m_floatingObjects) {
+        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+        while (it.current()) {
+            if (it.current()->m_renderer == o)
+                return true;
+            ++it;
+        }
+    }
+    return false;
+}
+
+void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove)
+{
+    setChildNeedsLayout(true);
+
+    if (floatToRemove)
+        removeFloatingObject(floatToRemove);
+
+    // Iterate over our children and mark them as needed.
+    if (!childrenInline()) {
+        for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+            if (isBlockFlow() && !child->isFloatingOrPositioned() &&
+                ((floatToRemove ? child->containsFloat(floatToRemove) : child->containsFloats()) || child->shrinkToAvoidFloats()))
+                child->markAllDescendantsWithFloatsForLayout(floatToRemove);
+        }
+    }
+}
+
+int RenderBlock::getClearDelta(RenderObject *child)
+{
+    // There is no need to compute clearance if we have no floats.
+    if (!containsFloats())
+        return 0;
+    
+    // At least one float is present.  We need to perform the clearance computation.
+    bool clearSet = child->style()->clear() != CNONE;
+    int bottom = 0;
+    switch (child->style()->clear()) {
+        case CNONE:
+            break;
+        case CLEFT:
+            bottom = leftBottom();
+            break;
+        case CRIGHT:
+            bottom = rightBottom();
+            break;
+        case CBOTH:
+            bottom = floatBottom();
+            break;
+    }
+
+    // We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default).
+    // FIXME: Note that the remaining space checks aren't quite accurate, since you should be able to clear only some floats (the minimum # needed
+    // to fit) and not all (we should be using nextFloatBottomBelow and looping).
+    // Do not allow tables to wrap in quirks or even in almost strict mode 
+    // (ebay on the PLT, finance.yahoo.com in the real world, versiontracker.com forces even almost strict mode not to work)
+    int result = clearSet ? max(0, bottom - child->yPos()) : 0;
+    if (!result && child->avoidsFloats() && child->style()->width().isFixed() && 
+        child->minPrefWidth() > lineWidth(child->yPos()) && child->minPrefWidth() <= availableWidth() && 
+        document()->inStrictMode())   
+        result = max(0, floatBottom() - child->yPos());
+    return result;
+}
+
+void RenderBlock::addVisualOverflow(const IntRect& r)
+{
+    if (r.isEmpty())
+        return;
+    m_overflowLeft = min(m_overflowLeft, r.x());
+    m_overflowWidth = max(m_overflowWidth, r.right());
+    m_overflowTop = min(m_overflowTop, r.y());
+    m_overflowHeight = max(m_overflowHeight, r.bottom());
+}
+
+bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty)
+{
+    if (!scrollsOverflow())
+        return false;
+
+    return layer()->hitTestOverflowControls(result);
+}
+
+bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
+{
+    bool inlineFlow = isInlineFlow();
+
+    int tx = _tx + m_x;
+    int ty = _ty + m_y + borderTopExtra();
+
+    if (!inlineFlow && !isRenderView()) {
+        // Check if we need to do anything at all.
+        IntRect overflowBox = overflowRect(false);
+        overflowBox.move(tx, ty);
+        if (!overflowBox.contains(_x, _y))
+            return false;
+    }
+
+    if (isPointInOverflowControl(result, _x, _y, tx, ty)) {
+        if (hitTestAction == HitTestBlockBackground) {
+            updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
+            return true;
+        }
+        return false;
+    }
+
+     // If we have lightweight control clipping, then we can't have any spillout. 
+    if (!hasControlClip() || controlClipRect(tx, ty).contains(_x, _y)) {
+        // Hit test descendants first.
+        int scrolledX = tx;
+        int scrolledY = ty;
+        if (hasOverflowClip())
+            m_layer->subtractScrollOffset(scrolledX, scrolledY);
+
+        // Hit test contents if we don't have columns.
+        if (!m_hasColumns && hitTestContents(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
+            return true;
+            
+        // Hit test our columns if we do have them.
+        if (m_hasColumns && hitTestColumns(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
+            return true;
+
+        // Hit test floats.
+        if (hitTestAction == HitTestFloat && m_floatingObjects) {
+            if (isRenderView()) {
+                scrolledX += static_cast<RenderView*>(this)->frameView()->scrollX();
+                scrolledY += static_cast<RenderView*>(this)->frameView()->scrollY();
+            }
+            
+            FloatingObject* o;
+            DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+            for (it.toLast(); (o = it.current()); --it) {
+                if (o->m_shouldPaint && !o->m_renderer->hasLayer()) {
+                    int xoffset = scrolledX + o->m_left + o->m_renderer->marginLeft() - o->m_renderer->xPos();
+                    int yoffset =  scrolledY + o->m_top + o->m_renderer->marginTop() - o->m_renderer->yPos();
+                    if (o->m_renderer->hitTest(request, result, IntPoint(_x, _y), xoffset, yoffset)) {
+                        updateHitTestResult(result, IntPoint(_x - xoffset, _y - yoffset));
+                        return true;
+                    }
+                }
+            }
+        }
+    }
+
+    // Now hit test our background.
+    if (!inlineFlow && (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground)) {
+        int topExtra = borderTopExtra();
+        IntRect boundsRect(tx, ty - topExtra, m_width, m_height + topExtra + borderBottomExtra());
+        if (style()->visibility() == VISIBLE && boundsRect.contains(_x, _y)) {
+            updateHitTestResult(result, IntPoint(_x - tx, _y - ty + topExtra));
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
+{
+    // We need to do multiple passes, breaking up our hit testing into strips.
+    // We can always go left to right, since column contents are clipped (meaning that there
+    // can't be any overlap).
+    int currXOffset = 0;
+    int currYOffset = 0;
+    int colGap = columnGap();
+    Vector<IntRect>* colRects = columnRects();
+    for (unsigned i = 0; i < colRects->size(); i++) {
+        IntRect colRect = colRects->at(i);
+        colRect.move(tx, ty);
+        
+        if (colRect.contains(x, y)) {
+            // The point is inside this column.
+            // Adjust tx and ty to change where we hit test.
+        
+            int finalX = tx + currXOffset;
+            int finalY = ty + currYOffset;
+            return hitTestContents(request, result, x, y, finalX, finalY, hitTestAction);
+        }
+        
+        // Move to the next position.
+        if (style()->direction() == LTR)
+            currXOffset += colRect.width() + colGap;
+        else
+            currXOffset -= (colRect.width() + colGap);
+
+        currYOffset -= colRect.height();
+    }
+
+    return false;
+}
+
+bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
+{
+    if (childrenInline() && !isTable()) {
+        // We have to hit-test our line boxes.
+        if (hitTestLines(request, result, x, y, tx, ty, hitTestAction)) {
+            updateHitTestResult(result, IntPoint(x - tx, y - ty));
+            return true;
+        }
+    } else {
+        // Hit test our children.
+        HitTestAction childHitTest = hitTestAction;
+        if (hitTestAction == HitTestChildBlockBackgrounds)
+            childHitTest = HitTestChildBlockBackground;
+        for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+            // FIXME: We have to skip over inline flows, since they can show up inside RenderTables at the moment (a demoted inline <form> for example).  If we ever implement a
+            // table-specific hit-test method (which we should do for performance reasons anyway), then we can remove this check.
+            if (!child->hasLayer() && !child->isFloating() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, childHitTest)) {
+                updateHitTestResult(result, IntPoint(x - tx, y - ty));
+                return true;
+            }
+        }
+    }
+    
+    return false;
+}
+
+Position RenderBlock::positionForBox(InlineBox *box, bool start) const
+{
+    if (!box)
+        return Position();
+
+    if (!box->object()->element())
+        return Position(element(), start ? caretMinOffset() : caretMaxOffset());
+
+    if (!box->isInlineTextBox())
+        return Position(box->object()->element(), start ? box->object()->caretMinOffset() : box->object()->caretMaxOffset());
+
+    InlineTextBox *textBox = static_cast<InlineTextBox *>(box);
+    return Position(box->object()->element(), start ? textBox->start() : textBox->start() + textBox->len());
+}
+
+Position RenderBlock::positionForRenderer(RenderObject* renderer, bool start) const
+{
+    if (!renderer)
+        return Position(element(), 0);
+
+    Node* node = renderer->element() ? renderer->element() : element();
+    if (!node)
+        return Position();
+
+    ASSERT(renderer == node->renderer());
+
+    int offset = start ? renderer->caretMinOffset() : renderer->caretMaxOffset();
+
+    // FIXME: This was a runtime check that seemingly couldn't fail; changed it to an assertion for now.
+    ASSERT(!node->isCharacterDataNode() || renderer->isText());
+
+    return Position(node, offset);
+}
+
+VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
+{
+    if (isTable())
+        return RenderFlow::positionForCoordinates(x, y); 
+
+    int top = borderTop();
+    int bottom = top + borderTopExtra() + paddingTop() + contentHeight() + paddingBottom() + borderBottomExtra();
+
+    int left = borderLeft();
+    int right = left + paddingLeft() + contentWidth() + paddingRight();
+
+    Node* n = element();
+    
+    int contentsX = x;
+    int contentsY = y - borderTopExtra();
+    if (hasOverflowClip())
+        m_layer->scrollOffset(contentsX, contentsY);
+    if (m_hasColumns) {
+        IntPoint contentsPoint(contentsX, contentsY);
+        adjustPointToColumnContents(contentsPoint);
+        contentsX = contentsPoint.x();
+        contentsY = contentsPoint.y();
+    }
+
+    if (isReplaced()) {
+        if (y < 0 || y < height() && x < 0)
+            return VisiblePosition(n, caretMinOffset(), DOWNSTREAM);
+        if (y >= height() || y >= 0 && x >= width())
+            return VisiblePosition(n, caretMaxOffset(), DOWNSTREAM);
+    } 
+
+    // If we start inside the shadow tree, we will stay inside (even if the point is above or below).
+    if (!(n && n->isShadowNode()) && !childrenInline()) {
+        // Don't return positions inside editable roots for coordinates outside those roots, except for coordinates outside
+        // a document that is entirely editable.
+        bool isEditableRoot = n && n->rootEditableElement() == n && !n->hasTagName(bodyTag) && !n->hasTagName(htmlTag);
+
+        if (y < top || (isEditableRoot && (y < bottom && x < left))) {
+            if (!isEditableRoot)
+                if (RenderObject* c = firstChild()) { // FIXME: This code doesn't make any sense.  This child could be an inline or a positioned element or a float or a compact, etc.
+                    VisiblePosition p = c->positionForCoordinates(contentsX - c->xPos(), contentsY - c->yPos());
+                    if (p.isNotNull())
+                        return p;
+                }
+            if (n) {
+                if (Node* sp = n->shadowParentNode())
+                    n = sp;
+                if (Node* p = n->parent())
+                    return VisiblePosition(p, n->nodeIndex(), DOWNSTREAM);
+            }
+            return VisiblePosition(n, 0, DOWNSTREAM);
+        }
+
+        if (y >= bottom || (isEditableRoot && (y >= top && x >= right))) {
+            if (!isEditableRoot)
+                if (RenderObject* c = lastChild()) { // FIXME: This code doesn't make any sense.  This child could be an inline or a positioned element or a float or a compact, ect.
+                    VisiblePosition p = c->positionForCoordinates(contentsX - c->xPos(), contentsY - c->yPos());
+                    if (p.isNotNull())
+                        return p;
+                }
+            if (n) {
+                if (Node* sp = n->shadowParentNode())
+                    n = sp;
+                if (Node* p = n->parent())
+                    return VisiblePosition(p, n->nodeIndex() + 1, DOWNSTREAM);
+            }
+            return VisiblePosition(n, 0, DOWNSTREAM);
+        }
+    }
+
+    if (childrenInline()) {
+        if (!firstRootBox())
+            return VisiblePosition(n, 0, DOWNSTREAM);
+
+        if (contentsY < firstRootBox()->topOverflow() - verticalLineClickFudgeFactor)
+            // y coordinate is above first root line box
+            return VisiblePosition(positionForBox(firstRootBox()->firstLeafChild(), true), DOWNSTREAM);
+        
+        // look for the closest line box in the root box which is at the passed-in y coordinate
+        for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
+            // set the bottom based on whether there is a next root box
+            if (root->nextRootBox())
+                // FIXME: make the break point halfway between the bottom of the previous root box and the top of the next root box
+                bottom = root->nextRootBox()->topOverflow();
+            else
+                bottom = root->bottomOverflow() + verticalLineClickFudgeFactor;
+            // check if this root line box is located at this y coordinate
+            if (contentsY < bottom && root->firstChild()) {
+                InlineBox* closestBox = root->closestLeafChildForXPos(x);
+                if (closestBox)
+                    // pass the box a y position that is inside it
+                    return closestBox->object()->positionForCoordinates(contentsX, closestBox->m_y);
+            }
+        }
+
+        if (lastRootBox())
+            // y coordinate is below last root line box
+            return VisiblePosition(positionForBox(lastRootBox()->lastLeafChild(), false), DOWNSTREAM);
+
+        return VisiblePosition(n, 0, DOWNSTREAM);
+    }
+    
+    // See if any child blocks exist at this y coordinate.
+    if (firstChild() && contentsY < firstChild()->yPos())
+        return VisiblePosition(n, 0, DOWNSTREAM);
+    for (RenderObject* renderer = firstChild(); renderer; renderer = renderer->nextSibling()) {
+        if (renderer->height() == 0 || renderer->style()->visibility() != VISIBLE || renderer->isFloatingOrPositioned())
+            continue;
+        RenderObject* next = renderer->nextSibling();
+        while (next && next->isFloatingOrPositioned())
+            next = next->nextSibling();
+        if (next) 
+            bottom = next->yPos();
+        else
+            bottom = top + scrollHeight();
+        if (contentsY >= renderer->yPos() && contentsY < bottom)
+            return renderer->positionForCoordinates(contentsX - renderer->xPos(), contentsY - renderer->yPos());
+    }
+    
+    return RenderFlow::positionForCoordinates(x, y);
+}
+
+int RenderBlock::availableWidth() const
+{
+    // If we have multiple columns, then the available width is reduced to our column width.
+    if (m_hasColumns)
+        return desiredColumnWidth();
+    return contentWidth();
+}
+
+int RenderBlock::columnGap() const
+{
+    if (style()->hasNormalColumnGap())
+        return style()->fontDescription().computedPixelSize(); // "1em" is recommended as the normal gap setting. Matches <p> margins.
+    return static_cast<int>(style()->columnGap());
+}
+
+void RenderBlock::calcColumnWidth()
+{    
+    // Calculate our column width and column count.
+    unsigned desiredColumnCount = 1;
+    int desiredColumnWidth = contentWidth();
+    
+    // For now, we don't support multi-column layouts when printing, since we have to do a lot of work for proper pagination.
+    if (document()->printing() || (style()->hasAutoColumnCount() && style()->hasAutoColumnWidth())) {
+        setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
+        return;
+    }
+        
+    int availWidth = desiredColumnWidth;
+    int colGap = columnGap();
+    int colWidth = max(1, static_cast<int>(style()->columnWidth()));
+    int colCount = max(1, static_cast<int>(style()->columnCount()));
+
+    if (style()->hasAutoColumnWidth()) {
+        if ((colCount - 1) * colGap < availWidth) {
+            desiredColumnCount = colCount;
+            desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
+        } else if (colGap < availWidth) {
+            desiredColumnCount = availWidth / colGap;
+            desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
+        }
+    } else if (style()->hasAutoColumnCount()) {
+        if (colWidth < availWidth) {
+            desiredColumnCount = (availWidth + colGap) / (colWidth + colGap);
+            desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
+        }
+    } else {
+        // Both are set.
+        if (colCount * colWidth + (colCount - 1) * colGap <= availWidth) {
+            desiredColumnCount = colCount;
+            desiredColumnWidth = colWidth;
+        } else if (colWidth < availWidth) {
+            desiredColumnCount = (availWidth + colGap) / (colWidth + colGap);
+            desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
+        }
+    }
+    setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
+}
+
+void RenderBlock::setDesiredColumnCountAndWidth(int count, int width)
+{
+    if (count == 1) {
+        if (m_hasColumns) {
+            delete gColumnInfoMap->take(this);
+            m_hasColumns = false;
+        }
+    } else {
+        ColumnInfo* info;
+        if (m_hasColumns)
+            info = gColumnInfoMap->get(this);
+        else {
+            if (!gColumnInfoMap)
+                gColumnInfoMap = new ColumnInfoMap;
+            info = new ColumnInfo;
+            gColumnInfoMap->add(this, info);
+            m_hasColumns = true;
+        }
+        info->m_desiredColumnCount = count;
+        info->m_desiredColumnWidth = width;   
+    }
+}
+
+int RenderBlock::desiredColumnWidth() const
+{
+    if (!m_hasColumns)
+        return contentWidth();
+    return gColumnInfoMap->get(this)->m_desiredColumnWidth;
+}
+
+unsigned RenderBlock::desiredColumnCount() const
+{
+    if (!m_hasColumns)
+        return 1;
+    return gColumnInfoMap->get(this)->m_desiredColumnCount;
+}
+
+Vector<IntRect>* RenderBlock::columnRects() const
+{
+    if (!m_hasColumns)
+        return 0;
+    return &gColumnInfoMap->get(this)->m_columnRects;    
+}
+
+int RenderBlock::layoutColumns(int endOfContent)
+{
+    // Don't do anything if we have no columns
+    if (!m_hasColumns)
+        return -1;
+
+    ColumnInfo* info = gColumnInfoMap->get(this);
+    int desiredColumnWidth = info->m_desiredColumnWidth;
+    int desiredColumnCount = info->m_desiredColumnCount;
+    Vector<IntRect>* columnRects = &info->m_columnRects;
+    
+    bool computeIntrinsicHeight = (endOfContent == -1);
+
+    // Fill the columns in to the available height.  Attempt to balance the height of the columns
+    int availableHeight = contentHeight();
+    int colHeight = computeIntrinsicHeight ? availableHeight / desiredColumnCount : availableHeight;
+    
+    // Add in half our line-height to help with best-guess initial balancing.
+    int columnSlop = lineHeight(false) / 2;
+    int remainingSlopSpace = columnSlop * desiredColumnCount;
+
+    if (computeIntrinsicHeight)
+        colHeight += columnSlop;
+                                                                            
+    int colGap = columnGap();
+
+    // Compute a collection of column rects.
+    columnRects->clear();
+    
+    // Then we do a simulated "paint" into the column slices and allow the content to slightly adjust our individual column rects.
+    // FIXME: We need to take into account layers that are affected by the columns as well here so that they can have an opportunity
+    // to adjust column rects also.
+    RenderView* v = view();
+    int left = borderLeft() + paddingLeft();
+    int top = borderTop() + paddingTop();
+    int currX = style()->direction() == LTR ? borderLeft() + paddingLeft() : borderLeft() + paddingLeft() + contentWidth() - desiredColumnWidth;
+    int currY = top;
+    unsigned colCount = desiredColumnCount;
+    int maxColBottom = borderTop() + paddingTop();
+    int contentBottom = top + availableHeight; 
+    for (unsigned i = 0; i < colCount; i++) {
+        // If we aren't constrained, then the last column can just get all the remaining space.
+        if (computeIntrinsicHeight && i == colCount - 1)
+            colHeight = availableHeight;
+
+        // This represents the real column position.
+        IntRect colRect(currX, top, desiredColumnWidth, colHeight);
+        
+        // For the simulated paint, we pretend like everything is in one long strip.
+        IntRect pageRect(left, currY, desiredColumnWidth, colHeight);
+        v->setPrintRect(pageRect);
+        v->setTruncatedAt(currY + colHeight);
+        GraphicsContext context((PlatformGraphicsContext*)0);
+        RenderObject::PaintInfo paintInfo(&context, pageRect, PaintPhaseForeground, false, 0, 0);
+        
+        m_hasColumns = false;
+        paintObject(paintInfo, 0, 0);
+        m_hasColumns = true;
+
+        int adjustedBottom = v->bestTruncatedAt();
+        if (adjustedBottom <= currY)
+            adjustedBottom = currY + colHeight;
+        
+        colRect.setHeight(adjustedBottom - currY);
+        
+        // Add in the lost space to the subsequent columns.
+        // FIXME: This will create a "staircase" effect if there are enough columns, but the effect should be pretty subtle.
+        if (computeIntrinsicHeight) {
+            int lostSpace = colHeight - colRect.height();
+            if (lostSpace > remainingSlopSpace) {
+                // Redestribute the space among the remaining columns.
+                int spaceToRedistribute = lostSpace - remainingSlopSpace;
+                int remainingColumns = colCount - i + 1;
+                colHeight += spaceToRedistribute / remainingColumns;
+            } 
+            remainingSlopSpace = max(0, remainingSlopSpace - lostSpace);
+        }
+        
+        if (style()->direction() == LTR)
+            currX += desiredColumnWidth + colGap;
+        else
+            currX -= (desiredColumnWidth + colGap);
+
+        currY += colRect.height();
+        availableHeight -= colRect.height();
+
+        maxColBottom = max(colRect.bottom(), maxColBottom);
+
+        columnRects->append(colRect);
+        
+        // Start adding in more columns as long as there's still content left.
+        if (currY < endOfContent && i == colCount - 1 && (computeIntrinsicHeight || contentHeight()))
+            colCount++;
+    }
+
+    m_overflowWidth = max(m_width, currX - colGap);
+    m_overflowLeft = min(0, currX + desiredColumnWidth + colGap);
+
+    m_overflowHeight = maxColBottom;
+    int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
+        
+    if (computeIntrinsicHeight)
+        m_height = m_overflowHeight + toAdd;
+
+    v->setPrintRect(IntRect());
+    v->setTruncatedAt(0);
+    
+    ASSERT(colCount == columnRects->size());
+    
+    return contentBottom;
+}
+
+void RenderBlock::adjustPointToColumnContents(IntPoint& point) const
+{
+    // Just bail if we have no columns.
+    if (!m_hasColumns)
+        return;
+    
+    Vector<IntRect>* colRects = columnRects();
+
+    // Determine which columns we intersect.
+    int colGap = columnGap();
+    int leftGap = colGap / 2;
+    IntPoint columnPoint(colRects->at(0).location());
+    int yOffset = 0;
+    for (unsigned i = 0; i < colRects->size(); i++) {
+        // Add in half the column gap to the left and right of the rect.
+        IntRect colRect = colRects->at(i);
+        IntRect gapAndColumnRect(colRect.x() - leftGap, colRect.y(), colRect.width() + colGap, colRect.height());
+        
+        if (gapAndColumnRect.contains(point)) {
+            // We're inside the column.  Translate the x and y into our column coordinate space.
+            point.move(columnPoint.x() - colRect.x(), yOffset);
+            return;
+        }
+
+        // Move to the next position.
+        yOffset += colRect.height();
+    }
+}
+
+void RenderBlock::adjustRectForColumns(IntRect& r) const
+{
+    // Just bail if we have no columns.
+    if (!m_hasColumns)
+        return;
+    
+    Vector<IntRect>* colRects = columnRects();
+
+    // Begin with a result rect that is empty.
+    IntRect result;
+    
+    // Determine which columns we intersect.
+    int currXOffset = 0;
+    int currYOffset = 0;
+    int colGap = columnGap();
+    for (unsigned i = 0; i < colRects->size(); i++) {
+        IntRect colRect = colRects->at(i);
+        
+        IntRect repaintRect = r;
+        repaintRect.move(currXOffset, currYOffset);
+        
+        repaintRect.intersect(colRect);
+        
+        result.unite(repaintRect);
+
+        // Move to the next position.
+        if (style()->direction() == LTR)
+            currXOffset += colRect.width() + colGap;
+        else
+            currXOffset -= (colRect.width() + colGap);
+
+        currYOffset -= colRect.height();
+    }
+
+    r = result;
+}
+
+void RenderBlock::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+
+    updateFirstLetter();
+
+    if (!isTableCell() && style()->width().isFixed() && style()->width().value() > 0)
+        m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
+    else {
+        m_minPrefWidth = 0;
+        m_maxPrefWidth = 0;
+
+        if (childrenInline())
+            calcInlinePrefWidths();
+        else
+            calcBlockPrefWidths();
+
+        m_maxPrefWidth = max(m_minPrefWidth, m_maxPrefWidth);
+
+        if (!style()->autoWrap() && childrenInline()) {
+            m_minPrefWidth = m_maxPrefWidth;
+            
+            // A horizontal marquee with inline children has no minimum width.
+            if (m_layer && m_layer->marquee() && m_layer->marquee()->isHorizontal())
+                m_minPrefWidth = 0;
+        }
+
+        if (isTableCell()) {
+            Length w = static_cast<const RenderTableCell*>(this)->styleOrColWidth();
+            if (w.isFixed() && w.value() > 0)
+                m_maxPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(w.value()));
+        }
+    }
+    
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+        m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+    }
+    
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
+        m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+        m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+    }
+
+    int toAdd = 0;
+    toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
+
+    m_minPrefWidth += toAdd;
+    m_maxPrefWidth += toAdd;
+
+    setPrefWidthsDirty(false);
+}
+
+struct InlineMinMaxIterator
+{
+/* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
+   inline min/max width calculations.  Note the following about the way it walks:
+   (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
+   (2) We do not drill into the children of floats or replaced elements, since you can't break
+       in the middle of such an element.
+   (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
+       distinct borders/margin/padding that contribute to the min/max width.
+*/
+    RenderObject* parent;
+    RenderObject* current;
+    bool endOfInline;
+
+    InlineMinMaxIterator(RenderObject* p, bool end = false)
+        :parent(p), current(p), endOfInline(end) {}
+
+    RenderObject* next();
+};
+
+RenderObject* InlineMinMaxIterator::next()
+{
+    RenderObject* result = 0;
+    bool oldEndOfInline = endOfInline;
+    endOfInline = false;
+    while (current || current == parent) {
+        if (!oldEndOfInline &&
+            (current == parent ||
+             (!current->isFloating() && !current->isReplaced() && !current->isPositioned())))
+            result = current->firstChild();
+        if (!result) {
+            // We hit the end of our inline. (It was empty, e.g., <span></span>.)
+            if (!oldEndOfInline && current->isInlineFlow()) {
+                result = current;
+                endOfInline = true;
+                break;
+            }
+
+            while (current && current != parent) {
+                result = current->nextSibling();
+                if (result) break;
+                current = current->parent();
+                if (current && current != parent && current->isInlineFlow()) {
+                    result = current;
+                    endOfInline = true;
+                    break;
+                }
+            }
+        }
+
+        if (!result)
+            break;
+
+        if (!result->isPositioned() && (result->isText() || result->isFloating() || result->isReplaced() || result->isInlineFlow()))
+             break;
+        
+        current = result;
+        result = 0;
+    }
+
+    // Update our position.
+    current = result;
+    return current;
+}
+
+static int getBPMWidth(int childValue, Length cssUnit)
+{
+    if (cssUnit.type() != Auto)
+        return (cssUnit.isFixed() ? cssUnit.value() : childValue);
+    return 0;
+}
+
+static int getBorderPaddingMargin(const RenderObject* child, bool endOfInline)
+{
+    RenderStyle* cstyle = child->style();
+    int result = 0;
+    bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;
+    result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),
+                          (leftSide ? cstyle->marginLeft() :
+                                      cstyle->marginRight()));
+    result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()),
+                          (leftSide ? cstyle->paddingLeft() :
+                                      cstyle->paddingRight()));
+    result += leftSide ? child->borderLeft() : child->borderRight();
+    return result;
+}
+
+static inline void stripTrailingSpace(int& inlineMax, int& inlineMin,
+                                      RenderObject* trailingSpaceChild)
+{
+    if (trailingSpaceChild && trailingSpaceChild->isText()) {
+        // Collapse away the trailing space at the end of a block.
+        RenderText* t = static_cast<RenderText*>(trailingSpaceChild);
+        const UChar space = ' ';
+        const Font& font = t->style()->font(); // FIXME: This ignores first-line.
+        int spaceWidth = font.width(TextRun(&space, 1));
+        inlineMax -= spaceWidth + font.wordSpacing();
+        if (inlineMin > inlineMax)
+            inlineMin = inlineMax;
+    }
+}
+
+void RenderBlock::calcInlinePrefWidths()
+{
+    int inlineMax = 0;
+    int inlineMin = 0;
+
+    int cw = containingBlock()->contentWidth();
+
+    // If we are at the start of a line, we want to ignore all white-space.
+    // Also strip spaces if we previously had text that ended in a trailing space.
+    bool stripFrontSpaces = true;
+    RenderObject* trailingSpaceChild = 0;
+
+    // Firefox and Opera will allow a table cell to grow to fit an image inside it under
+    // very specific cirucumstances (in order to match common WinIE renderings). 
+    // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.) 
+    bool allowImagesToBreak = !style()->htmlHacks() || !isTableCell() || !style()->width().isIntrinsicOrAuto();
+
+    bool autoWrap, oldAutoWrap;
+    autoWrap = oldAutoWrap = style()->autoWrap();
+
+    InlineMinMaxIterator childIterator(this);
+    bool addedTextIndent = false; // Only gets added in once.
+    RenderObject* prevFloat = 0;
+    RenderObject* previousLeaf = 0;
+    while (RenderObject* child = childIterator.next()) {
+        autoWrap = child->isReplaced() ? child->parent()->style()->autoWrap() : 
+            child->style()->autoWrap();
+
+        if (!child->isBR()) {
+            // Step One: determine whether or not we need to go ahead and
+            // terminate our current line.  Each discrete chunk can become
+            // the new min-width, if it is the widest chunk seen so far, and
+            // it can also become the max-width.
+
+            // Children fall into three categories:
+            // (1) An inline flow object.  These objects always have a min/max of 0,
+            // and are included in the iteration solely so that their margins can
+            // be added in.
+            //
+            // (2) An inline non-text non-flow object, e.g., an inline replaced element.
+            // These objects can always be on a line by themselves, so in this situation
+            // we need to go ahead and break the current line, and then add in our own
+            // margins and min/max width on its own line, and then terminate the line.
+            //
+            // (3) A text object.  Text runs can have breakable characters at the start,
+            // the middle or the end.  They may also lose whitespace off the front if
+            // we're already ignoring whitespace.  In order to compute accurate min-width
+            // information, we need three pieces of information.
+            // (a) the min-width of the first non-breakable run.  Should be 0 if the text string
+            // starts with whitespace.
+            // (b) the min-width of the last non-breakable run. Should be 0 if the text string
+            // ends with whitespace.
+            // (c) the min/max width of the string (trimmed for whitespace).
+            //
+            // If the text string starts with whitespace, then we need to go ahead and
+            // terminate our current line (unless we're already in a whitespace stripping
+            // mode.
+            //
+            // If the text string has a breakable character in the middle, but didn't start
+            // with whitespace, then we add the width of the first non-breakable run and
+            // then end the current line.  We then need to use the intermediate min/max width
+            // values (if any of them are larger than our current min/max).  We then look at
+            // the width of the last non-breakable run and use that to start a new line
+            // (unless we end in whitespace).
+            RenderStyle* cstyle = child->style();
+            int childMin = 0;
+            int childMax = 0;
+
+            if (!child->isText()) {
+                // Case (1) and (2).  Inline replaced and inline flow elements.
+                if (child->isInlineFlow()) {
+                    // Add in padding/border/margin from the appropriate side of
+                    // the element.
+                    int bpm = getBorderPaddingMargin(child, childIterator.endOfInline);
+                    childMin += bpm;
+                    childMax += bpm;
+
+                    inlineMin += childMin;
+                    inlineMax += childMax;
+                    
+                    child->setPrefWidthsDirty(false);
+                } else {
+                    // Inline replaced elts add in their margins to their min/max values.
+                    int margins = 0;
+                    Length leftMargin = cstyle->marginLeft();
+                    Length rightMargin = cstyle->marginRight();
+                    if (leftMargin.isFixed())
+                        margins += leftMargin.value();
+                    if (rightMargin.isFixed())
+                        margins += rightMargin.value();
+                    childMin += margins;
+                    childMax += margins;
+                }
+            }
+
+            if (!child->isRenderInline() && !child->isText()) {
+                // Case (2). Inline replaced elements and floats.
+                // Go ahead and terminate the current line as far as
+                // minwidth is concerned.
+                childMin += child->minPrefWidth();
+                childMax += child->maxPrefWidth();
+
+                bool clearPreviousFloat;
+                if (child->isFloating()) {
+                    clearPreviousFloat = (prevFloat
+                        && (prevFloat->style()->floating() == FLEFT && (child->style()->clear() & CLEFT)
+                            || prevFloat->style()->floating() == FRIGHT && (child->style()->clear() & CRIGHT)));
+                    prevFloat = child;
+                } else
+                    clearPreviousFloat = false;
+
+                bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
+                if (canBreakReplacedElement && (autoWrap || oldAutoWrap) || clearPreviousFloat) {
+                    m_minPrefWidth = max(inlineMin, m_minPrefWidth);
+                    inlineMin = 0;
+                }
+
+                // If we're supposed to clear the previous float, then terminate maxwidth as well.
+                if (clearPreviousFloat) {
+                    m_maxPrefWidth = max(inlineMax, m_maxPrefWidth);
+                    inlineMax = 0;
+                }
+
+                // Add in text-indent.  This is added in only once.
+                int ti = 0;
+                if (!addedTextIndent) {
+                    addedTextIndent = true;
+                    ti = style()->textIndent().calcMinValue(cw);
+                    childMin+=ti;
+                    childMax+=ti;
+                }
+
+                // Add our width to the max.
+                inlineMax += childMax;
+
+                if (!autoWrap || !canBreakReplacedElement) {
+                    if (child->isFloating())
+                        m_minPrefWidth = max(childMin, m_minPrefWidth);
+                    else
+                        inlineMin += childMin;
+                } else {
+                    // Now check our line.
+                    m_minPrefWidth = max(childMin, m_minPrefWidth);
+
+                    // Now start a new line.
+                    inlineMin = 0;
+                }
+
+                // We are no longer stripping whitespace at the start of
+                // a line.
+                if (!child->isFloating()) {
+                    stripFrontSpaces = false;
+                    trailingSpaceChild = 0;
+                }
+            } else if (child->isText()) {
+                // Case (3). Text.
+                RenderText* t = static_cast<RenderText *>(child);
+
+                if (t->isWordBreak()) {
+                    m_minPrefWidth = max(inlineMin, m_minPrefWidth);
+                    inlineMin = 0;
+                    continue;
+                }
+
+                // Determine if we have a breakable character.  Pass in
+                // whether or not we should ignore any spaces at the front
+                // of the string.  If those are going to be stripped out,
+                // then they shouldn't be considered in the breakable char
+                // check.
+                bool hasBreakableChar, hasBreak;
+                int beginMin, endMin;
+#ifdef ANDROID_FIX // bug found by valgrind
+                bool beginWS = false, endWS = false;
+#else
+                bool beginWS, endWS;
+#endif
+                int beginMax, endMax;
+                t->trimmedPrefWidths(inlineMax, beginMin, beginWS, endMin, endWS,
+                                     hasBreakableChar, hasBreak, beginMax, endMax,
+                                     childMin, childMax, stripFrontSpaces);
+
+                // This text object will not be rendered, but it may still provide a breaking opportunity.
+                if (!hasBreak && childMax == 0) {
+                    if (autoWrap && (beginWS || endWS)) {
+                        m_minPrefWidth = max(inlineMin, m_minPrefWidth);
+                        inlineMin = 0;
+                    }
+                    continue;
+                }
+                
+                if (stripFrontSpaces)
+                    trailingSpaceChild = child;
+                else
+                    trailingSpaceChild = 0;
+
+                // Add in text-indent.  This is added in only once.
+                int ti = 0;
+                if (!addedTextIndent) {
+                    addedTextIndent = true;
+                    ti = style()->textIndent().calcMinValue(cw);
+                    childMin+=ti; beginMin += ti;
+                    childMax+=ti; beginMax += ti;
+                }
+                
+                // If we have no breakable characters at all,
+                // then this is the easy case. We add ourselves to the current
+                // min and max and continue.
+                if (!hasBreakableChar) {
+                    inlineMin += childMin;
+                } else {
+                    // We have a breakable character.  Now we need to know if
+                    // we start and end with whitespace.
+                    if (beginWS)
+                        // Go ahead and end the current line.
+                        m_minPrefWidth = max(inlineMin, m_minPrefWidth);
+                    else {
+                        inlineMin += beginMin;
+                        m_minPrefWidth = max(inlineMin, m_minPrefWidth);
+                        childMin -= ti;
+                    }
+
+                    inlineMin = childMin;
+
+                    if (endWS) {
+                        // We end in whitespace, which means we can go ahead
+                        // and end our current line.
+                        m_minPrefWidth = max(inlineMin, m_minPrefWidth);
+                        inlineMin = 0;
+                    } else {
+                        m_minPrefWidth = max(inlineMin, m_minPrefWidth);
+                        inlineMin = endMin;
+                    }
+                }
+
+                if (hasBreak) {
+                    inlineMax += beginMax;
+                    m_maxPrefWidth = max(inlineMax, m_maxPrefWidth);
+                    m_maxPrefWidth = max(childMax, m_maxPrefWidth);
+                    inlineMax = endMax;
+                } else
+                    inlineMax += childMax;
+            }
+        } else {
+            m_minPrefWidth = max(inlineMin, m_minPrefWidth);
+            m_maxPrefWidth = max(inlineMax, m_maxPrefWidth);
+            inlineMin = inlineMax = 0;
+            stripFrontSpaces = true;
+            trailingSpaceChild = 0;
+        }
+
+        oldAutoWrap = autoWrap;
+        if (!child->isInlineFlow())
+            previousLeaf = child;
+    }
+
+    if (style()->collapseWhiteSpace())
+        stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
+
+    m_minPrefWidth = max(inlineMin, m_minPrefWidth);
+    m_maxPrefWidth = max(inlineMax, m_maxPrefWidth);
+}
+
+// Use a very large value (in effect infinite).
+#define BLOCK_MAX_WIDTH 15000
+
+void RenderBlock::calcBlockPrefWidths()
+{
+    bool nowrap = style()->whiteSpace() == NOWRAP;
+
+    RenderObject *child = firstChild();
+    int floatLeftWidth = 0, floatRightWidth = 0;
+    while (child) {
+        // Positioned children don't affect the min/max width
+        if (child->isPositioned()) {
+            child = child->nextSibling();
+            continue;
+        }
+
+        if (child->isFloating() || child->avoidsFloats()) {
+            int floatTotalWidth = floatLeftWidth + floatRightWidth;
+            if (child->style()->clear() & CLEFT) {
+                m_maxPrefWidth = max(floatTotalWidth, m_maxPrefWidth);
+                floatLeftWidth = 0;
+            }
+            if (child->style()->clear() & CRIGHT) {
+                m_maxPrefWidth = max(floatTotalWidth, m_maxPrefWidth);
+                floatRightWidth = 0;
+            }
+        }
+
+        // A margin basically has three types: fixed, percentage, and auto (variable).
+        // Auto and percentage margins simply become 0 when computing min/max width.
+        // Fixed margins can be added in as is.
+        Length ml = child->style()->marginLeft();
+        Length mr = child->style()->marginRight();
+        int margin = 0, marginLeft = 0, marginRight = 0;
+        if (ml.isFixed())
+            marginLeft += ml.value();
+        if (mr.isFixed())
+            marginRight += mr.value();
+        margin = marginLeft + marginRight;
+
+        int w = child->minPrefWidth() + margin;
+        m_minPrefWidth = max(w, m_minPrefWidth);
+        
+        // IE ignores tables for calculation of nowrap. Makes some sense.
+        if (nowrap && !child->isTable())
+            m_maxPrefWidth = max(w, m_maxPrefWidth);
+
+        w = child->maxPrefWidth() + margin;
+
+        if (!child->isFloating()) {
+            if (child->avoidsFloats()) {
+                // Determine a left and right max value based off whether or not the floats can fit in the
+                // margins of the object.  For negative margins, we will attempt to overlap the float if the negative margin
+                // is smaller than the float width.
+                int maxLeft = marginLeft > 0 ? max(floatLeftWidth, marginLeft) : floatLeftWidth + marginLeft;
+                int maxRight = marginRight > 0 ? max(floatRightWidth, marginRight) : floatRightWidth + marginRight;
+                w = child->maxPrefWidth() + maxLeft + maxRight;
+                w = max(w, floatLeftWidth + floatRightWidth);
+            }
+            else
+                m_maxPrefWidth = max(floatLeftWidth + floatRightWidth, m_maxPrefWidth);
+            floatLeftWidth = floatRightWidth = 0;
+        }
+        
+        if (child->isFloating()) {
+            if (style()->floating() == FLEFT)
+                floatLeftWidth += w;
+            else
+                floatRightWidth += w;
+        } else
+            m_maxPrefWidth = max(w, m_maxPrefWidth);
+
+        // A very specific WinIE quirk.
+        // Example:
+        /*
+           <div style="position:absolute; width:100px; top:50px;">
+              <div style="position:absolute;left:0px;top:50px;height:50px;background-color:green">
+                <table style="width:100%"><tr><td></table>
+              </div>
+           </div>
+        */
+        // In the above example, the inner absolute positioned block should have a computed width
+        // of 100px because of the table.
+        // We can achieve this effect by making the maxwidth of blocks that contain tables
+        // with percentage widths be infinite (as long as they are not inside a table cell).
+        if (style()->htmlHacks() && child->style()->width().isPercent() &&
+            !isTableCell() && child->isTable() && m_maxPrefWidth < BLOCK_MAX_WIDTH) {
+            RenderBlock* cb = containingBlock();
+            while (!cb->isRenderView() && !cb->isTableCell())
+                cb = cb->containingBlock();
+            if (!cb->isTableCell())
+                m_maxPrefWidth = BLOCK_MAX_WIDTH;
+        }
+        
+        child = child->nextSibling();
+    }
+
+    // Always make sure these values are non-negative.
+    m_minPrefWidth = max(0, m_minPrefWidth);
+    m_maxPrefWidth = max(0, m_maxPrefWidth);
+
+    m_maxPrefWidth = max(floatLeftWidth + floatRightWidth, m_maxPrefWidth);
+}
+
+bool RenderBlock::hasLineIfEmpty() const
+{
+    return element() && (element()->isContentEditable() && element()->rootEditableElement() == element() ||
+                         element()->isShadowNode() && element()->shadowParentNode()->hasTagName(inputTag));
+}
+
+int RenderBlock::lineHeight(bool b, bool isRootLineBox) const
+{
+    // Inline blocks are replaced elements. Otherwise, just pass off to
+    // the base class.  If we're being queried as though we're the root line
+    // box, then the fact that we're an inline-block is irrelevant, and we behave
+    // just like a block.
+    if (isReplaced() && !isRootLineBox)
+        return height() + marginTop() + marginBottom();
+    return RenderFlow::lineHeight(b, isRootLineBox);
+}
+
+int RenderBlock::baselinePosition(bool b, bool isRootLineBox) const
+{
+    // Inline blocks are replaced elements. Otherwise, just pass off to
+    // the base class.  If we're being queried as though we're the root line
+    // box, then the fact that we're an inline-block is irrelevant, and we behave
+    // just like a block.
+    if (isReplaced() && !isRootLineBox) {
+        // For "leaf" theme objects, let the theme decide what the baseline position is.
+        // FIXME: Might be better to have a custom CSS property instead, so that if the theme
+        // is turned off, checkboxes/radios will still have decent baselines.
+        if (style()->hasAppearance() && !theme()->isControlContainer(style()->appearance()))
+            return theme()->baselinePosition(this);
+            
+        // CSS2.1 states that the baseline of an inline block is the baseline of the last line box in
+        // the normal flow.  We make an exception for marquees, since their baselines are meaningless
+        // (the content inside them moves).  This matches WinIE as well, which just bottom-aligns them.
+        // We also give up on finding a baseline if we have a vertical scrollbar, or if we are scrolled
+        // vertically (e.g., an overflow:hidden block that has had scrollTop moved) or if the baseline is outside
+        // of our content box.
+        int baselinePos = (m_layer && (m_layer->marquee() || m_layer->verticalScrollbar() || m_layer->scrollYOffset() != 0)) ? -1 : getBaselineOfLastLineBox();
+        if (baselinePos != -1 && baselinePos <= borderTop() + paddingTop() + contentHeight())
+            return marginTop() + baselinePos;
+        return height() + marginTop() + marginBottom();
+    }
+    return RenderFlow::baselinePosition(b, isRootLineBox);
+}
+
+int RenderBlock::getBaselineOfFirstLineBox() const
+{
+    if (!isBlockFlow())
+        return RenderFlow::getBaselineOfFirstLineBox();
+
+    if (childrenInline()) {
+        if (firstLineBox())
+            return firstLineBox()->yPos() + firstLineBox()->baseline();
+        else
+            return -1;
+    }
+    else {
+        for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+            if (!curr->isFloatingOrPositioned()) {
+                int result = curr->getBaselineOfFirstLineBox();
+                if (result != -1)
+                    return curr->yPos() + result; // Translate to our coordinate space.
+            }
+        }
+    }
+
+    return -1;
+}
+
+int RenderBlock::getBaselineOfLastLineBox() const
+{
+    if (!isBlockFlow())
+        return RenderFlow::getBaselineOfLastLineBox();
+
+    if (childrenInline()) {
+        if (!firstLineBox() && hasLineIfEmpty())
+            return RenderFlow::baselinePosition(true, true) + borderTop() + paddingTop();
+        if (lastLineBox())
+            return lastLineBox()->yPos() + lastLineBox()->baseline();
+        return -1;
+    }
+    else {
+        bool haveNormalFlowChild = false;
+        for (RenderObject* curr = lastChild(); curr; curr = curr->previousSibling()) {
+            if (!curr->isFloatingOrPositioned()) {
+                haveNormalFlowChild = true;
+                int result = curr->getBaselineOfLastLineBox();
+                if (result != -1)
+                    return curr->yPos() + result; // Translate to our coordinate space.
+            }
+        }
+        if (!haveNormalFlowChild && hasLineIfEmpty())
+            return RenderFlow::baselinePosition(true, true) + borderTop() + paddingTop();
+    }
+
+    return -1;
+}
+
+RenderBlock* RenderBlock::firstLineBlock() const
+{
+    const RenderObject* firstLineBlock = this;
+    bool hasPseudo = false;
+    while (true) {
+        hasPseudo = firstLineBlock->style()->hasPseudoStyle(RenderStyle::FIRST_LINE);
+        if (hasPseudo)
+            break;
+        RenderObject* parentBlock = firstLineBlock->parent();
+        if (firstLineBlock->isReplaced() || firstLineBlock->isFloating() || 
+            !parentBlock || parentBlock->firstChild() != firstLineBlock || !parentBlock->isBlockFlow())
+            break;
+        firstLineBlock = parentBlock;
+    } 
+    
+    if (!hasPseudo)
+        return 0;
+    
+    return (RenderBlock*)(firstLineBlock);
+}
+
+void RenderBlock::updateFirstLetter()
+{
+    if (!document()->usesFirstLetterRules())
+        return;
+    // Don't recurse
+    if (style()->styleType() == RenderStyle::FIRST_LETTER)
+        return;
+
+    // FIXME: We need to destroy the first-letter object if it is no longer the first child.  Need to find
+    // an efficient way to check for that situation though before implementing anything.
+    RenderObject* firstLetterBlock = this;
+    bool hasPseudoStyle = false;
+    while (true) {
+        // We only honor first-letter if the firstLetterBlock can have children in the DOM. This correctly 
+        // prevents form controls from honoring first-letter.
+        hasPseudoStyle = firstLetterBlock->style()->hasPseudoStyle(RenderStyle::FIRST_LETTER) 
+            && firstLetterBlock->canHaveChildren();
+        if (hasPseudoStyle)
+            break;
+        RenderObject* parentBlock = firstLetterBlock->parent();
+        if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock || 
+            !parentBlock->isBlockFlow())
+            break;
+        firstLetterBlock = parentBlock;
+    } 
+
+    if (!hasPseudoStyle) 
+        return;
+
+    // Drill into inlines looking for our first text child.
+    RenderObject* currChild = firstLetterBlock->firstChild();
+    while (currChild && currChild->needsLayout() && (!currChild->isReplaced() || currChild->isFloatingOrPositioned()) && !currChild->isText()) {
+        if (currChild->isFloatingOrPositioned()) {
+            if (currChild->style()->styleType() == RenderStyle::FIRST_LETTER)
+                break;
+            currChild = currChild->nextSibling();
+        } else
+            currChild = currChild->firstChild();
+    }
+
+    // Get list markers out of the way.
+    while (currChild && currChild->isListMarker())
+        currChild = currChild->nextSibling();
+
+    if (!currChild)
+        return;
+
+    RenderObject* firstLetterContainer = currChild->parent();
+
+    // If the child already has style, then it has already been created, so we just want
+    // to update it.
+    if (currChild->style()->styleType() == RenderStyle::FIRST_LETTER) {
+        RenderStyle* pseudo = firstLetterBlock->getCachedPseudoStyle(RenderStyle::FIRST_LETTER,
+                                                                     firstLetterContainer->firstLineStyle());
+        currChild->setStyle(pseudo);
+        for (RenderObject* genChild = currChild->firstChild(); genChild; genChild = genChild->nextSibling()) {
+            if (genChild->isText()) 
+                genChild->setStyle(pseudo);
+        }
+        return;
+    }
+
+    // If the child does not already have style, we create it here.
+    if (currChild->isText() && !currChild->isBR() && currChild->parent()->style()->styleType() != RenderStyle::FIRST_LETTER) {
+        // Our layout state is not valid for the repaints we are going to trigger by
+        // adding and removing children of firstLetterContainer.
+        view()->disableLayoutState();
+
+        RenderText* textObj = static_cast<RenderText*>(currChild);
+        
+        // Create our pseudo style now that we have our firstLetterContainer determined.
+        RenderStyle* pseudoStyle = firstLetterBlock->getCachedPseudoStyle(RenderStyle::FIRST_LETTER,
+                                                                          firstLetterContainer->firstLineStyle());
+        
+        // Force inline display (except for floating first-letters)
+        pseudoStyle->setDisplay( pseudoStyle->isFloating() ? BLOCK : INLINE);
+        pseudoStyle->setPosition( StaticPosition ); // CSS2 says first-letter can't be positioned.
+        
+        RenderObject* firstLetter = RenderFlow::createAnonymousFlow(document(), pseudoStyle); // anonymous box
+        firstLetterContainer->addChild(firstLetter, currChild);
+        
+        // The original string is going to be either a generated content string or a DOM node's
+        // string.  We want the original string before it got transformed in case first-letter has
+        // no text-transform or a different text-transform applied to it.
+        RefPtr<StringImpl> oldText = textObj->originalText();
+        ASSERT(oldText);
+        
+        if (oldText && oldText->length() > 0) {
+            unsigned int length = 0;
+            
+            // account for leading spaces and punctuation
+            while (length < oldText->length() && (isSpaceOrNewline((*oldText)[length]) || Unicode::isPunct((*oldText)[length])))
+                length++;
+            
+            // account for first letter
+            length++;
+            
+            // construct text fragment for the text after the first letter
+            // NOTE: this might empty
+            RenderTextFragment* remainingText = 
+                new (renderArena()) RenderTextFragment(textObj->node(), oldText.get(), length, oldText->length() - length);
+            remainingText->setStyle(textObj->style());
+            if (remainingText->element())
+                remainingText->element()->setRenderer(remainingText);
+            
+            RenderObject* nextObj = textObj->nextSibling();
+            firstLetterContainer->removeChild(textObj);
+            firstLetterContainer->addChild(remainingText, nextObj);
+            remainingText->setFirstLetter(firstLetter);
+            
+            // construct text fragment for the first letter
+            RenderTextFragment* letter = 
+                new (renderArena()) RenderTextFragment(remainingText->node(), oldText.get(), 0, length);
+            RefPtr<RenderStyle> newStyle = RenderStyle::create();
+            newStyle->inheritFrom(pseudoStyle);
+            letter->setStyle(newStyle.release());
+            firstLetter->addChild(letter);
+
+            textObj->destroy();
+        }
+        view()->enableLayoutState();
+    }
+}
+
+bool RenderBlock::inRootBlockContext() const
+{
+    if (isTableCell() || isFloatingOrPositioned() || hasOverflowClip())
+        return false;
+    
+    if (isRoot() || isRenderView())
+        return true;
+    
+    return containingBlock()->inRootBlockContext();
+}
+
+// Helper methods for obtaining the last line, computing line counts and heights for line counts
+// (crawling into blocks).
+static bool shouldCheckLines(RenderObject* obj)
+{
+    return !obj->isFloatingOrPositioned() && !obj->isCompact() && !obj->isRunIn() &&
+            obj->isBlockFlow() && obj->style()->height().isAuto() &&
+            (!obj->isFlexibleBox() || obj->style()->boxOrient() == VERTICAL);
+}
+
+static RootInlineBox* getLineAtIndex(RenderBlock* block, int i, int& count)
+{
+    if (block->style()->visibility() == VISIBLE) {
+        if (block->childrenInline()) {
+            for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
+                if (count++ == i)
+                    return box;
+            }
+        }
+        else {
+            for (RenderObject* obj = block->firstChild(); obj; obj = obj->nextSibling()) {
+                if (shouldCheckLines(obj)) {
+                    RootInlineBox *box = getLineAtIndex(static_cast<RenderBlock*>(obj), i, count);
+                    if (box)
+                        return box;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom, int& count)
+{
+    if (block->style()->visibility() == VISIBLE) {
+        if (block->childrenInline()) {
+            for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
+                if (++count == l)
+                    return box->bottomOverflow() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
+            }
+        }
+        else {
+            RenderObject* normalFlowChildWithoutLines = 0;
+            for (RenderObject* obj = block->firstChild(); obj; obj = obj->nextSibling()) {
+                if (shouldCheckLines(obj)) {
+                    int result = getHeightForLineCount(static_cast<RenderBlock*>(obj), l, false, count);
+                    if (result != -1)
+                        return result + obj->yPos() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
+                }
+                else if (!obj->isFloatingOrPositioned() && !obj->isCompact() && !obj->isRunIn())
+                    normalFlowChildWithoutLines = obj;
+            }
+            if (normalFlowChildWithoutLines && l == 0)
+                return normalFlowChildWithoutLines->yPos() + normalFlowChildWithoutLines->height();
+        }
+    }
+    
+    return -1;
+}
+
+RootInlineBox* RenderBlock::lineAtIndex(int i)
+{
+    int count = 0;
+    return getLineAtIndex(this, i, count);
+}
+
+int RenderBlock::lineCount()
+{
+    int count = 0;
+    if (style()->visibility() == VISIBLE) {
+        if (childrenInline())
+            for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
+                count++;
+        else
+            for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
+                if (shouldCheckLines(obj))
+                    count += static_cast<RenderBlock*>(obj)->lineCount();
+    }
+    return count;
+}
+
+int RenderBlock::heightForLineCount(int l)
+{
+    int count = 0;
+    return getHeightForLineCount(this, l, true, count);
+}
+
+void RenderBlock::adjustForBorderFit(int x, int& left, int& right) const
+{
+    // We don't deal with relative positioning.  Our assumption is that you shrink to fit the lines without accounting
+    // for either overflow or translations via relative positioning.
+    if (style()->visibility() == VISIBLE) {
+        if (childrenInline()) {
+            for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox()) {
+                if (box->firstChild())
+                    left = min(left, x + box->firstChild()->xPos());
+                if (box->lastChild())
+                    right = max(right, x + box->lastChild()->xPos() + box->lastChild()->width());
+            }
+        }
+        else {
+            for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling()) {
+                if (!obj->isFloatingOrPositioned()) {
+                    if (obj->isBlockFlow() && !obj->hasOverflowClip())
+                        static_cast<RenderBlock*>(obj)->adjustForBorderFit(x + obj->xPos(), left, right);
+                    else if (obj->style()->visibility() == VISIBLE) {
+                        // We are a replaced element or some kind of non-block-flow object.
+                        left = min(left, x + obj->xPos());
+                        right = max(right, x + obj->xPos() + obj->width());
+                    }
+                }
+            }
+        }
+        
+        if (m_floatingObjects) {
+            FloatingObject* r;
+            DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+            for (; (r = it.current()); ++it) {
+                // Only examine the object if our m_shouldPaint flag is set.
+                if (r->m_shouldPaint) {
+                    int floatLeft = r->m_left - r->m_renderer->xPos() + r->m_renderer->marginLeft();
+                    int floatRight = floatLeft + r->m_renderer->width();
+                    left = min(left, floatLeft);
+                    right = max(right, floatRight);
+                }
+            }
+        }
+    }
+}
+
+void RenderBlock::borderFitAdjust(int& x, int& w) const
+{
+    if (style()->borderFit() == BorderFitBorder)
+        return;
+
+    // Walk any normal flow lines to snugly fit.
+    int left = INT_MAX;
+    int right = INT_MIN;
+    int oldWidth = w;
+    adjustForBorderFit(0, left, right);
+    if (left != INT_MAX) {
+        left -= (borderLeft() + paddingLeft());
+        if (left > 0) {
+            x += left;
+            w -= left;
+        }
+    }
+    if (right != INT_MIN) {
+        right += (borderRight() + paddingRight());
+        if (right < oldWidth)
+            w -= (oldWidth - right);
+    }
+}
+
+void RenderBlock::clearTruncation()
+{
+    if (style()->visibility() == VISIBLE) {
+        if (childrenInline() && hasMarkupTruncation()) {
+            setHasMarkupTruncation(false);
+            for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
+                box->clearTruncation();
+        }
+        else
+            for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
+                if (shouldCheckLines(obj))
+                    static_cast<RenderBlock*>(obj)->clearTruncation();
+    }
+}
+
+void RenderBlock::setMaxTopMargins(int pos, int neg)
+{
+    if (!m_maxMargin) {
+        if (pos == MaxMargin::topPosDefault(this) && neg == MaxMargin::topNegDefault(this))
+            return;
+        m_maxMargin = new MaxMargin(this);
+    }
+    m_maxMargin->m_topPos = pos;
+    m_maxMargin->m_topNeg = neg;
+}
+
+void RenderBlock::setMaxBottomMargins(int pos, int neg)
+{
+    if (!m_maxMargin) {
+        if (pos == MaxMargin::bottomPosDefault(this) && neg == MaxMargin::bottomNegDefault(this))
+            return;
+        m_maxMargin = new MaxMargin(this);
+    }
+    m_maxMargin->m_bottomPos = pos;
+    m_maxMargin->m_bottomNeg = neg;
+}
+
+const char* RenderBlock::renderName() const
+{
+    if (isBody())
+        return "RenderBody"; // FIXME: Temporary hack until we know that the regression tests pass.
+    
+    if (isFloating())
+        return "RenderBlock (floating)";
+    if (isPositioned())
+        return "RenderBlock (positioned)";
+    if (isAnonymousBlock())
+        return "RenderBlock (anonymous)";
+    else if (isAnonymous())
+        return "RenderBlock (generated)";
+    if (isRelPositioned())
+        return "RenderBlock (relative positioned)";
+    if (isCompact())
+        return "RenderBlock (compact)";
+    if (isRunIn())
+        return "RenderBlock (run-in)";
+    return "RenderBlock";
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h
new file mode 100644
index 0000000..d38de16
--- /dev/null
+++ b/WebCore/rendering/RenderBlock.h
@@ -0,0 +1,506 @@
+/*
+ * This file is part of the render object implementation for KHTML.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ *           (C) 2007 David Smith ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RenderBlock_h
+#define RenderBlock_h
+
+#include "DeprecatedPtrList.h"
+#include "GapRects.h"
+#include "RenderFlow.h"
+#include "RootInlineBox.h"
+#include <wtf/ListHashSet.h>
+
+namespace WebCore {
+
+class InlineIterator;
+class BidiRun;
+class Position;
+class RootInlineBox;
+
+template <class Iterator, class Run> class BidiResolver;
+typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver;
+
+enum CaretType { CursorCaret, DragCaret };
+
+class RenderBlock : public RenderFlow {
+public:
+    RenderBlock(Node*);
+    virtual ~RenderBlock();
+
+    virtual const char* renderName() const;
+
+    // These two functions are overridden for inline-block.
+    virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
+    virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
+
+    virtual bool isRenderBlock() const { return true; }
+    virtual bool isBlockFlow() const { return (!isInline() || isReplaced()) && !isTable(); }
+    virtual bool isInlineFlow() const { return isInline() && !isReplaced(); }
+    virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); }
+
+    virtual bool childrenInline() const { return m_childrenInline; }
+    virtual void setChildrenInline(bool b) { m_childrenInline = b; }
+    void makeChildrenNonInline(RenderObject* insertionPoint = 0);
+    void deleteLineBoxTree();
+
+    // The height (and width) of a block when you include overflow spillage out of the bottom
+    // of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside
+    // it would have an overflow height of borderTop() + paddingTop() + 100px.
+    virtual int overflowHeight(bool includeInterior = true) const;
+    virtual int overflowWidth(bool includeInterior = true) const;
+    virtual int overflowLeft(bool includeInterior = true) const;
+    virtual int overflowTop(bool includeInterior = true) const;
+    virtual IntRect overflowRect(bool includeInterior = true) const;
+    virtual void setOverflowHeight(int h) { m_overflowHeight = h; }
+    virtual void setOverflowWidth(int w) { m_overflowWidth = w; }
+
+    void addVisualOverflow(const IntRect&);
+
+    virtual bool isSelfCollapsingBlock() const;
+    virtual bool isTopMarginQuirk() const { return m_topMarginQuirk; }
+    virtual bool isBottomMarginQuirk() const { return m_bottomMarginQuirk; }
+
+    virtual int maxTopMargin(bool positive) const { return positive ? maxTopPosMargin() : maxTopNegMargin(); }
+    virtual int maxBottomMargin(bool positive) const { return positive ? maxBottomPosMargin() : maxBottomNegMargin(); }
+
+    int maxTopPosMargin() const { return m_maxMargin ? m_maxMargin->m_topPos : MaxMargin::topPosDefault(this); }
+    int maxTopNegMargin() const { return m_maxMargin ? m_maxMargin->m_topNeg : MaxMargin::topNegDefault(this); }
+    int maxBottomPosMargin() const { return m_maxMargin ? m_maxMargin->m_bottomPos : MaxMargin::bottomPosDefault(this); }
+    int maxBottomNegMargin() const { return m_maxMargin ? m_maxMargin->m_bottomNeg : MaxMargin::bottomNegDefault(this); }
+    void setMaxTopMargins(int pos, int neg);
+    void setMaxBottomMargins(int pos, int neg);
+    
+    void initMaxMarginValues()
+    {
+        if (m_maxMargin) {
+            m_maxMargin->m_topPos = MaxMargin::topPosDefault(this);
+            m_maxMargin->m_topNeg = MaxMargin::topNegDefault(this);
+            m_maxMargin->m_bottomPos = MaxMargin::bottomPosDefault(this);
+            m_maxMargin->m_bottomNeg = MaxMargin::bottomNegDefault(this);
+        }
+    }
+
+    virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild);
+    virtual void removeChild(RenderObject*);
+
+    virtual void repaintOverhangingFloats(bool paintAllDescendants);
+
+    virtual void layout();
+    virtual void layoutBlock(bool relayoutChildren);
+    void layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom);
+    void layoutInlineChildren(bool relayoutChildren, int& repaintTop, int& repaintBottom);
+
+    void layoutPositionedObjects(bool relayoutChildren);
+    void insertPositionedObject(RenderObject*);
+    void removePositionedObject(RenderObject*);
+    virtual void removePositionedObjects(RenderBlock*);
+
+    void addPercentHeightDescendant(RenderBox*);
+    static void removePercentHeightDescendant(RenderBox*);
+
+    virtual void positionListMarker() { }
+
+    virtual void borderFitAdjust(int& x, int& w) const; // Shrink the box in which the border paints if border-fit is set.
+
+    // Called to lay out the legend for a fieldset.
+    virtual RenderObject* layoutLegend(bool relayoutChildren) { return 0; };
+
+    // the implementation of the following functions is in bidi.cpp
+    struct FloatWithRect {
+        FloatWithRect(RenderObject* f)
+            : object(f)
+            , rect(IntRect(f->xPos() - f->marginLeft(), f->yPos() - f->marginTop(), f->width() + f->marginLeft() + f->marginRight(), f->height() + f->marginTop() + f->marginBottom()))
+        {
+        }
+
+        RenderObject* object;
+        IntRect rect;
+    };
+
+    void bidiReorderLine(InlineBidiResolver&, const InlineIterator& end);
+    RootInlineBox* determineStartPosition(bool& fullLayout, InlineBidiResolver&, Vector<FloatWithRect>& floats, unsigned& numCleanFloats);
+    RootInlineBox* determineEndPosition(RootInlineBox* startBox, InlineIterator& cleanLineStart,
+                                        BidiStatus& cleanLineBidiStatus,
+                                        int& yPos);
+    bool matchedEndLine(const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus,
+                        RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop);
+    bool generatesLineBoxesForInlineChild(RenderObject*);
+    void skipTrailingWhitespace(InlineIterator&);
+    int skipLeadingWhitespace(InlineBidiResolver&);
+    void fitBelowFloats(int widthToFit, int& availableWidth);
+    InlineIterator findNextLineBreak(InlineBidiResolver&, EClear* clear = 0);
+    RootInlineBox* constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool lastLine, RenderObject* endObject);
+    InlineFlowBox* createLineBoxes(RenderObject*);
+    void computeHorizontalPositionsForLine(RootInlineBox*, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd);
+    void computeVerticalPositionsForLine(RootInlineBox*, BidiRun*);
+    void checkLinesForOverflow();
+    void deleteEllipsisLineBoxes();
+    void checkLinesForTextOverflow();
+    // end bidi.cpp functions
+
+    virtual void paint(PaintInfo&, int tx, int ty);
+    virtual void paintObject(PaintInfo&, int tx, int ty);
+    void paintFloats(PaintInfo&, int tx, int ty, bool preservePhase = false);
+    void paintContents(PaintInfo&, int tx, int ty);
+    void paintColumns(PaintInfo&, int tx, int ty, bool paintFloats = false);
+    void paintChildren(PaintInfo&, int tx, int ty);
+    void paintEllipsisBoxes(PaintInfo&, int tx, int ty);
+    void paintSelection(PaintInfo&, int tx, int ty);
+    void paintCaret(PaintInfo&, CaretType);
+
+    void insertFloatingObject(RenderObject*);
+    void removeFloatingObject(RenderObject*);
+
+    // Called from lineWidth, to position the floats added in the last line.
+    // Returns ture if and only if it has positioned any floats.
+    bool positionNewFloats();
+    void clearFloats();
+    int getClearDelta(RenderObject* child);
+    virtual void markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove = 0);
+    void markPositionedObjectsForLayout();
+
+    virtual bool containsFloats() { return m_floatingObjects && !m_floatingObjects->isEmpty(); }
+    virtual bool containsFloat(RenderObject*);
+
+    virtual bool avoidsFloats() const;
+
+    virtual bool hasOverhangingFloats() { return !hasColumns() && floatBottom() > m_height; }
+    void addIntrudingFloats(RenderBlock* prev, int xoffset, int yoffset);
+    int addOverhangingFloats(RenderBlock* child, int xoffset, int yoffset, bool makeChildPaintOtherFloats);
+
+    int nextFloatBottomBelow(int) const;
+    int floatBottom() const;
+    inline int leftBottom();
+    inline int rightBottom();
+    IntRect floatRect() const;
+
+    virtual int lineWidth(int) const;
+    virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+    virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+    virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+
+    int rightOffset() const;
+    int rightRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int* heightRemaining = 0) const;
+    int rightOffset(int y) const { return rightRelOffset(y, rightOffset(), true); }
+
+    int leftOffset() const;
+    int leftRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int* heightRemaining = 0) const;
+    int leftOffset(int y) const { return leftRelOffset(y, leftOffset(), true); }
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+    virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+    virtual bool hitTestContents(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+    virtual bool isPointInOverflowControl(HitTestResult&, int x, int y, int tx, int ty);
+
+    virtual VisiblePosition positionForCoordinates(int x, int y);
+    
+    // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.)
+    virtual int availableWidth() const;
+    
+    virtual void calcPrefWidths();
+    void calcInlinePrefWidths();
+    void calcBlockPrefWidths();
+
+    virtual int getBaselineOfFirstLineBox() const;
+    virtual int getBaselineOfLastLineBox() const;
+
+    RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); }
+    RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); }
+
+    // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
+    // children.
+    virtual RenderBlock* firstLineBlock() const;
+    virtual void updateFirstLetter();
+
+    bool inRootBlockContext() const;
+
+    void setHasMarkupTruncation(bool b = true) { m_hasMarkupTruncation = b; }
+    bool hasMarkupTruncation() const { return m_hasMarkupTruncation; }
+
+    virtual bool hasSelectedChildren() const { return m_selectionState != SelectionNone; }
+    virtual SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState); }
+    virtual void setSelectionState(SelectionState s);
+
+    struct BlockSelectionInfo {
+        RenderBlock* m_block;
+        GapRects m_rects;
+        SelectionState m_state;
+
+        BlockSelectionInfo()
+            : m_block(0)
+            , m_state(SelectionNone)
+        {
+        }
+
+        BlockSelectionInfo(RenderBlock* b)
+            : m_block(b)
+            , m_rects(b->needsLayout() ? GapRects() : b->selectionGapRects())
+            , m_state(b->selectionState())
+        { 
+        }
+
+        RenderBlock* block() const { return m_block; }
+        GapRects rects() const { return m_rects; }
+        SelectionState state() const { return m_state; }
+    };
+
+    virtual IntRect selectionRect(bool) { return selectionGapRects(); }
+    GapRects selectionGapRects();
+    virtual bool shouldPaintSelectionGaps() const;
+    bool isSelectionRoot() const;
+    GapRects fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
+                               int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* = 0);
+    GapRects fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
+                                     int& lastTop, int& lastLeft, int& lastRight, const PaintInfo*);
+    GapRects fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
+                                    int& lastTop, int& lastLeft, int& lastRight, const PaintInfo*);
+    IntRect fillVerticalSelectionGap(int lastTop, int lastLeft, int lastRight, int bottomY, RenderBlock* rootBlock,
+                                     int blockX, int blockY, const PaintInfo*);
+    IntRect fillLeftSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock, 
+                                 int blockX, int blockY, int tx, int ty, const PaintInfo*);
+    IntRect fillRightSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
+                                  int blockX, int blockY, int tx, int ty, const PaintInfo*);
+    IntRect fillHorizontalSelectionGap(RenderObject* selObj, int xPos, int yPos, int width, int height, const PaintInfo*);
+
+    void getHorizontalSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
+    int leftSelectionOffset(RenderBlock* rootBlock, int y);
+    int rightSelectionOffset(RenderBlock* rootBlock, int y);
+
+    // Helper methods for computing line counts and heights for line counts.
+    RootInlineBox* lineAtIndex(int);
+    int lineCount();
+    int heightForLineCount(int);
+    void clearTruncation();
+
+    int desiredColumnWidth() const;
+    unsigned desiredColumnCount() const;
+    Vector<IntRect>* columnRects() const;
+    void setDesiredColumnCountAndWidth(int count, int width);
+    
+    void adjustRectForColumns(IntRect&) const;
+
+    void addContinuationWithOutline(RenderFlow*);
+    void paintContinuationOutlines(PaintInfo&, int tx, int ty);
+
+private:
+    void adjustPointToColumnContents(IntPoint&) const;
+    void adjustForBorderFit(int x, int& left, int& right) const; // Helper function for borderFitAdjust
+
+    void markLinesDirtyInVerticalRange(int top, int bottom);
+
+protected:
+    virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+    void newLine(EClear);
+    virtual bool hasLineIfEmpty() const;
+    bool layoutOnlyPositionedObjects();
+
+private:
+    Position positionForBox(InlineBox*, bool start = true) const;
+    Position positionForRenderer(RenderObject*, bool start = true) const;
+// columGap() is used by WebKit when hit-testing columns. It's called by
+// CacheBuilder when it duplicates the hit-testing logic.
+#ifdef ANDROID_EXPOSE_COLUMN_GAP
+public:
+#endif
+    int columnGap() const;
+#ifdef ANDROID_EXPOSE_COLUMN_GAP
+private:
+#endif
+    void calcColumnWidth();
+    int layoutColumns(int endOfContent = -1);
+
+protected:
+    struct FloatingObject {
+        enum Type {
+            FloatLeft,
+            FloatRight
+        };
+
+        FloatingObject(Type type)
+            : m_renderer(0)
+            , m_top(0)
+            , m_bottom(0)
+            , m_left(0)
+            , m_width(0)
+            , m_type(type)
+            , m_shouldPaint(true)
+            , m_isDescendant(false)
+        {
+        }
+
+        Type type() { return static_cast<Type>(m_type); }
+
+        RenderObject* m_renderer;
+        int m_top;
+        int m_bottom;
+        int m_left;
+        int m_width;
+        unsigned m_type : 1; // Type (left or right aligned)
+        bool m_shouldPaint : 1;
+        bool m_isDescendant : 1;
+    };
+
+    // The following helper functions and structs are used by layoutBlockChildren.
+    class CompactInfo {
+        // A compact child that needs to be collapsed into the margin of the following block.
+        RenderObject* m_compact;
+
+        // The block with the open margin that the compact child is going to place itself within.
+        RenderObject* m_block;
+
+    public:
+        RenderObject* compact() const { return m_compact; }
+        RenderObject* block() const { return m_block; }
+        bool matches(RenderObject* child) const { return m_compact && m_block == child; }
+
+        void clear() { set(0, 0); }
+        void set(RenderObject* c, RenderObject* b) { m_compact = c; m_block = b; }
+
+        CompactInfo() { clear(); }
+    };
+
+    class MarginInfo {
+        // Collapsing flags for whether we can collapse our margins with our children's margins.
+        bool m_canCollapseWithChildren : 1;
+        bool m_canCollapseTopWithChildren : 1;
+        bool m_canCollapseBottomWithChildren : 1;
+
+        // Whether or not we are a quirky container, i.e., do we collapse away top and bottom
+        // margins in our container.  Table cells and the body are the common examples. We
+        // also have a custom style property for Safari RSS to deal with TypePad blog articles.
+        bool m_quirkContainer : 1;
+
+        // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block.  
+        // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will
+        // always be collapsing with one another.  This variable can remain set to true through multiple iterations 
+        // as long as we keep encountering self-collapsing blocks.
+        bool m_atTopOfBlock : 1;
+
+        // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block.
+        bool m_atBottomOfBlock : 1;
+
+        // If our last normal flow child was a self-collapsing block that cleared a float,
+        // we track it in this variable.
+        bool m_selfCollapsingBlockClearedFloat : 1;
+
+        // These variables are used to detect quirky margins that we need to collapse away (in table cells
+        // and in the body element).
+        bool m_topQuirk : 1;
+        bool m_bottomQuirk : 1;
+        bool m_determinedTopQuirk : 1;
+
+        // These flags track the previous maximal positive and negative margins.
+        int m_posMargin;
+        int m_negMargin;
+
+    public:
+        MarginInfo(RenderBlock* b, int top, int bottom);
+
+        void setAtTopOfBlock(bool b) { m_atTopOfBlock = b; }
+        void setAtBottomOfBlock(bool b) { m_atBottomOfBlock = b; }
+        void clearMargin() { m_posMargin = m_negMargin = 0; }
+        void setSelfCollapsingBlockClearedFloat(bool b) { m_selfCollapsingBlockClearedFloat = b; }
+        void setTopQuirk(bool b) { m_topQuirk = b; }
+        void setBottomQuirk(bool b) { m_bottomQuirk = b; }
+        void setDeterminedTopQuirk(bool b) { m_determinedTopQuirk = b; }
+        void setPosMargin(int p) { m_posMargin = p; }
+        void setNegMargin(int n) { m_negMargin = n; }
+        void setPosMarginIfLarger(int p) { if (p > m_posMargin) m_posMargin = p; }
+        void setNegMarginIfLarger(int n) { if (n > m_negMargin) m_negMargin = n; }
+
+        void setMargin(int p, int n) { m_posMargin = p; m_negMargin = n; }
+
+        bool atTopOfBlock() const { return m_atTopOfBlock; }
+        bool canCollapseWithTop() const { return m_atTopOfBlock && m_canCollapseTopWithChildren; }
+        bool canCollapseWithBottom() const { return m_atBottomOfBlock && m_canCollapseBottomWithChildren; }
+        bool canCollapseTopWithChildren() const { return m_canCollapseTopWithChildren; }
+        bool canCollapseBottomWithChildren() const { return m_canCollapseBottomWithChildren; }
+        bool selfCollapsingBlockClearedFloat() const { return m_selfCollapsingBlockClearedFloat; }
+        bool quirkContainer() const { return m_quirkContainer; }
+        bool determinedTopQuirk() const { return m_determinedTopQuirk; }
+        bool topQuirk() const { return m_topQuirk; }
+        bool bottomQuirk() const { return m_bottomQuirk; }
+        int posMargin() const { return m_posMargin; }
+        int negMargin() const { return m_negMargin; }
+        int margin() const { return m_posMargin - m_negMargin; }
+    };
+
+    void adjustPositionedBlock(RenderObject* child, const MarginInfo&);
+    void adjustFloatingBlock(const MarginInfo&);
+    RenderObject* handleSpecialChild(RenderObject* child, const MarginInfo&, CompactInfo&, bool& handled);
+    RenderObject* handleFloatingChild(RenderObject* child, const MarginInfo&, bool& handled);
+    RenderObject* handlePositionedChild(RenderObject* child, const MarginInfo&, bool& handled);
+    RenderObject* handleCompactChild(RenderObject* child, CompactInfo&, bool& handled);
+    RenderObject* handleRunInChild(RenderObject* child, bool& handled);
+    void collapseMargins(RenderObject* child, MarginInfo&, int yPosEstimate);
+    void clearFloatsIfNeeded(RenderObject* child, MarginInfo&, int oldTopPosMargin, int oldTopNegMargin);
+    void insertCompactIfNeeded(RenderObject* child, CompactInfo&);
+    int estimateVerticalPosition(RenderObject* child, const MarginInfo&);
+    void determineHorizontalPosition(RenderObject* child);
+    void handleBottomOfBlock(int top, int bottom, MarginInfo&);
+    void setCollapsedBottomMargin(const MarginInfo&);
+    // End helper functions and structs used by layoutBlockChildren.
+
+private:
+    typedef ListHashSet<RenderObject*>::const_iterator Iterator;
+    DeprecatedPtrList<FloatingObject>* m_floatingObjects;
+    ListHashSet<RenderObject*>* m_positionedObjects;
+         
+    // Allocated only when some of these fields have non-default values
+    struct MaxMargin {
+        MaxMargin(const RenderBlock* o) 
+            : m_topPos(topPosDefault(o))
+            , m_topNeg(topNegDefault(o))
+            , m_bottomPos(bottomPosDefault(o))
+            , m_bottomNeg(bottomNegDefault(o))
+        { 
+        }
+
+        static int topPosDefault(const RenderBlock* o) { return o->marginTop() > 0 ? o->marginTop() : 0; }
+        static int topNegDefault(const RenderBlock* o) { return o->marginTop() < 0 ? -o->marginTop() : 0; }
+        static int bottomPosDefault(const RenderBlock* o) { return o->marginBottom() > 0 ? o->marginBottom() : 0; }
+        static int bottomNegDefault(const RenderBlock* o) { return o->marginBottom() < 0 ? -o->marginBottom() : 0; }
+
+        int m_topPos;
+        int m_topNeg;
+        int m_bottomPos;
+        int m_bottomNeg;
+     };
+
+    MaxMargin* m_maxMargin;
+
+protected:
+    // How much content overflows out of our block vertically or horizontally.
+    int m_overflowHeight;
+    int m_overflowWidth;
+    int m_overflowLeft;
+    int m_overflowTop;
+};
+
+} // namespace WebCore
+
+#endif // RenderBlock_h
diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp
new file mode 100644
index 0000000..40b0e93
--- /dev/null
+++ b/WebCore/rendering/RenderBox.cpp
@@ -0,0 +1,2769 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ *           (C) 2005 Allan Sandfeld Jensen ([email protected])
+ *           (C) 2005, 2006 Samuel Weinig ([email protected])
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderBox.h"
+
+#include "CachedImage.h"
+#include "ChromeClient.h"
+#include "Document.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLElement.h"
+#include "HTMLNames.h"
+#include "ImageBuffer.h"
+#include "Frame.h"
+#include "Page.h"
+#include "RenderArena.h"
+#include "RenderFlexibleBox.h"
+#include "RenderLayer.h"
+#include "RenderReplica.h"
+#include "RenderTableCell.h"
+#include "RenderTheme.h"
+#ifdef ANDROID_LAYOUT
+#include "Settings.h"
+#endif
+#include "RenderView.h"
+#include <algorithm>
+#include <math.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+// Used by flexible boxes when flexing this element.
+typedef WTF::HashMap<const RenderBox*, int> OverrideSizeMap;
+static OverrideSizeMap* gOverrideSizeMap = 0;
+
+bool RenderBox::s_wasFloating = false;
+bool RenderBox::s_hadOverflowClip = false;
+
+RenderBox::RenderBox(Node* node)
+    : RenderObject(node)
+    , m_width(0)
+    , m_height(0)
+#ifdef ANDROID_LAYOUT
+    , m_visibleWidth(0)
+#endif
+    , m_x(0)
+    , m_y(0)
+    , m_marginLeft(0)
+    , m_marginRight(0)
+    , m_marginTop(0)
+    , m_marginBottom(0)
+    , m_minPrefWidth(-1)
+    , m_maxPrefWidth(-1)
+    , m_layer(0)
+    , m_inlineBoxWrapper(0)
+{
+}
+
+RenderBox::~RenderBox()
+{
+}
+
+void RenderBox::destroy()
+{
+    // A lot of the code in this function is just pasted into
+    // RenderWidget::destroy. If anything in this function changes,
+    // be sure to fix RenderWidget::destroy() as well.
+    if (hasOverrideSize())
+        gOverrideSizeMap->remove(this);
+
+    // This must be done before we destroy the RenderObject.
+    if (m_layer)
+        m_layer->clearClipRect();
+
+    if (style() && (style()->height().isPercent() || style()->minHeight().isPercent() || style()->maxHeight().isPercent()))
+        RenderBlock::removePercentHeightDescendant(this);
+
+    RenderObject::destroy();
+}
+
+void RenderBox::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+{
+    s_wasFloating = isFloating();
+    s_hadOverflowClip = hasOverflowClip();
+
+    RenderObject::styleWillChange(diff, newStyle);
+}
+
+void RenderBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderObject::styleDidChange(diff, oldStyle);
+
+    if (needsLayout() && oldStyle && (oldStyle->height().isPercent() || oldStyle->minHeight().isPercent() || oldStyle->maxHeight().isPercent()))
+        RenderBlock::removePercentHeightDescendant(this);
+
+    // The root and the RenderView always paint their backgrounds/borders.
+    if (isRoot() || isRenderView())
+        setHasBoxDecorations(true);
+
+    setInline(style()->isDisplayInlineType());
+
+    switch (style()->position()) {
+        case AbsolutePosition:
+        case FixedPosition:
+            setPositioned(true);
+            break;
+        default:
+            setPositioned(false);
+
+            if (style()->isFloating())
+                setFloating(true);
+
+            if (style()->position() == RelativePosition)
+                setRelPositioned(true);
+            break;
+    }
+
+    // We also handle <body> and <html>, whose overflow applies to the viewport.
+    if (!isRoot() && (isRenderBlock() || isTableRow() || isTableSection()) && style()->overflowX() != OVISIBLE) {
+        bool boxHasOverflowClip = true;
+        if (isBody()) {
+            // Overflow on the body can propagate to the viewport under the following conditions.
+            // (1) The root element is <html>.
+            // (2) We are the primary <body> (can be checked by looking at document.body).
+            // (3) The root element has visible overflow.
+            if (document()->documentElement()->hasTagName(htmlTag) &&
+                document()->body() == element() &&
+                document()->documentElement()->renderer()->style()->overflowX() == OVISIBLE)
+                boxHasOverflowClip = false;
+        }
+        
+        // Check for overflow clip.
+        // It's sufficient to just check one direction, since it's illegal to have visible on only one overflow value.
+        if (boxHasOverflowClip) {
+            if (!s_hadOverflowClip)
+                // Erase the overflow
+                repaint();
+            setHasOverflowClip();
+        }
+    }
+
+    setHasTransform(style()->hasTransform());
+    setHasReflection(style()->boxReflect());
+
+    if (requiresLayer()) {
+        if (!m_layer) {
+            if (s_wasFloating && isFloating())
+                setChildNeedsLayout(true);
+            m_layer = new (renderArena()) RenderLayer(this);
+            setHasLayer(true);
+            m_layer->insertOnlyThisLayer();
+            if (parent() && !needsLayout() && containingBlock())
+                m_layer->updateLayerPositions();
+        }
+    } else if (m_layer && !isRoot() && !isRenderView()) {
+        ASSERT(m_layer->parent());
+        RenderLayer* layer = m_layer;
+        m_layer = 0;
+        setHasLayer(false);
+        setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
+        setHasReflection(false);
+        layer->removeOnlyThisLayer();
+        if (s_wasFloating && isFloating())
+            setChildNeedsLayout(true);
+    }
+
+    // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the
+    // new zoomed coordinate space.
+    if (hasOverflowClip() && oldStyle && style() && oldStyle->effectiveZoom() != style()->effectiveZoom()) {
+        int left = scrollLeft();
+        if (left) {
+            left = (left / oldStyle->effectiveZoom()) * style()->effectiveZoom();
+            setScrollLeft(left);
+        }
+        int top = scrollTop();
+        if (top) {
+            top = (top / oldStyle->effectiveZoom()) * style()->effectiveZoom();
+            setScrollTop(top);
+        }
+    }
+
+    if (m_layer)
+        m_layer->styleChanged(diff, oldStyle);
+
+    // Set the text color if we're the body.
+    if (isBody())
+        document()->setTextColor(style()->color());
+
+    if (style()->outlineWidth() > 0 && style()->outlineSize() > maximalOutlineSize(PaintPhaseOutline))
+        static_cast<RenderView*>(document()->renderer())->setMaximalOutlineSize(style()->outlineSize());
+}
+
+int RenderBox::minPrefWidth() const
+{
+    if (prefWidthsDirty())
+        const_cast<RenderBox*>(this)->calcPrefWidths();
+        
+    return m_minPrefWidth;
+}
+
+int RenderBox::maxPrefWidth() const
+{
+    if (prefWidthsDirty())
+        const_cast<RenderBox*>(this)->calcPrefWidths();
+        
+    return m_maxPrefWidth;
+}
+
+int RenderBox::overrideSize() const
+{
+    if (!hasOverrideSize())
+        return -1;
+    return gOverrideSizeMap->get(this);
+}
+
+void RenderBox::setOverrideSize(int s)
+{
+    if (s == -1) {
+        if (hasOverrideSize()) {
+            setHasOverrideSize(false);
+            gOverrideSizeMap->remove(this);
+        }
+    } else {
+        if (!gOverrideSizeMap)
+            gOverrideSizeMap = new OverrideSizeMap();
+        setHasOverrideSize(true);
+        gOverrideSizeMap->set(this, s);
+    }
+}
+
+int RenderBox::overrideWidth() const
+{
+    return hasOverrideSize() ? overrideSize() : m_width;
+}
+
+int RenderBox::overrideHeight() const
+{
+    return hasOverrideSize() ? overrideSize() : m_height;
+}
+
+void RenderBox::setPos(int xPos, int yPos)
+{
+    // Optimize for the case where we don't move at all.
+    if (xPos == m_x && yPos == m_y)
+        return;
+
+    m_x = xPos;
+    m_y = yPos;
+}
+
+int RenderBox::calcBorderBoxWidth(int width) const
+{
+    int bordersPlusPadding = borderLeft() + borderRight() + paddingLeft() + paddingRight();
+    if (style()->boxSizing() == CONTENT_BOX)
+        return width + bordersPlusPadding;
+    return max(width, bordersPlusPadding);
+}
+
+int RenderBox::calcBorderBoxHeight(int height) const
+{
+    int bordersPlusPadding = borderTop() + borderBottom() + paddingTop() + paddingBottom();
+    if (style()->boxSizing() == CONTENT_BOX)
+        return height + bordersPlusPadding;
+    return max(height, bordersPlusPadding);
+}
+
+int RenderBox::calcContentBoxWidth(int width) const
+{
+    if (style()->boxSizing() == BORDER_BOX)
+        width -= (borderLeft() + borderRight() + paddingLeft() + paddingRight());
+    return max(0, width);
+}
+
+int RenderBox::calcContentBoxHeight(int height) const
+{
+    if (style()->boxSizing() == BORDER_BOX)
+        height -= (borderTop() + borderBottom() + paddingTop() + paddingBottom());
+    return max(0, height);
+}
+
+// Hit Testing
+bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction action)
+{
+    tx += m_x;
+    ty += m_y;
+
+    // Check kids first.
+    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+        // FIXME: We have to skip over inline flows, since they can show up inside table rows
+        // at the moment (a demoted inline <form> for example). If we ever implement a
+        // table-specific hit-test method (which we should do for performance reasons anyway),
+        // then we can remove this check.
+        if (!child->hasLayer() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
+            updateHitTestResult(result, IntPoint(x - tx, y - ty));
+            return true;
+        }
+    }
+
+    // Check our bounds next. For this purpose always assume that we can only be hit in the
+    // foreground phase (which is true for replaced elements like images).
+    if (style()->visibility() == VISIBLE && action == HitTestForeground && IntRect(tx, ty, m_width, m_height).contains(x, y)) {
+        updateHitTestResult(result, IntPoint(x - tx, y - ty));
+        return true;
+    }
+
+    return false;
+}
+
+// --------------------- painting stuff -------------------------------
+
+void RenderBox::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    tx += m_x;
+    ty += m_y;
+
+    // default implementation. Just pass paint through to the children
+    PaintInfo childInfo(paintInfo);
+    childInfo.paintingRoot = paintingRootForChildren(paintInfo);
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling())
+        child->paint(childInfo, tx, ty);
+}
+
+void RenderBox::paintRootBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
+{
+    const FillLayer* bgLayer = style()->backgroundLayers();
+    Color bgColor = style()->backgroundColor();
+    if (!style()->hasBackground() && element() && element()->hasTagName(HTMLNames::htmlTag)) {
+        // Locate the <body> element using the DOM.  This is easier than trying
+        // to crawl around a render tree with potential :before/:after content and
+        // anonymous blocks created by inline <body> tags etc.  We can locate the <body>
+        // render object very easily via the DOM.
+        HTMLElement* body = document()->body();
+        RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
+        if (bodyObject) {
+            bgLayer = bodyObject->style()->backgroundLayers();
+            bgColor = bodyObject->style()->backgroundColor();
+        }
+    }
+
+    int w = width();
+    int h = height();
+
+    int rw;
+    int rh;
+    if (view()->frameView()) {
+        rw = view()->frameView()->contentsWidth();
+        rh = view()->frameView()->contentsHeight();
+    } else {
+        rw = view()->width();
+        rh = view()->height();
+    }
+
+    // CSS2 14.2:
+    // The background of the box generated by the root element covers the entire canvas including
+    // its margins.
+    int bx = tx - marginLeft();
+    int by = ty - marginTop();
+    int bw = max(w + marginLeft() + marginRight() + borderLeft() + borderRight(), rw);
+    int bh = max(h + marginTop() + marginBottom() + borderTop() + borderBottom(), rh);
+
+    int my = max(by, paintInfo.rect.y());
+
+    paintFillLayers(paintInfo, bgColor, bgLayer, my, paintInfo.rect.height(), bx, by, bw, bh);
+
+    if (style()->hasBorder() && style()->display() != INLINE)
+        paintBorder(paintInfo.context, tx, ty, w, h, style());
+}
+
+void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (!shouldPaintWithinRoot(paintInfo))
+        return;
+
+    if (isRoot()) {
+        paintRootBoxDecorations(paintInfo, tx, ty);
+        return;
+    }
+
+    int w = width();
+    int h = height() + borderTopExtra() + borderBottomExtra();
+    ty -= borderTopExtra();
+
+    // border-fit can adjust where we paint our border and background.  If set, we snugly fit our line box descendants.  (The iChat
+    // balloon layout is an example of this).
+    borderFitAdjust(tx, w);
+
+    int my = max(ty, paintInfo.rect.y());
+    int mh;
+    if (ty < paintInfo.rect.y())
+        mh = max(0, h - (paintInfo.rect.y() - ty));
+    else
+        mh = min(paintInfo.rect.height(), h);
+
+    // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
+    // custom shadows of their own.
+    paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
+
+    // If we have a native theme appearance, paint that before painting our background.
+    // The theme will tell us whether or not we should also paint the CSS background.
+    bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, IntRect(tx, ty, w, h));
+    if (!themePainted) {
+        // The <body> only paints its background if the root element has defined a background
+        // independent of the body.  Go through the DOM to get to the root element's render object,
+        // since the root could be inline and wrapped in an anonymous block.
+        if (!isBody() || document()->documentElement()->renderer()->style()->hasBackground())
+            paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), my, mh, tx, ty, w, h);
+        if (style()->hasAppearance())
+            theme()->paintDecorations(this, paintInfo, IntRect(tx, ty, w, h));
+    }
+
+    // The theme will tell us whether or not we should also paint the CSS border.
+    if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, IntRect(tx, ty, w, h)))) && style()->hasBorder())
+        paintBorder(paintInfo.context, tx, ty, w, h, style());
+}
+
+void RenderBox::paintMask(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (!shouldPaintWithinRoot(paintInfo) || style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+        return;
+
+    int w = width();
+    int h = height() + borderTopExtra() + borderBottomExtra();
+    ty -= borderTopExtra();
+
+    // border-fit can adjust where we paint our border and background.  If set, we snugly fit our line box descendants.  (The iChat
+    // balloon layout is an example of this).
+    borderFitAdjust(tx, w);
+
+    int my = max(ty, paintInfo.rect.y());
+    int mh;
+    if (ty < paintInfo.rect.y())
+        mh = max(0, h - (paintInfo.rect.y() - ty));
+    else
+        mh = min(paintInfo.rect.height(), h);
+
+    paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+}
+
+void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int my, int mh, int tx, int ty, int w, int h)
+{
+    // Figure out if we need to push a transparency layer to render our mask.
+    bool pushTransparencyLayer = false;
+    StyleImage* maskBoxImage = style()->maskBoxImage().image();
+    if ((maskBoxImage && style()->maskLayers()->hasImage()) || style()->maskLayers()->next())
+        // We have to use an extra image buffer to hold the mask. Multiple mask images need
+        // to composite together using source-over so that they can then combine into a single unified mask that
+        // can be composited with the content using destination-in.  SVG images need to be able to set compositing modes
+        // as they draw images contained inside their sub-document, so we paint all our images into a separate buffer
+        // and composite that buffer as the mask.
+        pushTransparencyLayer = true;
+    
+    CompositeOperator compositeOp = CompositeDestinationIn;
+    if (pushTransparencyLayer) {
+        paintInfo.context->setCompositeOperation(CompositeDestinationIn);
+        paintInfo.context->beginTransparencyLayer(1.0f);
+        compositeOp = CompositeSourceOver;
+    }
+
+    paintFillLayers(paintInfo, Color(), style()->maskLayers(), my, mh, tx, ty, w, h, compositeOp);
+    paintNinePieceImage(paintInfo.context, tx, ty, w, h, style(), style()->maskBoxImage(), compositeOp);
+    
+    if (pushTransparencyLayer)
+        paintInfo.context->endTransparencyLayer();
+}
+
+IntRect RenderBox::maskClipRect()
+{
+    IntRect bbox = borderBox();
+    if (style()->maskBoxImage().image())
+        return bbox;
+    
+    IntRect result;
+    for (const FillLayer* maskLayer = style()->maskLayers(); maskLayer; maskLayer = maskLayer->next()) {
+        if (maskLayer->image()) {
+            IntRect maskRect;
+            IntPoint phase;
+            IntSize tileSize;
+            calculateBackgroundImageGeometry(maskLayer, bbox.x(), bbox.y(), bbox.width(), bbox.height(), maskRect, phase, tileSize);
+            result.unite(maskRect);
+        }
+    }
+    return result;
+}
+
+void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
+                                int clipY, int clipH, int tx, int ty, int width, int height, CompositeOperator op)
+{
+    if (!fillLayer)
+        return;
+
+    paintFillLayers(paintInfo, c, fillLayer->next(), clipY, clipH, tx, ty, width, height, op);
+    paintFillLayer(paintInfo, c, fillLayer, clipY, clipH, tx, ty, width, height, op);
+}
+
+void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
+                               int clipY, int clipH, int tx, int ty, int width, int height, CompositeOperator op)
+{
+    paintFillLayerExtended(paintInfo, c, fillLayer, clipY, clipH, tx, ty, width, height, 0, op);
+}
+
+IntSize RenderBox::calculateBackgroundSize(const FillLayer* bgLayer, int scaledWidth, int scaledHeight) const
+{
+    StyleImage* bg = bgLayer->image();
+    bg->setImageContainerSize(IntSize(scaledWidth, scaledHeight)); // Use the box established by background-origin.
+
+    if (bgLayer->isSizeSet()) {
+        int w = scaledWidth;
+        int h = scaledHeight;
+        Length bgWidth = bgLayer->size().width();
+        Length bgHeight = bgLayer->size().height();
+
+        if (bgWidth.isFixed())
+            w = bgWidth.value();
+        else if (bgWidth.isPercent())
+            w = bgWidth.calcValue(scaledWidth);
+        
+        if (bgHeight.isFixed())
+            h = bgHeight.value();
+        else if (bgHeight.isPercent())
+            h = bgHeight.calcValue(scaledHeight);
+        
+        // If one of the values is auto we have to use the appropriate
+        // scale to maintain our aspect ratio.
+        if (bgWidth.isAuto() && !bgHeight.isAuto())
+            w = bg->imageSize(this, style()->effectiveZoom()).width() * h / bg->imageSize(this, style()->effectiveZoom()).height();        
+        else if (!bgWidth.isAuto() && bgHeight.isAuto())
+            h = bg->imageSize(this, style()->effectiveZoom()).height() * w / bg->imageSize(this, style()->effectiveZoom()).width();
+        else if (bgWidth.isAuto() && bgHeight.isAuto()) {
+            // If both width and height are auto, we just want to use the image's
+            // intrinsic size.
+            w = bg->imageSize(this, style()->effectiveZoom()).width();
+            h = bg->imageSize(this, style()->effectiveZoom()).height();
+        }
+        
+        return IntSize(max(1, w), max(1, h));
+    } else
+        return bg->imageSize(this, style()->effectiveZoom());
+}
+
+void RenderBox::imageChanged(WrappedImagePtr image)
+{
+    if (isInlineFlow() ||
+        style()->borderImage().image() && style()->borderImage().image()->data() == image ||
+        style()->maskBoxImage().image() && style()->maskBoxImage().image()->data() == image) {
+        repaint();
+        return;
+    }
+
+    bool didFullRepaint = repaintLayerRectsForImage(image, style()->backgroundLayers(), true);
+    if (!didFullRepaint) {
+        repaintLayerRectsForImage(image, style()->maskLayers(), false);
+    }
+}
+
+bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer* layers, bool drawingBackground)
+{
+    IntRect absoluteRect;
+    RenderBox* layerRenderer = 0;
+
+    for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
+        if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(style()->effectiveZoom())) {
+            // Now that we know this image is being used, compute the renderer and the rect
+            // if we haven't already
+            if (!layerRenderer) {
+                bool drawingRootBackground = drawingBackground && (isRoot() || (isBody() && !document()->documentElement()->renderer()->style()->hasBackground()));
+                if (drawingRootBackground) {
+                    layerRenderer = view();
+
+                    int rw;
+                    int rh;
+
+                    if (FrameView* frameView = static_cast<RenderView*>(layerRenderer)->frameView()) {
+                        rw = frameView->contentsWidth();
+                        rh = frameView->contentsHeight();
+                    } else {
+                        rw = layerRenderer->width();
+                        rh = layerRenderer->height();
+                    }
+                    absoluteRect = IntRect(-layerRenderer->marginLeft(),
+                        -layerRenderer->marginTop(),
+                        max(layerRenderer->width() + layerRenderer->marginLeft() + layerRenderer->marginRight() + layerRenderer->borderLeft() + layerRenderer->borderRight(), rw),
+                        max(layerRenderer->height() + layerRenderer->marginTop() + layerRenderer->marginBottom() + layerRenderer->borderTop() + layerRenderer->borderBottom(), rh));
+                } else {
+                    layerRenderer = this;
+                    absoluteRect = borderBox();
+                }
+
+                layerRenderer->computeAbsoluteRepaintRect(absoluteRect);
+            }
+
+            IntRect repaintRect;
+            IntPoint phase;
+            IntSize tileSize;
+            layerRenderer->calculateBackgroundImageGeometry(curLayer, absoluteRect.x(), absoluteRect.y(), absoluteRect.width(), absoluteRect.height(), repaintRect, phase, tileSize);
+            view()->repaintViewRectangle(repaintRect);
+            if (repaintRect == absoluteRect)
+                return true;
+        }
+    }
+    return false;
+}
+
+void RenderBox::calculateBackgroundImageGeometry(const FillLayer* bgLayer, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize)
+{
+    int pw;
+    int ph;
+    int left = 0;
+    int right = 0;
+    int top = 0;
+    int bottom = 0;
+    int cx;
+    int cy;
+    int rw = 0;
+    int rh = 0;
+
+    // CSS2 chapter 14.2.1
+
+    if (bgLayer->attachment()) {
+        // Scroll
+        if (bgLayer->origin() != BorderFillBox) {
+            left = borderLeft();
+            right = borderRight();
+            top = borderTop();
+            bottom = borderBottom();
+            if (bgLayer->origin() == ContentFillBox) {
+                left += paddingLeft();
+                right += paddingRight();
+                top += paddingTop();
+                bottom += paddingBottom();
+            }
+        }
+        
+        // The background of the box generated by the root element covers the entire canvas including
+        // its margins.  Since those were added in already, we have to factor them out when computing the
+        // box used by background-origin/size/position.
+        if (isRoot()) {
+            rw = width() - left - right;
+            rh = height() - top - bottom; 
+            left += marginLeft();
+            right += marginRight();
+            top += marginTop();
+            bottom += marginBottom();
+        }
+        cx = tx;
+        cy = ty;
+        pw = w - left - right;
+        ph = h - top - bottom;
+    } else {
+        // Fixed
+        IntRect vr = viewRect();
+        cx = vr.x();
+        cy = vr.y();
+        pw = vr.width();
+        ph = vr.height();
+    }
+
+    int sx = 0;
+    int sy = 0;
+    int cw;
+    int ch;
+
+    IntSize scaledImageSize;
+    if (isRoot() && bgLayer->attachment())
+        scaledImageSize = calculateBackgroundSize(bgLayer, rw, rh);
+    else
+        scaledImageSize = calculateBackgroundSize(bgLayer, pw, ph);
+        
+    int scaledImageWidth = scaledImageSize.width();
+    int scaledImageHeight = scaledImageSize.height();
+
+    EFillRepeat backgroundRepeat = bgLayer->repeat();
+    
+    int xPosition;
+    if (isRoot() && bgLayer->attachment())
+        xPosition = bgLayer->xPosition().calcMinValue(rw - scaledImageWidth, true);
+    else
+        xPosition = bgLayer->xPosition().calcMinValue(pw - scaledImageWidth, true);
+    if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatXFill) {
+        cw = pw + left + right;
+        sx = scaledImageWidth ? scaledImageWidth - (xPosition + left) % scaledImageWidth : 0;
+    } else {
+        cx += max(xPosition + left, 0);
+        sx = -min(xPosition + left, 0);
+        cw = scaledImageWidth + min(xPosition + left, 0);
+    }
+    
+    int yPosition;
+    if (isRoot() && bgLayer->attachment())
+        yPosition = bgLayer->yPosition().calcMinValue(rh - scaledImageHeight, true);
+    else 
+        yPosition = bgLayer->yPosition().calcMinValue(ph - scaledImageHeight, true);
+    if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatYFill) {
+        ch = ph + top + bottom;
+        sy = scaledImageHeight ? scaledImageHeight - (yPosition + top) % scaledImageHeight : 0;
+    } else {
+        cy += max(yPosition + top, 0);
+        sy = -min(yPosition + top, 0);
+        ch = scaledImageHeight + min(yPosition + top, 0);
+    }
+
+    if (!bgLayer->attachment()) {
+        sx += max(tx - cx, 0);
+        sy += max(ty - cy, 0);
+    }
+
+    destRect = IntRect(cx, cy, cw, ch);
+    destRect.intersect(IntRect(tx, ty, w, h));
+    phase = IntPoint(sx, sy);
+    tileSize = IntSize(scaledImageWidth, scaledImageHeight);
+}
+
+void RenderBox::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& c, const FillLayer* bgLayer, int clipY, int clipH,
+                                       int tx, int ty, int w, int h, InlineFlowBox* box, CompositeOperator op)
+{
+    GraphicsContext* context = paintInfo.context;
+    bool includeLeftEdge = box ? box->includeLeftEdge() : true;
+    bool includeRightEdge = box ? box->includeRightEdge() : true;
+    int bLeft = includeLeftEdge ? borderLeft() : 0;
+    int bRight = includeRightEdge ? borderRight() : 0;
+    int pLeft = includeLeftEdge ? paddingLeft() : 0;
+    int pRight = includeRightEdge ? paddingRight() : 0;
+
+    bool clippedToBorderRadius = false;
+    if (style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge)) {
+        context->save();
+        context->addRoundedRectClip(IntRect(tx, ty, w, h),
+            includeLeftEdge ? style()->borderTopLeftRadius() : IntSize(),
+            includeRightEdge ? style()->borderTopRightRadius() : IntSize(),
+            includeLeftEdge ? style()->borderBottomLeftRadius() : IntSize(),
+            includeRightEdge ? style()->borderBottomRightRadius() : IntSize());
+        clippedToBorderRadius = true;
+    }
+
+    if (bgLayer->clip() == PaddingFillBox || bgLayer->clip() == ContentFillBox) {
+        // Clip to the padding or content boxes as necessary.
+        bool includePadding = bgLayer->clip() == ContentFillBox;
+        int x = tx + bLeft + (includePadding ? pLeft : 0);
+        int y = ty + borderTop() + (includePadding ? paddingTop() : 0);
+        int width = w - bLeft - bRight - (includePadding ? pLeft + pRight : 0);
+        int height = h - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : 0);
+        context->save();
+        context->clip(IntRect(x, y, width, height));
+    } else if (bgLayer->clip() == TextFillBox) {
+        // We have to draw our text into a mask that can then be used to clip background drawing.
+        // First figure out how big the mask has to be.  It should be no bigger than what we need
+        // to actually render, so we should intersect the dirty rect with the border box of the background.
+        IntRect maskRect(tx, ty, w, h);
+        maskRect.intersect(paintInfo.rect);
+        
+        // Now create the mask.
+        auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(maskRect.size(), false);
+        if (!maskImage.get())
+            return;
+        
+        GraphicsContext* maskImageContext = maskImage->context();
+        maskImageContext->translate(-maskRect.x(), -maskRect.y());
+        
+        // Now add the text to the clip.  We do this by painting using a special paint phase that signals to
+        // InlineTextBoxes that they should just add their contents to the clip.
+        PaintInfo info(maskImageContext, maskRect, PaintPhaseTextClip, true, 0, 0);
+        if (box)
+            box->paint(info, tx - box->xPos(), ty - box->yPos());
+        else
+            paint(info, tx, ty);
+            
+        // The mask has been created.  Now we just need to clip to it.
+        context->save();
+        context->clipToImageBuffer(maskRect, maskImage.get());
+    }
+    
+    StyleImage* bg = bgLayer->image();
+    bool shouldPaintBackgroundImage = bg && bg->canRender(style()->effectiveZoom());
+    Color bgColor = c;
+
+    // When this style flag is set, change existing background colors and images to a solid white background.
+    // If there's no bg color or image, leave it untouched to avoid affecting transparency.
+    // We don't try to avoid loading the background images, because this style flag is only set
+    // when printing, and at that point we've already loaded the background images anyway. (To avoid
+    // loading the background images we'd have to do this check when applying styles rather than
+    // while rendering.)
+    if (style()->forceBackgroundsToWhite()) {
+        // Note that we can't reuse this variable below because the bgColor might be changed
+        bool shouldPaintBackgroundColor = !bgLayer->next() && bgColor.isValid() && bgColor.alpha() > 0;
+        if (shouldPaintBackgroundImage || shouldPaintBackgroundColor) {
+            bgColor = Color::white;
+            shouldPaintBackgroundImage = false;
+        }
+    }
+
+    // Only fill with a base color (e.g., white) if we're the root document, since iframes/frames with
+    // no background in the child document should show the parent's background.
+    bool isTransparent = false;
+    if (!bgLayer->next() && isRoot() && !(bgColor.isValid() && bgColor.alpha() > 0) && view()->frameView()) {
+        Node* elt = document()->ownerElement();
+        if (elt) {
+            if (!elt->hasTagName(frameTag)) {
+                // Locate the <body> element using the DOM.  This is easier than trying
+                // to crawl around a render tree with potential :before/:after content and
+                // anonymous blocks created by inline <body> tags etc.  We can locate the <body>
+                // render object very easily via the DOM.
+                HTMLElement* body = document()->body();
+                isTransparent = !body || !body->hasLocalName(framesetTag); // Can't scroll a frameset document anyway.
+            }
+        } else
+            isTransparent = view()->frameView()->isTransparent();
+
+        // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being transparent.
+        if (isTransparent)
+            view()->frameView()->setUseSlowRepaints(); // The parent must show behind the child.
+    }
+
+    // Paint the color first underneath all images.
+    if (!bgLayer->next()) {
+        IntRect rect(tx, clipY, w, clipH);
+        // If we have an alpha and we are painting the root element, go ahead and blend with the base background color.
+        if (isRoot() && (!bgColor.isValid() || bgColor.alpha() < 0xFF) && !isTransparent) {
+            Color baseColor = view()->frameView()->baseBackgroundColor();
+            if (baseColor.alpha() > 0) {
+                context->save();
+                context->setCompositeOperation(CompositeCopy);
+                context->fillRect(rect, baseColor);
+                context->restore();
+#ifdef ANDROID_ALLOW_TRANSPARENT_BACKGROUNDS
+            }
+#else
+            } else 
+                context->clearRect(rect);
+#endif
+        }
+
+        if (bgColor.isValid() && bgColor.alpha() > 0)
+            context->fillRect(rect, bgColor);
+    }
+
+    // no progressive loading of the background image
+    if (shouldPaintBackgroundImage) {
+        IntRect destRect;
+        IntPoint phase;
+        IntSize tileSize;
+
+        calculateBackgroundImageGeometry(bgLayer, tx, ty, w, h, destRect, phase, tileSize);
+        if (!destRect.isEmpty()) {
+            CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op;
+            context->drawTiledImage(bg->image(this, tileSize), destRect, phase, tileSize, compositeOp);
+        }
+    }
+
+    if (bgLayer->clip() != BorderFillBox)
+        // Undo the background clip
+        context->restore();
+
+    if (clippedToBorderRadius)
+        // Undo the border radius clip
+        context->restore();
+}
+
+#if PLATFORM(MAC)
+
+void RenderBox::paintCustomHighlight(int tx, int ty, const AtomicString& type, bool behindText)
+{
+    Frame* frame = document()->frame();
+    if (!frame)
+        return;
+    Page* page = frame->page();
+    if (!page)
+        return;
+
+    InlineBox* boxWrap = inlineBoxWrapper();
+    RootInlineBox* r = boxWrap ? boxWrap->root() : 0;
+    if (r) {
+        FloatRect rootRect(tx + r->xPos(), ty + r->selectionTop(), r->width(), r->selectionHeight());
+        FloatRect imageRect(tx + m_x, rootRect.y(), width(), rootRect.height());
+        page->chrome()->client()->paintCustomHighlight(node(), type, imageRect, rootRect, behindText, false);
+    } else {
+        FloatRect imageRect(tx + m_x, ty + m_y, width(), height());
+        page->chrome()->client()->paintCustomHighlight(node(), type, imageRect, imageRect, behindText, false);
+    }
+}
+
+#endif
+
+IntRect RenderBox::getOverflowClipRect(int tx, int ty)
+{
+    // FIXME: When overflow-clip (CSS3) is implemented, we'll obtain the property
+    // here.
+
+    int bLeft = borderLeft();
+    int bTop = borderTop();
+
+    int clipX = tx + bLeft;
+    int clipY = ty + bTop;
+    int clipWidth = m_width - bLeft - borderRight();
+    int clipHeight = m_height - bTop - borderBottom() + borderTopExtra() + borderBottomExtra();
+
+    // Subtract out scrollbars if we have them.
+    if (m_layer) {
+        clipWidth -= m_layer->verticalScrollbarWidth();
+        clipHeight -= m_layer->horizontalScrollbarHeight();
+    }
+
+    return IntRect(clipX, clipY, clipWidth, clipHeight);
+}
+
+IntRect RenderBox::getClipRect(int tx, int ty)
+{
+    int clipX = tx;
+    int clipY = ty;
+    int clipWidth = m_width;
+    int clipHeight = m_height;
+
+    if (!style()->clipLeft().isAuto()) {
+        int c = style()->clipLeft().calcValue(m_width);
+        clipX += c;
+        clipWidth -= c;
+    }
+
+    if (!style()->clipRight().isAuto())
+        clipWidth -= m_width - style()->clipRight().calcValue(m_width);
+
+    if (!style()->clipTop().isAuto()) {
+        int c = style()->clipTop().calcValue(m_height);
+        clipY += c;
+        clipHeight -= c;
+    }
+
+    if (!style()->clipBottom().isAuto())
+        clipHeight -= m_height - style()->clipBottom().calcValue(m_height);
+
+    return IntRect(clipX, clipY, clipWidth, clipHeight);
+}
+
+int RenderBox::containingBlockWidth() const
+{
+    RenderBlock* cb = containingBlock();
+    if (!cb)
+        return 0;
+    if (shrinkToAvoidFloats())
+        return cb->lineWidth(m_y);
+    return cb->availableWidth();
+}
+
+IntSize RenderBox::offsetForPositionedInContainer(RenderObject* container) const
+{
+    if (!container->isRelPositioned() || !container->isInlineFlow())
+        return IntSize();
+
+    // When we have an enclosing relpositioned inline, we need to add in the offset of the first line
+    // box from the rest of the content, but only in the cases where we know we're positioned
+    // relative to the inline itself.
+
+    IntSize offset;
+    RenderFlow* flow = static_cast<RenderFlow*>(container);
+    int sx;
+    int sy;
+    if (flow->firstLineBox()) {
+        sx = flow->firstLineBox()->xPos();
+        sy = flow->firstLineBox()->yPos();
+    } else {
+        sx = flow->staticX();
+        sy = flow->staticY();
+    }
+
+    if (!hasStaticX())
+        offset.setWidth(sx);
+    // This is not terribly intuitive, but we have to match other browsers.  Despite being a block display type inside
+    // an inline, we still keep our x locked to the left of the relative positioned inline.  Arguably the correct
+    // behavior would be to go flush left to the block that contains the inline, but that isn't what other browsers
+    // do.
+    else if (!style()->isOriginalDisplayInlineType())
+        // Avoid adding in the left border/padding of the containing block twice.  Subtract it out.
+        offset.setWidth(sx - (containingBlock()->borderLeft() + containingBlock()->paddingLeft()));
+
+    if (!hasStaticY())
+        offset.setHeight(sy);
+
+    return offset;
+}
+
+bool RenderBox::absolutePosition(int& xPos, int& yPos, bool fixed) const
+{
+    if (RenderView* v = view()) {
+        if (LayoutState* layoutState = v->layoutState()) {
+            xPos = layoutState->m_offset.width() + m_x;
+            yPos = layoutState->m_offset.height() + m_y;
+            if (style()->position() == RelativePosition && m_layer)
+                m_layer->relativePositionOffset(xPos, yPos);
+            return true;
+        }
+    }
+
+    if (style()->position() == FixedPosition)
+        fixed = true;
+
+    RenderObject* o = container();
+    if (o && o->absolutePositionForContent(xPos, yPos, fixed)) {
+        if (style()->position() == AbsolutePosition) {
+            IntSize offset = offsetForPositionedInContainer(o);
+            xPos += offset.width();
+            yPos += offset.height();
+        }
+
+        if (o->hasOverflowClip())
+            o->layer()->subtractScrollOffset(xPos, yPos);
+
+        if (!isInline() || isReplaced()) {
+            RenderBlock* cb;
+            if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition
+                    && (cb = static_cast<RenderBlock*>(o))->hasColumns()) {
+                IntRect rect(m_x, m_y, 1, 1);
+                cb->adjustRectForColumns(rect);
+                xPos += rect.x();
+                yPos += rect.y();
+            } else {
+                xPos += m_x;
+                yPos += m_y;
+            }
+        }
+
+        if (isRelPositioned()) {
+            xPos += relativePositionOffsetX();
+            yPos += relativePositionOffsetY();
+        }
+
+        return true;
+    } else {
+        xPos = 0;
+        yPos = 0;
+        return false;
+    }
+}
+
+void RenderBox::dirtyLineBoxes(bool fullLayout, bool /*isRootLineBox*/)
+{
+    if (m_inlineBoxWrapper) {
+        if (fullLayout) {
+            m_inlineBoxWrapper->destroy(renderArena());
+            m_inlineBoxWrapper = 0;
+        } else
+            m_inlineBoxWrapper->dirtyLineBoxes();
+    }
+}
+
+void RenderBox::position(InlineBox* box)
+{
+    if (isPositioned()) {
+        // Cache the x position only if we were an INLINE type originally.
+        bool wasInline = style()->isOriginalDisplayInlineType();
+        if (wasInline && hasStaticX()) {
+            // The value is cached in the xPos of the box.  We only need this value if
+            // our object was inline originally, since otherwise it would have ended up underneath
+            // the inlines.
+            setStaticX(box->xPos());
+            setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
+        } else if (!wasInline && hasStaticY()) {
+            // Our object was a block originally, so we make our normal flow position be
+            // just below the line box (as though all the inlines that came before us got
+            // wrapped in an anonymous block, which is what would have happened had we been
+            // in flow).  This value was cached in the yPos() of the box.
+            setStaticY(box->yPos());
+            setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
+        }
+
+        // Nuke the box.
+        box->remove();
+        box->destroy(renderArena());
+    } else if (isReplaced()) {
+        m_x = box->xPos();
+        m_y = box->yPos();
+        m_inlineBoxWrapper = box;
+    }
+}
+
+void RenderBox::deleteLineBoxWrapper()
+{
+    if (m_inlineBoxWrapper) {
+        if (!documentBeingDestroyed())
+            m_inlineBoxWrapper->remove();
+        m_inlineBoxWrapper->destroy(renderArena());
+        m_inlineBoxWrapper = 0;
+    }
+}
+
+IntRect RenderBox::absoluteClippedOverflowRect()
+{
+    if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
+        return IntRect();
+
+    IntRect r = overflowRect(false);
+
+    if (RenderView* v = view())
+        r.move(v->layoutDelta());
+
+    if (style()) {
+        if (style()->hasAppearance())
+            // The theme may wish to inflate the rect used when repainting.
+            theme()->adjustRepaintRect(this, r);
+
+        // FIXME: Technically the outline inflation could fit within the theme inflation.
+        if (!isInline() && continuation())
+            r.inflate(continuation()->style()->outlineSize());
+        else
+            r.inflate(style()->outlineSize());
+    }
+    computeAbsoluteRepaintRect(r);
+    return r;
+}
+
+void RenderBox::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
+{
+    if (RenderView* v = view()) {
+        if (LayoutState* layoutState = v->layoutState()) {
+            if (style()->position() == RelativePosition && m_layer) {
+                int relX = 0;
+                int relY = 0;
+                m_layer->relativePositionOffset(relX, relY);
+                rect.move(relX, relY);
+            }
+            rect.move(m_x, m_y);
+            rect.move(layoutState->m_offset);
+            if (layoutState->m_clipped)
+                rect.intersect(layoutState->m_clipRect);
+            return;
+        }
+    }
+
+    // FIXME: This is really a hack.  If the reflection caused the repaint, we don't have to 
+    // do this (and yet we do).  If there are nested reflections, then the single static is insufficient.
+    static bool invalidatingReflection;
+    if (hasReflection() && !invalidatingReflection) {
+        invalidatingReflection = true;
+        layer()->reflection()->repaintRectangle(rect);
+        invalidatingReflection = false;
+    }
+
+    int x = rect.x() + m_x;
+    int y = rect.y() + m_y;
+
+    // Apply the relative position offset when invalidating a rectangle.  The layer
+    // is translated, but the render box isn't, so we need to do this to get the
+    // right dirty rect.  Since this is called from RenderObject::setStyle, the relative position
+    // flag on the RenderObject has been cleared, so use the one on the style().
+    if (style()->position() == RelativePosition && m_layer)
+        m_layer->relativePositionOffset(x, y);
+
+    if (style()->position() == FixedPosition)
+        fixed = true;
+        
+    RenderObject* o = container();
+    if (o) {
+        if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition) {
+            RenderBlock* cb = static_cast<RenderBlock*>(o);
+            if (cb->hasColumns()) {
+                IntRect repaintRect(x, y, rect.width(), rect.height());
+                cb->adjustRectForColumns(repaintRect);
+                x = repaintRect.x();
+                y = repaintRect.y();
+                rect = repaintRect;
+            }
+        }
+
+        if (style()->position() == AbsolutePosition) {
+            IntSize offset = offsetForPositionedInContainer(o);
+            x += offset.width();
+            y += offset.height();
+        }
+        
+        // We are now in our parent container's coordinate space.  Apply our transform to obtain a bounding box
+        // in the parent's coordinate space that encloses us.
+        if (m_layer && m_layer->transform()) {
+            fixed = false;
+            rect = m_layer->transform()->mapRect(rect);
+            x = rect.x() + m_x;
+            y = rect.y() + m_y;
+        }
+
+        // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
+        // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
+        if (o->hasOverflowClip()) {
+            // o->height() is inaccurate if we're in the middle of a layout of |o|, so use the
+            // layer's size instead.  Even if the layer's size is wrong, the layer itself will repaint
+            // anyway if its size does change.
+            IntRect boxRect(0, 0, o->layer()->width(), o->layer()->height());
+            o->layer()->subtractScrollOffset(x, y); // For overflow:auto/scroll/hidden.
+            IntRect repaintRect(x, y, rect.width(), rect.height());
+            rect = intersection(repaintRect, boxRect);
+            if (rect.isEmpty())
+                return;
+        } else {
+            rect.setX(x);
+            rect.setY(y);
+        }
+        
+        o->computeAbsoluteRepaintRect(rect, fixed);
+    }
+}
+
+void RenderBox::repaintDuringLayoutIfMoved(const IntRect& rect)
+{
+    int newX = m_x;
+    int newY = m_y;
+    int newWidth = m_width;
+    int newHeight = m_height;
+    if (rect.x() != newX || rect.y() != newY) {
+        // The child moved.  Invalidate the object's old and new positions.  We have to do this
+        // since the object may not have gotten a layout.
+        m_x = rect.x();
+        m_y = rect.y();
+        m_width = rect.width();
+        m_height = rect.height();
+        repaint();
+        repaintOverhangingFloats(true);
+
+        m_x = newX;
+        m_y = newY;
+        m_width = newWidth;
+        m_height = newHeight;
+        repaint();
+        repaintOverhangingFloats(true);
+    }
+}
+
+int RenderBox::relativePositionOffsetX() const
+{
+    if (!style()->left().isAuto()) {
+        if (!style()->right().isAuto() && containingBlock()->style()->direction() == RTL)
+            return -style()->right().calcValue(containingBlockWidth());
+        return style()->left().calcValue(containingBlockWidth());
+    }
+    if (!style()->right().isAuto())
+        return -style()->right().calcValue(containingBlockWidth());
+    return 0;
+}
+
+int RenderBox::relativePositionOffsetY() const
+{
+    if (!style()->top().isAuto()) {
+        if (!style()->top().isPercent() || containingBlock()->style()->height().isFixed())
+            return style()->top().calcValue(containingBlockHeight());
+    } else if (!style()->bottom().isAuto()) {
+        if (!style()->bottom().isPercent() || containingBlock()->style()->height().isFixed())
+            return -style()->bottom().calcValue(containingBlockHeight());
+    }
+    return 0;
+}
+
+void RenderBox::calcWidth()
+{
+#ifdef ANDROID_LAYOUT
+    if (view()->frameView()) {
+        const Settings* settings = document()->settings();
+        ASSERT(settings);
+        if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) {
+            m_visibleWidth = view()->frameView()->screenWidth();
+        }
+    }
+#endif
+                
+    if (isPositioned()) {
+        calcAbsoluteHorizontal();
+        return;
+    }
+
+    // If layout is limited to a subtree, the subtree root's width does not change.
+    if (node() && view()->frameView() && view()->frameView()->layoutRoot(true) == this)
+        return;
+
+    // The parent box is flexing us, so it has increased or decreased our
+    // width.  Use the width from the style context.
+    if (hasOverrideSize() &&  parent()->style()->boxOrient() == HORIZONTAL
+            && parent()->isFlexibleBox() && parent()->isFlexingChildren()) {
+        m_width = overrideSize();
+        return;
+    }
+
+    bool inVerticalBox = parent()->isFlexibleBox() && (parent()->style()->boxOrient() == VERTICAL);
+    bool stretching = (parent()->style()->boxAlign() == BSTRETCH);
+    bool treatAsReplaced = shouldCalculateSizeAsReplaced() && (!inVerticalBox || !stretching);
+
+    Length width = (treatAsReplaced) ? Length(calcReplacedWidth(), Fixed) : style()->width();
+
+    RenderBlock* cb = containingBlock();
+    int containerWidth = max(0, containingBlockWidth());
+
+    Length marginLeft = style()->marginLeft();
+    Length marginRight = style()->marginRight();
+
+    if (isInline() && !isInlineBlockOrInlineTable()) {
+        // just calculate margins
+        m_marginLeft = marginLeft.calcMinValue(containerWidth);
+        m_marginRight = marginRight.calcMinValue(containerWidth);
+        if (treatAsReplaced)
+            m_width = max(width.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight(), minPrefWidth());
+#ifdef ANDROID_LAYOUT
+        // in SSR mode with replaced box, if the box width is wider than the container width,
+        // it will be shrinked to fit to the container.
+        if (containerWidth && (m_width+m_marginLeft+m_marginRight) > containerWidth && 
+                document()->frame()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) {
+            m_marginLeft = m_marginRight = 0;                    
+            m_width = m_minPrefWidth = m_maxPrefWidth = containerWidth;
+        }
+#endif        
+
+        return;
+    }
+
+    // Width calculations
+    if (treatAsReplaced)
+        m_width = width.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight();
+    else {
+        // Calculate Width
+        m_width = calcWidthUsing(Width, containerWidth);
+
+        // Calculate MaxWidth
+        if (!style()->maxWidth().isUndefined()) {
+            int maxW = calcWidthUsing(MaxWidth, containerWidth);
+            if (m_width > maxW) {
+                m_width = maxW;
+                width = style()->maxWidth();
+            }
+        }
+
+        // Calculate MinWidth
+        int minW = calcWidthUsing(MinWidth, containerWidth);
+        if (m_width < minW) {
+            m_width = minW;
+            width = style()->minWidth();
+        }
+    }
+
+    if (stretchesToMinIntrinsicWidth()) {
+        m_width = max(m_width, minPrefWidth());
+        width = Length(m_width, Fixed);
+    }
+
+    // Margin calculations
+    if (width.isAuto()) {
+        m_marginLeft = marginLeft.calcMinValue(containerWidth);
+        m_marginRight = marginRight.calcMinValue(containerWidth);
+    } else {
+        m_marginLeft = 0;
+        m_marginRight = 0;
+        calcHorizontalMargins(marginLeft, marginRight, containerWidth);
+    }
+#ifdef ANDROID_LAYOUT
+    // in SSR mode with non-replaced box, we use ANDROID_SSR_MARGIN_PADDING for left/right margin.
+    // If the box width is wider than the container width, it will be shrinked to fit to the container. 
+    if (containerWidth && !treatAsReplaced && 
+            document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) {
+        m_width += m_marginLeft + m_marginRight;
+        m_marginLeft = m_marginLeft > ANDROID_SSR_MARGIN_PADDING ? ANDROID_SSR_MARGIN_PADDING : m_marginLeft;
+        m_marginRight = m_marginRight > ANDROID_SSR_MARGIN_PADDING ? ANDROID_SSR_MARGIN_PADDING : m_marginRight;
+        if (m_width > containerWidth)
+            m_width = m_minPrefWidth = m_maxPrefWidth = containerWidth-(m_marginLeft + m_marginRight);
+        else
+            m_width -= (m_marginLeft + m_marginRight);
+    }
+#endif
+
+    if (containerWidth && containerWidth != (m_width + m_marginLeft + m_marginRight)
+            && !isFloating() && !isInline() && !cb->isFlexibleBox()) {
+        if (cb->style()->direction() == LTR)
+            m_marginRight = containerWidth - m_width - m_marginLeft;
+        else
+            m_marginLeft = containerWidth - m_width - m_marginRight;
+    }
+}
+
+int RenderBox::calcWidthUsing(WidthType widthType, int cw)
+{
+    int width = m_width;
+    Length w;
+    if (widthType == Width)
+        w = style()->width();
+    else if (widthType == MinWidth)
+        w = style()->minWidth();
+    else
+        w = style()->maxWidth();
+
+    if (w.isIntrinsicOrAuto()) {
+        int marginLeft = style()->marginLeft().calcMinValue(cw);
+        int marginRight = style()->marginRight().calcMinValue(cw);
+        if (cw)
+            width = cw - marginLeft - marginRight;
+
+        if (sizesToIntrinsicWidth(widthType)) {
+            width = max(width, minPrefWidth());
+            width = min(width, maxPrefWidth());
+        }
+    } else
+        width = calcBorderBoxWidth(w.calcValue(cw));
+
+    return width;
+}
+
+bool RenderBox::sizesToIntrinsicWidth(WidthType widthType) const
+{
+    // Marquees in WinIE are like a mixture of blocks and inline-blocks.  They size as though they're blocks,
+    // but they allow text to sit on the same line as the marquee.
+    if (isFloating() || (isCompact() && isInline())
+            || (isInlineBlockOrInlineTable() && !isHTMLMarquee()))
+        return true;
+
+    // This code may look a bit strange.  Basically width:intrinsic should clamp the size when testing both
+    // min-width and width.  max-width is only clamped if it is also intrinsic.
+    Length width = (widthType == MaxWidth) ? style()->maxWidth() : style()->width();
+    if (width.type() == Intrinsic)
+        return true;
+
+    // Children of a horizontal marquee do not fill the container by default.
+    // FIXME: Need to deal with MAUTO value properly.  It could be vertical.
+    if (parent()->style()->overflowX() == OMARQUEE) {
+        EMarqueeDirection dir = parent()->style()->marqueeDirection();
+        if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT)
+            return true;
+    }
+
+    // Flexible horizontal boxes lay out children at their intrinsic widths.  Also vertical boxes
+    // that don't stretch their kids lay out their children at their intrinsic widths.
+    if (parent()->isFlexibleBox()
+            && (parent()->style()->boxOrient() == HORIZONTAL || parent()->style()->boxAlign() != BSTRETCH))
+        return true;
+
+    return false;
+}
+
+void RenderBox::calcHorizontalMargins(const Length& marginLeft, const Length& marginRight, int containerWidth)
+{
+    if (isFloating() || isInline()) {
+        // Inline blocks/tables and floats don't have their margins increased.
+        m_marginLeft = marginLeft.calcMinValue(containerWidth);
+        m_marginRight = marginRight.calcMinValue(containerWidth);
+        return;
+    }
+
+    if ((marginLeft.isAuto() && marginRight.isAuto() && m_width < containerWidth)
+            || (!marginLeft.isAuto() && !marginRight.isAuto() && containingBlock()->style()->textAlign() == WEBKIT_CENTER)) {
+        m_marginLeft = max(0, (containerWidth - m_width) / 2);
+        m_marginRight = containerWidth - m_width - m_marginLeft;
+    } else if ((marginRight.isAuto() && m_width < containerWidth)
+            || (!marginLeft.isAuto() && containingBlock()->style()->direction() == RTL && containingBlock()->style()->textAlign() == WEBKIT_LEFT)) {
+        m_marginLeft = marginLeft.calcValue(containerWidth);
+        m_marginRight = containerWidth - m_width - m_marginLeft;
+    } else if ((marginLeft.isAuto() && m_width < containerWidth)
+            || (!marginRight.isAuto() && containingBlock()->style()->direction() == LTR && containingBlock()->style()->textAlign() == WEBKIT_RIGHT)) {
+        m_marginRight = marginRight.calcValue(containerWidth);
+        m_marginLeft = containerWidth - m_width - m_marginRight;
+    } else {
+        // This makes auto margins 0 if we failed a m_width < containerWidth test above (css2.1, 10.3.3).
+        m_marginLeft = marginLeft.calcMinValue(containerWidth);
+        m_marginRight = marginRight.calcMinValue(containerWidth);
+    }
+}
+
+void RenderBox::calcHeight()
+{
+    // Cell height is managed by the table and inline non-replaced elements do not support a height property.
+    if (isTableCell() || (isInline() && !isReplaced()))
+        return;
+
+    if (isPositioned())
+        calcAbsoluteVertical();
+    else {
+        calcVerticalMargins();
+
+        // For tables, calculate margins only.
+        if (isTable())
+            return;
+
+        Length h;
+        bool inHorizontalBox = parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL;
+        bool stretching = parent()->style()->boxAlign() == BSTRETCH;
+        bool treatAsReplaced = shouldCalculateSizeAsReplaced() && (!inHorizontalBox || !stretching);
+        bool checkMinMaxHeight = false;
+
+        // The parent box is flexing us, so it has increased or decreased our height.  We have to
+        // grab our cached flexible height.
+        if (hasOverrideSize() && parent()->isFlexibleBox() && parent()->style()->boxOrient() == VERTICAL
+                && parent()->isFlexingChildren())
+            h = Length(overrideSize() - borderTop() - borderBottom() - paddingTop() - paddingBottom(), Fixed);
+        else if (treatAsReplaced)
+            h = Length(calcReplacedHeight(), Fixed);
+        else {
+            h = style()->height();
+            checkMinMaxHeight = true;
+        }
+
+        // Block children of horizontal flexible boxes fill the height of the box.
+        if (h.isAuto() && parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
+                && parent()->isStretchingChildren()) {
+            h = Length(parent()->contentHeight() - marginTop() - marginBottom() -
+                       borderTop() - paddingTop() - borderBottom() - paddingBottom(), Fixed);
+            checkMinMaxHeight = false;
+        }
+
+        int height;
+        if (checkMinMaxHeight) {
+#ifdef ANDROID_LAYOUT
+            // in SSR mode, ignore CSS height as layout is so different
+            if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR)
+                height = m_height;
+            else
+#endif
+            height = calcHeightUsing(style()->height());
+            if (height == -1)
+                height = m_height;
+            int minH = calcHeightUsing(style()->minHeight()); // Leave as -1 if unset.
+            int maxH = style()->maxHeight().isUndefined() ? height : calcHeightUsing(style()->maxHeight());
+            if (maxH == -1)
+                maxH = height;
+            height = min(maxH, height);
+            height = max(minH, height);
+        } else
+            // The only times we don't check min/max height are when a fixed length has
+            // been given as an override.  Just use that.  The value has already been adjusted
+            // for box-sizing.
+            height = h.value() + borderTop() + borderBottom() + paddingTop() + paddingBottom();
+
+        m_height = height;
+    }
+
+    // WinIE quirk: The <html> block always fills the entire canvas in quirks mode.  The <body> always fills the
+    // <html> block in quirks mode.  Only apply this quirk if the block is normal flow and no height
+    // is specified.
+    if (stretchesToViewHeight() && !document()->printing()) {
+        int margins = collapsedMarginTop() + collapsedMarginBottom();
+        int visHeight = view()->viewHeight();
+        if (isRoot())
+            m_height = max(m_height, visHeight - margins);
+        else {
+            int marginsBordersPadding = margins + parent()->marginTop() + parent()->marginBottom()
+                + parent()->borderTop() + parent()->borderBottom()
+                + parent()->paddingTop() + parent()->paddingBottom();
+            m_height = max(m_height, visHeight - marginsBordersPadding);
+        }
+    }
+}
+
+int RenderBox::calcHeightUsing(const Length& h)
+{
+    int height = -1;
+    if (!h.isAuto()) {
+        if (h.isFixed())
+            height = h.value();
+        else if (h.isPercent())
+            height = calcPercentageHeight(h);
+        if (height != -1) {
+            height = calcBorderBoxHeight(height);
+            return height;
+        }
+    }
+    return height;
+}
+
+int RenderBox::calcPercentageHeight(const Length& height)
+{
+    int result = -1;
+    bool includeBorderPadding = isTable();
+    RenderBlock* cb = containingBlock();
+    if (style()->htmlHacks()) {
+        // In quirks mode, blocks with auto height are skipped, and we keep looking for an enclosing
+        // block that may have a specified height and then use it.  In strict mode, this violates the
+        // specification, which states that percentage heights just revert to auto if the containing
+        // block has an auto height.
+        while (!cb->isRenderView() && !cb->isBody() && !cb->isTableCell() && !cb->isPositioned() && cb->style()->height().isAuto()) {
+            cb = cb->containingBlock();
+            cb->addPercentHeightDescendant(this);
+        }
+    }
+
+    // A positioned element that specified both top/bottom or that specifies height should be treated as though it has a height
+    // explicitly specified that can be used for any percentage computations.
+    bool isPositionedWithSpecifiedHeight = cb->isPositioned() && (!cb->style()->height().isAuto() || (!cb->style()->top().isAuto() && !cb->style()->bottom().isAuto()));
+
+    // Table cells violate what the CSS spec says to do with heights.  Basically we
+    // don't care if the cell specified a height or not.  We just always make ourselves
+    // be a percentage of the cell's current content height.
+    if (cb->isTableCell()) {
+        result = cb->overrideSize();
+        if (result == -1) {
+            // Normally we would let the cell size intrinsically, but scrolling overflow has to be
+            // treated differently, since WinIE lets scrolled overflow regions shrink as needed.
+            // While we can't get all cases right, we can at least detect when the cell has a specified
+            // height or when the table has a specified height.  In these cases we want to initially have
+            // no size and allow the flexing of the table or the cell to its specified height to cause us
+            // to grow to fill the space.  This could end up being wrong in some cases, but it is
+            // preferable to the alternative (sizing intrinsically and making the row end up too big).
+            RenderTableCell* cell = static_cast<RenderTableCell*>(cb);
+            if (scrollsOverflowY() && (!cell->style()->height().isAuto() || !cell->table()->style()->height().isAuto()))
+                return 0;
+            return -1;
+        }
+        includeBorderPadding = true;
+    }
+    // Otherwise we only use our percentage height if our containing block had a specified
+    // height.
+    else if (cb->style()->height().isFixed())
+        result = cb->calcContentBoxHeight(cb->style()->height().value());
+    else if (cb->style()->height().isPercent() && !isPositionedWithSpecifiedHeight) {
+        // We need to recur and compute the percentage height for our containing block.
+        result = cb->calcPercentageHeight(cb->style()->height());
+        if (result != -1)
+            result = cb->calcContentBoxHeight(result);
+    } else if (cb->isRenderView() || (cb->isBody() && style()->htmlHacks()) || isPositionedWithSpecifiedHeight) {
+        // Don't allow this to affect the block' m_height member variable, since this
+        // can get called while the block is still laying out its kids.
+        int oldHeight = cb->height();
+        cb->calcHeight();
+        result = cb->contentHeight();
+        cb->setHeight(oldHeight);
+    } else if (cb->isRoot() && isPositioned())
+        // Match the positioned objects behavior, which is that positioned objects will fill their viewport
+        // always.  Note we could only hit this case by recurring into calcPercentageHeight on a positioned containing block.
+        result = cb->calcContentBoxHeight(cb->availableHeight());
+
+    if (result != -1) {
+        result = height.calcValue(result);
+        if (includeBorderPadding) {
+            // It is necessary to use the border-box to match WinIE's broken
+            // box model.  This is essential for sizing inside
+            // table cells using percentage heights.
+            result -= (borderTop() + paddingTop() + borderBottom() + paddingBottom());
+            result = max(0, result);
+        }
+    }
+    return result;
+}
+
+int RenderBox::calcReplacedWidth(bool includeMaxWidth) const
+{
+    int width = calcReplacedWidthUsing(style()->width());
+    int minW = calcReplacedWidthUsing(style()->minWidth());
+    int maxW = !includeMaxWidth || style()->maxWidth().isUndefined() ? width : calcReplacedWidthUsing(style()->maxWidth());
+
+    return max(minW, min(width, maxW));
+}
+
+int RenderBox::calcReplacedWidthUsing(Length width) const
+{
+    switch (width.type()) {
+        case Fixed:
+            return calcContentBoxWidth(width.value());
+        case Percent: {
+            const int cw = isPositioned() ? containingBlockWidthForPositioned(container()) : containingBlockWidth();
+            if (cw > 0)
+                return calcContentBoxWidth(width.calcMinValue(cw));
+        }
+        // fall through
+        default:
+            return intrinsicSize().width();
+     }
+ }
+
+int RenderBox::calcReplacedHeight() const
+{
+    int height = calcReplacedHeightUsing(style()->height());
+    int minH = calcReplacedHeightUsing(style()->minHeight());
+    int maxH = style()->maxHeight().isUndefined() ? height : calcReplacedHeightUsing(style()->maxHeight());
+
+    return max(minH, min(height, maxH));
+}
+
+int RenderBox::calcReplacedHeightUsing(Length height) const
+{
+    switch (height.type()) {
+        case Fixed:
+            return calcContentBoxHeight(height.value());
+        case Percent:
+        {
+            RenderObject* cb = isPositioned() ? container() : containingBlock();
+            while (cb->isAnonymous()) {
+                cb = cb->containingBlock();
+                static_cast<RenderBlock*>(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
+            }
+
+            if (cb->isPositioned() && cb->style()->height().isAuto() && !(cb->style()->top().isAuto() || cb->style()->bottom().isAuto())) {
+                ASSERT(cb->isRenderBlock());
+                RenderBlock* block = static_cast<RenderBlock*>(cb);
+                int oldHeight = block->height();
+                block->calcHeight();
+                int newHeight = block->calcContentBoxHeight(block->contentHeight());
+                block->setHeight(oldHeight);
+                return calcContentBoxHeight(height.calcValue(newHeight));
+            }
+            
+            int availableHeight = isPositioned() ? containingBlockHeightForPositioned(cb) : cb->availableHeight();
+
+            // It is necessary to use the border-box to match WinIE's broken
+            // box model.  This is essential for sizing inside
+            // table cells using percentage heights.
+            if (cb->isTableCell() && (cb->style()->height().isAuto() || cb->style()->height().isPercent())) {
+                // Don't let table cells squeeze percent-height replaced elements
+                // <http://bugs.webkit.org/show_bug.cgi?id=15359>
+                availableHeight = max(availableHeight, intrinsicSize().height());
+                return height.calcValue(availableHeight - (borderTop() + borderBottom()
+                    + paddingTop() + paddingBottom()));
+            }
+
+            return calcContentBoxHeight(height.calcValue(availableHeight));
+        }
+        default:
+            return intrinsicSize().height();
+    }
+}
+
+int RenderBox::availableHeight() const
+{
+    return availableHeightUsing(style()->height());
+}
+
+int RenderBox::availableHeightUsing(const Length& h) const
+{
+    if (h.isFixed())
+        return calcContentBoxHeight(h.value());
+
+    if (isRenderView())
+        return static_cast<const RenderView*>(this)->frameView()->visibleHeight();
+
+    // We need to stop here, since we don't want to increase the height of the table
+    // artificially.  We're going to rely on this cell getting expanded to some new
+    // height, and then when we lay out again we'll use the calculation below.
+    if (isTableCell() && (h.isAuto() || h.isPercent()))
+        return overrideSize() - (borderLeft() + borderRight() + paddingLeft() + paddingRight());
+
+    if (h.isPercent())
+       return calcContentBoxHeight(h.calcValue(containingBlock()->availableHeight()));
+
+    if (isRenderBlock() && isPositioned() && style()->height().isAuto() && !(style()->top().isAuto() || style()->bottom().isAuto())) {
+        RenderBlock* block = const_cast<RenderBlock*>(static_cast<const RenderBlock*>(this));
+        int oldHeight = block->height();
+        block->calcHeight();
+        int newHeight = block->calcContentBoxHeight(block->contentHeight());
+        block->setHeight(oldHeight);
+        return calcContentBoxHeight(newHeight);
+    }
+
+    return containingBlock()->availableHeight();
+}
+
+void RenderBox::calcVerticalMargins()
+{
+    if (isTableCell()) {
+        m_marginTop = 0;
+        m_marginBottom = 0;
+        return;
+    }
+
+    // margins are calculated with respect to the _width_ of
+    // the containing block (8.3)
+    int cw = containingBlock()->contentWidth();
+
+    m_marginTop = style()->marginTop().calcMinValue(cw);
+    m_marginBottom = style()->marginBottom().calcMinValue(cw);
+}
+
+int RenderBox::staticX() const
+{
+    return m_layer ? m_layer->staticX() : 0;
+}
+
+int RenderBox::staticY() const
+{
+    return m_layer ? m_layer->staticY() : 0;
+}
+
+void RenderBox::setStaticX(int staticX)
+{
+    ASSERT(isPositioned() || isRelPositioned());
+    m_layer->setStaticX(staticX);
+}
+
+void RenderBox::setStaticY(int staticY)
+{
+    ASSERT(isPositioned() || isRelPositioned());
+    
+    if (staticY == m_layer->staticY())
+        return;
+    
+    m_layer->setStaticY(staticY);
+    setChildNeedsLayout(true, false);
+}
+
+int RenderBox::containingBlockWidthForPositioned(const RenderObject* containingBlock) const
+{
+    if (containingBlock->isInlineFlow()) {
+        ASSERT(containingBlock->isRelPositioned());
+
+        const RenderFlow* flow = static_cast<const RenderFlow*>(containingBlock);
+        InlineFlowBox* first = flow->firstLineBox();
+        InlineFlowBox* last = flow->lastLineBox();
+
+        // If the containing block is empty, return a width of 0.
+        if (!first || !last)
+            return 0;
+
+        int fromLeft;
+        int fromRight;
+        if (containingBlock->style()->direction() == LTR) {
+            fromLeft = first->xPos() + first->borderLeft();
+            fromRight = last->xPos() + last->width() - last->borderRight();
+        } else {
+            fromRight = first->xPos() + first->width() - first->borderRight();
+            fromLeft = last->xPos() + last->borderLeft();
+        }
+
+        return max(0, (fromRight - fromLeft));
+    }
+
+    return containingBlock->width() - containingBlock->borderLeft() - containingBlock->borderRight() - containingBlock->verticalScrollbarWidth();
+}
+
+int RenderBox::containingBlockHeightForPositioned(const RenderObject* containingBlock) const
+{
+    return containingBlock->height() - containingBlock->borderTop() - containingBlock->borderBottom();
+}
+
+void RenderBox::calcAbsoluteHorizontal()
+{
+    if (isReplaced()) {
+        calcAbsoluteHorizontalReplaced();
+        return;
+    }
+
+    // QUESTIONS
+    // FIXME 1: Which RenderObject's 'direction' property should used: the
+    // containing block (cb) as the spec seems to imply, the parent (parent()) as
+    // was previously done in calculating the static distances, or ourself, which
+    // was also previously done for deciding what to override when you had
+    // over-constrained margins?  Also note that the container block is used
+    // in similar situations in other parts of the RenderBox class (see calcWidth()
+    // and calcHorizontalMargins()). For now we are using the parent for quirks
+    // mode and the containing block for strict mode.
+
+    // FIXME 2: Should we still deal with these the cases of 'left' or 'right' having
+    // the type 'static' in determining whether to calculate the static distance?
+    // NOTE: 'static' is not a legal value for 'left' or 'right' as of CSS 2.1.
+
+    // FIXME 3: Can perhaps optimize out cases when max-width/min-width are greater
+    // than or less than the computed m_width.  Be careful of box-sizing and
+    // percentage issues.
+
+    // The following is based off of the W3C Working Draft from April 11, 2006 of
+    // CSS 2.1: Section 10.3.7 "Absolutely positioned, non-replaced elements"
+    // <http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width>
+    // (block-style-comments in this function and in calcAbsoluteHorizontalValues()
+    // correspond to text from the spec)
+
+
+    // We don't use containingBlock(), since we may be positioned by an enclosing
+    // relative positioned inline.
+    const RenderObject* containerBlock = container();
+
+    const int containerWidth = containingBlockWidthForPositioned(containerBlock);
+
+    // To match WinIE, in quirks mode use the parent's 'direction' property
+    // instead of the the container block's.
+    TextDirection containerDirection = (style()->htmlHacks()) ? parent()->style()->direction() : containerBlock->style()->direction();
+
+    const int bordersPlusPadding = borderLeft() + borderRight() + paddingLeft() + paddingRight();
+    const Length marginLeft = style()->marginLeft();
+    const Length marginRight = style()->marginRight();
+    Length left = style()->left();
+    Length right = style()->right();
+
+    /*---------------------------------------------------------------------------*\
+     * For the purposes of this section and the next, the term "static position"
+     * (of an element) refers, roughly, to the position an element would have had
+     * in the normal flow. More precisely:
+     *
+     * * The static position for 'left' is the distance from the left edge of the
+     *   containing block to the left margin edge of a hypothetical box that would
+     *   have been the first box of the element if its 'position' property had
+     *   been 'static' and 'float' had been 'none'. The value is negative if the
+     *   hypothetical box is to the left of the containing block.
+     * * The static position for 'right' is the distance from the right edge of the
+     *   containing block to the right margin edge of the same hypothetical box as
+     *   above. The value is positive if the hypothetical box is to the left of the
+     *   containing block's edge.
+     *
+     * But rather than actually calculating the dimensions of that hypothetical box,
+     * user agents are free to make a guess at its probable position.
+     *
+     * For the purposes of calculating the static position, the containing block of
+     * fixed positioned elements is the initial containing block instead of the
+     * viewport, and all scrollable boxes should be assumed to be scrolled to their
+     * origin.
+    \*---------------------------------------------------------------------------*/
+
+    // see FIXME 2
+    // Calculate the static distance if needed.
+    if (left.isAuto() && right.isAuto()) {
+        if (containerDirection == LTR) {
+            // 'staticX' should already have been set through layout of the parent.
+            int staticPosition = staticX() - containerBlock->borderLeft();
+            for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent())
+                staticPosition += po->xPos();
+            left.setValue(Fixed, staticPosition);
+        } else {
+            RenderObject* po = parent();
+            // 'staticX' should already have been set through layout of the parent.
+            int staticPosition = staticX() + containerWidth + containerBlock->borderRight() - po->width();
+            for (; po && po != containerBlock; po = po->parent())
+                staticPosition -= po->xPos();
+            right.setValue(Fixed, staticPosition);
+        }
+    }
+
+    // Calculate constraint equation values for 'width' case.
+    calcAbsoluteHorizontalValues(style()->width(), containerBlock, containerDirection,
+                                 containerWidth, bordersPlusPadding,
+                                 left, right, marginLeft, marginRight,
+                                 m_width, m_marginLeft, m_marginRight, m_x);
+
+    // Calculate constraint equation values for 'max-width' case.
+    if (!style()->maxWidth().isUndefined()) {
+        int maxWidth;
+        int maxMarginLeft;
+        int maxMarginRight;
+        int maxXPos;
+
+        calcAbsoluteHorizontalValues(style()->maxWidth(), containerBlock, containerDirection,
+                                     containerWidth, bordersPlusPadding,
+                                     left, right, marginLeft, marginRight,
+                                     maxWidth, maxMarginLeft, maxMarginRight, maxXPos);
+
+        if (m_width > maxWidth) {
+            m_width = maxWidth;
+            m_marginLeft = maxMarginLeft;
+            m_marginRight = maxMarginRight;
+            m_x = maxXPos;
+        }
+    }
+
+    // Calculate constraint equation values for 'min-width' case.
+    if (!style()->minWidth().isZero()) {
+        int minWidth;
+        int minMarginLeft;
+        int minMarginRight;
+        int minXPos;
+
+        calcAbsoluteHorizontalValues(style()->minWidth(), containerBlock, containerDirection,
+                                     containerWidth, bordersPlusPadding,
+                                     left, right, marginLeft, marginRight,
+                                     minWidth, minMarginLeft, minMarginRight, minXPos);
+
+        if (m_width < minWidth) {
+            m_width = minWidth;
+            m_marginLeft = minMarginLeft;
+            m_marginRight = minMarginRight;
+            m_x = minXPos;
+        }
+    }
+
+    if (stretchesToMinIntrinsicWidth() && m_width < minPrefWidth() - bordersPlusPadding)
+        calcAbsoluteHorizontalValues(Length(minPrefWidth() - bordersPlusPadding, Fixed), containerBlock, containerDirection,
+                                     containerWidth, bordersPlusPadding,
+                                     left, right, marginLeft, marginRight,
+                                     m_width, m_marginLeft, m_marginRight, m_x);
+
+    // Put m_width into correct form.
+    m_width += bordersPlusPadding;
+}
+
+void RenderBox::calcAbsoluteHorizontalValues(Length width, const RenderObject* containerBlock, TextDirection containerDirection,
+                                             const int containerWidth, const int bordersPlusPadding,
+                                             const Length left, const Length right, const Length marginLeft, const Length marginRight,
+                                             int& widthValue, int& marginLeftValue, int& marginRightValue, int& xPos)
+{
+    // 'left' and 'right' cannot both be 'auto' because one would of been
+    // converted to the static postion already
+    ASSERT(!(left.isAuto() && right.isAuto()));
+
+    int leftValue = 0;
+
+    bool widthIsAuto = width.isIntrinsicOrAuto();
+    bool leftIsAuto = left.isAuto();
+    bool rightIsAuto = right.isAuto();
+
+    if (!leftIsAuto && !widthIsAuto && !rightIsAuto) {
+        /*-----------------------------------------------------------------------*\
+         * If none of the three is 'auto': If both 'margin-left' and 'margin-
+         * right' are 'auto', solve the equation under the extra constraint that
+         * the two margins get equal values, unless this would make them negative,
+         * in which case when direction of the containing block is 'ltr' ('rtl'),
+         * set 'margin-left' ('margin-right') to zero and solve for 'margin-right'
+         * ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto',
+         * solve the equation for that value. If the values are over-constrained,
+         * ignore the value for 'left' (in case the 'direction' property of the
+         * containing block is 'rtl') or 'right' (in case 'direction' is 'ltr')
+         * and solve for that value.
+        \*-----------------------------------------------------------------------*/
+        // NOTE:  It is not necessary to solve for 'right' in the over constrained
+        // case because the value is not used for any further calculations.
+
+        leftValue = left.calcValue(containerWidth);
+        widthValue = calcContentBoxWidth(width.calcValue(containerWidth));
+
+        const int availableSpace = containerWidth - (leftValue + widthValue + right.calcValue(containerWidth) + bordersPlusPadding);
+
+        // Margins are now the only unknown
+        if (marginLeft.isAuto() && marginRight.isAuto()) {
+            // Both margins auto, solve for equality
+            if (availableSpace >= 0) {
+                marginLeftValue = availableSpace / 2; // split the diference
+                marginRightValue = availableSpace - marginLeftValue;  // account for odd valued differences
+            } else {
+                // see FIXME 1
+                if (containerDirection == LTR) {
+                    marginLeftValue = 0;
+                    marginRightValue = availableSpace; // will be negative
+                } else {
+                    marginLeftValue = availableSpace; // will be negative
+                    marginRightValue = 0;
+                }
+            }
+        } else if (marginLeft.isAuto()) {
+            // Solve for left margin
+            marginRightValue = marginRight.calcValue(containerWidth);
+            marginLeftValue = availableSpace - marginRightValue;
+        } else if (marginRight.isAuto()) {
+            // Solve for right margin
+            marginLeftValue = marginLeft.calcValue(containerWidth);
+            marginRightValue = availableSpace - marginLeftValue;
+        } else {
+            // Over-constrained, solve for left if direction is RTL
+            marginLeftValue = marginLeft.calcValue(containerWidth);
+            marginRightValue = marginRight.calcValue(containerWidth);
+
+            // see FIXME 1 -- used to be "this->style()->direction()"
+            if (containerDirection == RTL)
+                leftValue = (availableSpace + leftValue) - marginLeftValue - marginRightValue;
+        }
+    } else {
+        /*--------------------------------------------------------------------*\
+         * Otherwise, set 'auto' values for 'margin-left' and 'margin-right'
+         * to 0, and pick the one of the following six rules that applies.
+         *
+         * 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the
+         *    width is shrink-to-fit. Then solve for 'left'
+         *
+         *              OMIT RULE 2 AS IT SHOULD NEVER BE HIT
+         * ------------------------------------------------------------------
+         * 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if
+         *    the 'direction' property of the containing block is 'ltr' set
+         *    'left' to the static position, otherwise set 'right' to the
+         *    static position. Then solve for 'left' (if 'direction is 'rtl')
+         *    or 'right' (if 'direction' is 'ltr').
+         * ------------------------------------------------------------------
+         *
+         * 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the
+         *    width is shrink-to-fit . Then solve for 'right'
+         * 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve
+         *    for 'left'
+         * 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve
+         *    for 'width'
+         * 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve
+         *    for 'right'
+         *
+         * Calculation of the shrink-to-fit width is similar to calculating the
+         * width of a table cell using the automatic table layout algorithm.
+         * Roughly: calculate the preferred width by formatting the content
+         * without breaking lines other than where explicit line breaks occur,
+         * and also calculate the preferred minimum width, e.g., by trying all
+         * possible line breaks. CSS 2.1 does not define the exact algorithm.
+         * Thirdly, calculate the available width: this is found by solving
+         * for 'width' after setting 'left' (in case 1) or 'right' (in case 3)
+         * to 0.
+         *
+         * Then the shrink-to-fit width is:
+         * min(max(preferred minimum width, available width), preferred width).
+        \*--------------------------------------------------------------------*/
+        // NOTE: For rules 3 and 6 it is not necessary to solve for 'right'
+        // because the value is not used for any further calculations.
+
+        // Calculate margins, 'auto' margins are ignored.
+        marginLeftValue = marginLeft.calcMinValue(containerWidth);
+        marginRightValue = marginRight.calcMinValue(containerWidth);
+
+        const int availableSpace = containerWidth - (marginLeftValue + marginRightValue + bordersPlusPadding);
+
+        // FIXME: Is there a faster way to find the correct case?
+        // Use rule/case that applies.
+        if (leftIsAuto && widthIsAuto && !rightIsAuto) {
+            // RULE 1: (use shrink-to-fit for width, and solve of left)
+            int rightValue = right.calcValue(containerWidth);
+
+            // FIXME: would it be better to have shrink-to-fit in one step?
+            int preferredWidth = maxPrefWidth() - bordersPlusPadding;
+            int preferredMinWidth = minPrefWidth() - bordersPlusPadding;
+            int availableWidth = availableSpace - rightValue;
+            widthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
+            leftValue = availableSpace - (widthValue + rightValue);
+        } else if (!leftIsAuto && widthIsAuto && rightIsAuto) {
+            // RULE 3: (use shrink-to-fit for width, and no need solve of right)
+            leftValue = left.calcValue(containerWidth);
+
+            // FIXME: would it be better to have shrink-to-fit in one step?
+            int preferredWidth = maxPrefWidth() - bordersPlusPadding;
+            int preferredMinWidth = minPrefWidth() - bordersPlusPadding;
+            int availableWidth = availableSpace - leftValue;
+            widthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
+        } else if (leftIsAuto && !width.isAuto() && !rightIsAuto) {
+            // RULE 4: (solve for left)
+            widthValue = calcContentBoxWidth(width.calcValue(containerWidth));
+            leftValue = availableSpace - (widthValue + right.calcValue(containerWidth));
+        } else if (!leftIsAuto && widthIsAuto && !rightIsAuto) {
+            // RULE 5: (solve for width)
+            leftValue = left.calcValue(containerWidth);
+            widthValue = availableSpace - (leftValue + right.calcValue(containerWidth));
+        } else if (!leftIsAuto&& !widthIsAuto && rightIsAuto) {
+            // RULE 6: (no need solve for right)
+            leftValue = left.calcValue(containerWidth);
+            widthValue = calcContentBoxWidth(width.calcValue(containerWidth));
+        }
+    }
+
+    // Use computed values to calculate the horizontal position.
+
+    // FIXME: This hack is needed to calculate the xPos for a 'rtl' relatively
+    // positioned, inline containing block because right now, it is using the xPos
+    // of the first line box when really it should use the last line box.  When
+    // this is fixed elsewhere, this block should be removed.
+    if (containerBlock->isInline() && containerBlock->style()->direction() == RTL) {
+        const RenderFlow* flow = static_cast<const RenderFlow*>(containerBlock);
+        InlineFlowBox* firstLine = flow->firstLineBox();
+        InlineFlowBox* lastLine = flow->lastLineBox();
+        if (firstLine && lastLine && firstLine != lastLine) {
+            xPos = leftValue + marginLeftValue + lastLine->borderLeft() + (lastLine->xPos() - firstLine->xPos());
+            return;
+        }
+    }
+
+    xPos = leftValue + marginLeftValue + containerBlock->borderLeft();
+}
+
+void RenderBox::calcAbsoluteVertical()
+{
+    if (isReplaced()) {
+        calcAbsoluteVerticalReplaced();
+        return;
+    }
+
+    // The following is based off of the W3C Working Draft from April 11, 2006 of
+    // CSS 2.1: Section 10.6.4 "Absolutely positioned, non-replaced elements"
+    // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-non-replaced-height>
+    // (block-style-comments in this function and in calcAbsoluteVerticalValues()
+    // correspond to text from the spec)
+
+
+    // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
+    const RenderObject* containerBlock = container();
+
+    const int containerHeight = containingBlockHeightForPositioned(containerBlock);
+
+    const int bordersPlusPadding = borderTop() + borderBottom() + paddingTop() + paddingBottom();
+    const Length marginTop = style()->marginTop();
+    const Length marginBottom = style()->marginBottom();
+    Length top = style()->top();
+    Length bottom = style()->bottom();
+
+    /*---------------------------------------------------------------------------*\
+     * For the purposes of this section and the next, the term "static position"
+     * (of an element) refers, roughly, to the position an element would have had
+     * in the normal flow. More precisely, the static position for 'top' is the
+     * distance from the top edge of the containing block to the top margin edge
+     * of a hypothetical box that would have been the first box of the element if
+     * its 'position' property had been 'static' and 'float' had been 'none'. The
+     * value is negative if the hypothetical box is above the containing block.
+     *
+     * But rather than actually calculating the dimensions of that hypothetical
+     * box, user agents are free to make a guess at its probable position.
+     *
+     * For the purposes of calculating the static position, the containing block
+     * of fixed positioned elements is the initial containing block instead of
+     * the viewport.
+    \*---------------------------------------------------------------------------*/
+
+    // see FIXME 2
+    // Calculate the static distance if needed.
+    if (top.isAuto() && bottom.isAuto()) {
+        // staticY should already have been set through layout of the parent()
+        int staticTop = staticY() - containerBlock->borderTop();
+        for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
+            if (!po->isTableRow())
+                staticTop += po->yPos();
+        }
+        top.setValue(Fixed, staticTop);
+    }
+
+
+    int height; // Needed to compute overflow.
+
+    // Calculate constraint equation values for 'height' case.
+    calcAbsoluteVerticalValues(style()->height(), containerBlock, containerHeight, bordersPlusPadding,
+                               top, bottom, marginTop, marginBottom,
+                               height, m_marginTop, m_marginBottom, m_y);
+
+    // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
+    // see FIXME 3
+
+    // Calculate constraint equation values for 'max-height' case.
+    if (!style()->maxHeight().isUndefined()) {
+        int maxHeight;
+        int maxMarginTop;
+        int maxMarginBottom;
+        int maxYPos;
+
+        calcAbsoluteVerticalValues(style()->maxHeight(), containerBlock, containerHeight, bordersPlusPadding,
+                                   top, bottom, marginTop, marginBottom,
+                                   maxHeight, maxMarginTop, maxMarginBottom, maxYPos);
+
+        if (height > maxHeight) {
+            height = maxHeight;
+            m_marginTop = maxMarginTop;
+            m_marginBottom = maxMarginBottom;
+            m_y = maxYPos;
+        }
+    }
+
+    // Calculate constraint equation values for 'min-height' case.
+    if (!style()->minHeight().isZero()) {
+        int minHeight;
+        int minMarginTop;
+        int minMarginBottom;
+        int minYPos;
+
+        calcAbsoluteVerticalValues(style()->minHeight(), containerBlock, containerHeight, bordersPlusPadding,
+                                   top, bottom, marginTop, marginBottom,
+                                   minHeight, minMarginTop, minMarginBottom, minYPos);
+
+        if (height < minHeight) {
+            height = minHeight;
+            m_marginTop = minMarginTop;
+            m_marginBottom = minMarginBottom;
+            m_y = minYPos;
+        }
+    }
+
+    // Set final height value.
+    m_height = height + bordersPlusPadding;
+}
+
+void RenderBox::calcAbsoluteVerticalValues(Length height, const RenderObject* containerBlock,
+                                           const int containerHeight, const int bordersPlusPadding,
+                                           const Length top, const Length bottom, const Length marginTop, const Length marginBottom,
+                                           int& heightValue, int& marginTopValue, int& marginBottomValue, int& yPos)
+{
+    // 'top' and 'bottom' cannot both be 'auto' because 'top would of been
+    // converted to the static position in calcAbsoluteVertical()
+    ASSERT(!(top.isAuto() && bottom.isAuto()));
+
+    int contentHeight = m_height - bordersPlusPadding;
+
+    int topValue = 0;
+
+    bool heightIsAuto = height.isAuto();
+    bool topIsAuto = top.isAuto();
+    bool bottomIsAuto = bottom.isAuto();
+
+    // Height is never unsolved for tables.
+    if (isTable()) {
+        height.setValue(Fixed, contentHeight);
+        heightIsAuto = false;
+    }
+
+    if (!topIsAuto && !heightIsAuto && !bottomIsAuto) {
+        /*-----------------------------------------------------------------------*\
+         * If none of the three are 'auto': If both 'margin-top' and 'margin-
+         * bottom' are 'auto', solve the equation under the extra constraint that
+         * the two margins get equal values. If one of 'margin-top' or 'margin-
+         * bottom' is 'auto', solve the equation for that value. If the values
+         * are over-constrained, ignore the value for 'bottom' and solve for that
+         * value.
+        \*-----------------------------------------------------------------------*/
+        // NOTE:  It is not necessary to solve for 'bottom' in the over constrained
+        // case because the value is not used for any further calculations.
+
+        heightValue = calcContentBoxHeight(height.calcValue(containerHeight));
+        topValue = top.calcValue(containerHeight);
+
+        const int availableSpace = containerHeight - (topValue + heightValue + bottom.calcValue(containerHeight) + bordersPlusPadding);
+
+        // Margins are now the only unknown
+        if (marginTop.isAuto() && marginBottom.isAuto()) {
+            // Both margins auto, solve for equality
+            // NOTE: This may result in negative values.
+            marginTopValue = availableSpace / 2; // split the diference
+            marginBottomValue = availableSpace - marginTopValue; // account for odd valued differences
+        } else if (marginTop.isAuto()) {
+            // Solve for top margin
+            marginBottomValue = marginBottom.calcValue(containerHeight);
+            marginTopValue = availableSpace - marginBottomValue;
+        } else if (marginBottom.isAuto()) {
+            // Solve for bottom margin
+            marginTopValue = marginTop.calcValue(containerHeight);
+            marginBottomValue = availableSpace - marginTopValue;
+        } else {
+            // Over-constrained, (no need solve for bottom)
+            marginTopValue = marginTop.calcValue(containerHeight);
+            marginBottomValue = marginBottom.calcValue(containerHeight);
+        }
+    } else {
+        /*--------------------------------------------------------------------*\
+         * Otherwise, set 'auto' values for 'margin-top' and 'margin-bottom'
+         * to 0, and pick the one of the following six rules that applies.
+         *
+         * 1. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then
+         *    the height is based on the content, and solve for 'top'.
+         *
+         *              OMIT RULE 2 AS IT SHOULD NEVER BE HIT
+         * ------------------------------------------------------------------
+         * 2. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then
+         *    set 'top' to the static position, and solve for 'bottom'.
+         * ------------------------------------------------------------------
+         *
+         * 3. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then
+         *    the height is based on the content, and solve for 'bottom'.
+         * 4. 'top' is 'auto', 'height' and 'bottom' are not 'auto', and
+         *    solve for 'top'.
+         * 5. 'height' is 'auto', 'top' and 'bottom' are not 'auto', and
+         *    solve for 'height'.
+         * 6. 'bottom' is 'auto', 'top' and 'height' are not 'auto', and
+         *    solve for 'bottom'.
+        \*--------------------------------------------------------------------*/
+        // NOTE: For rules 3 and 6 it is not necessary to solve for 'bottom'
+        // because the value is not used for any further calculations.
+
+        // Calculate margins, 'auto' margins are ignored.
+        marginTopValue = marginTop.calcMinValue(containerHeight);
+        marginBottomValue = marginBottom.calcMinValue(containerHeight);
+
+        const int availableSpace = containerHeight - (marginTopValue + marginBottomValue + bordersPlusPadding);
+
+        // Use rule/case that applies.
+        if (topIsAuto && heightIsAuto && !bottomIsAuto) {
+            // RULE 1: (height is content based, solve of top)
+            heightValue = contentHeight;
+            topValue = availableSpace - (heightValue + bottom.calcValue(containerHeight));
+        } else if (!topIsAuto && heightIsAuto && bottomIsAuto) {
+            // RULE 3: (height is content based, no need solve of bottom)
+            topValue = top.calcValue(containerHeight);
+            heightValue = contentHeight;
+        } else if (topIsAuto && !heightIsAuto && !bottomIsAuto) {
+            // RULE 4: (solve of top)
+            heightValue = calcContentBoxHeight(height.calcValue(containerHeight));
+            topValue = availableSpace - (heightValue + bottom.calcValue(containerHeight));
+        } else if (!topIsAuto && heightIsAuto && !bottomIsAuto) {
+            // RULE 5: (solve of height)
+            topValue = top.calcValue(containerHeight);
+            heightValue = max(0, availableSpace - (topValue + bottom.calcValue(containerHeight)));
+        } else if (!topIsAuto && !heightIsAuto && bottomIsAuto) {
+            // RULE 6: (no need solve of bottom)
+            heightValue = calcContentBoxHeight(height.calcValue(containerHeight));
+            topValue = top.calcValue(containerHeight);
+        }
+    }
+
+    // Use computed values to calculate the vertical position.
+    yPos = topValue + marginTopValue + containerBlock->borderTop();
+}
+
+void RenderBox::calcAbsoluteHorizontalReplaced()
+{
+    // The following is based off of the W3C Working Draft from April 11, 2006 of
+    // CSS 2.1: Section 10.3.8 "Absolutly positioned, replaced elements"
+    // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-width>
+    // (block-style-comments in this function correspond to text from the spec and
+    // the numbers correspond to numbers in spec)
+
+    // We don't use containingBlock(), since we may be positioned by an enclosing
+    // relative positioned inline.
+    const RenderObject* containerBlock = container();
+
+    const int containerWidth = containingBlockWidthForPositioned(containerBlock);
+
+    // To match WinIE, in quirks mode use the parent's 'direction' property
+    // instead of the the container block's.
+    TextDirection containerDirection = (style()->htmlHacks()) ? parent()->style()->direction() : containerBlock->style()->direction();
+
+    // Variables to solve.
+    Length left = style()->left();
+    Length right = style()->right();
+    Length marginLeft = style()->marginLeft();
+    Length marginRight = style()->marginRight();
+
+
+    /*-----------------------------------------------------------------------*\
+     * 1. The used value of 'width' is determined as for inline replaced
+     *    elements.
+    \*-----------------------------------------------------------------------*/
+    // NOTE: This value of width is FINAL in that the min/max width calculations
+    // are dealt with in calcReplacedWidth().  This means that the steps to produce
+    // correct max/min in the non-replaced version, are not necessary.
+    m_width = calcReplacedWidth() + borderLeft() + borderRight() + paddingLeft() + paddingRight();
+    const int availableSpace = containerWidth - m_width;
+
+    /*-----------------------------------------------------------------------*\
+     * 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
+     *    of the containing block is 'ltr', set 'left' to the static position;
+     *    else if 'direction' is 'rtl', set 'right' to the static position.
+    \*-----------------------------------------------------------------------*/
+    // see FIXME 2
+    if (left.isAuto() && right.isAuto()) {
+        // see FIXME 1
+        if (containerDirection == LTR) {
+            // 'staticX' should already have been set through layout of the parent.
+            int staticPosition = staticX() - containerBlock->borderLeft();
+            for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent())
+                staticPosition += po->xPos();
+            left.setValue(Fixed, staticPosition);
+        } else {
+            RenderObject* po = parent();
+            // 'staticX' should already have been set through layout of the parent.
+            int staticPosition = staticX() + containerWidth + containerBlock->borderRight() - po->width();
+            for (; po && po != containerBlock; po = po->parent())
+                staticPosition -= po->xPos();
+            right.setValue(Fixed, staticPosition);
+        }
+    }
+
+    /*-----------------------------------------------------------------------*\
+     * 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
+     *    or 'margin-right' with '0'.
+    \*-----------------------------------------------------------------------*/
+    if (left.isAuto() || right.isAuto()) {
+        if (marginLeft.isAuto())
+            marginLeft.setValue(Fixed, 0);
+        if (marginRight.isAuto())
+            marginRight.setValue(Fixed, 0);
+    }
+
+    /*-----------------------------------------------------------------------*\
+     * 4. If at this point both 'margin-left' and 'margin-right' are still
+     *    'auto', solve the equation under the extra constraint that the two
+     *    margins must get equal values, unless this would make them negative,
+     *    in which case when the direction of the containing block is 'ltr'
+     *    ('rtl'), set 'margin-left' ('margin-right') to zero and solve for
+     *    'margin-right' ('margin-left').
+    \*-----------------------------------------------------------------------*/
+    int leftValue = 0;
+    int rightValue = 0;
+
+    if (marginLeft.isAuto() && marginRight.isAuto()) {
+        // 'left' and 'right' cannot be 'auto' due to step 3
+        ASSERT(!(left.isAuto() && right.isAuto()));
+
+        leftValue = left.calcValue(containerWidth);
+        rightValue = right.calcValue(containerWidth);
+
+        int difference = availableSpace - (leftValue + rightValue);
+        if (difference > 0) {
+            m_marginLeft = difference / 2; // split the diference
+            m_marginRight = difference - m_marginLeft; // account for odd valued differences
+        } else {
+            // see FIXME 1
+            if (containerDirection == LTR) {
+                m_marginLeft = 0;
+                m_marginRight = difference;  // will be negative
+            } else {
+                m_marginLeft = difference;  // will be negative
+                m_marginRight = 0;
+            }
+        }
+
+    /*-----------------------------------------------------------------------*\
+     * 5. If at this point there is an 'auto' left, solve the equation for
+     *    that value.
+    \*-----------------------------------------------------------------------*/
+    } else if (left.isAuto()) {
+        m_marginLeft = marginLeft.calcValue(containerWidth);
+        m_marginRight = marginRight.calcValue(containerWidth);
+        rightValue = right.calcValue(containerWidth);
+
+        // Solve for 'left'
+        leftValue = availableSpace - (rightValue + m_marginLeft + m_marginRight);
+    } else if (right.isAuto()) {
+        m_marginLeft = marginLeft.calcValue(containerWidth);
+        m_marginRight = marginRight.calcValue(containerWidth);
+        leftValue = left.calcValue(containerWidth);
+
+        // Solve for 'right'
+        rightValue = availableSpace - (leftValue + m_marginLeft + m_marginRight);
+    } else if (marginLeft.isAuto()) {
+        m_marginRight = marginRight.calcValue(containerWidth);
+        leftValue = left.calcValue(containerWidth);
+        rightValue = right.calcValue(containerWidth);
+
+        // Solve for 'margin-left'
+        m_marginLeft = availableSpace - (leftValue + rightValue + m_marginRight);
+    } else if (marginRight.isAuto()) {
+        m_marginLeft = marginLeft.calcValue(containerWidth);
+        leftValue = left.calcValue(containerWidth);
+        rightValue = right.calcValue(containerWidth);
+
+        // Solve for 'margin-right'
+        m_marginRight = availableSpace - (leftValue + rightValue + m_marginLeft);
+    } else {
+        // Nothing is 'auto', just calculate the values.
+        m_marginLeft = marginLeft.calcValue(containerWidth);
+        m_marginRight = marginRight.calcValue(containerWidth);
+        rightValue = right.calcValue(containerWidth);
+        leftValue = left.calcValue(containerWidth);
+    }
+
+    /*-----------------------------------------------------------------------*\
+     * 6. If at this point the values are over-constrained, ignore the value
+     *    for either 'left' (in case the 'direction' property of the
+     *    containing block is 'rtl') or 'right' (in case 'direction' is
+     *    'ltr') and solve for that value.
+    \*-----------------------------------------------------------------------*/
+    // NOTE:  It is not necessary to solve for 'right' when the direction is
+    // LTR because the value is not used.
+    int totalWidth = m_width + leftValue + rightValue +  m_marginLeft + m_marginRight;
+    if (totalWidth > containerWidth && (containerDirection == RTL))
+        leftValue = containerWidth - (totalWidth - leftValue);
+
+    // Use computed values to calculate the horizontal position.
+
+    // FIXME: This hack is needed to calculate the xPos for a 'rtl' relatively
+    // positioned, inline containing block because right now, it is using the xPos
+    // of the first line box when really it should use the last line box.  When
+    // this is fixed elsewhere, this block should be removed.
+    if (containerBlock->isInline() && containerBlock->style()->direction() == RTL) {
+        const RenderFlow* flow = static_cast<const RenderFlow*>(containerBlock);
+        InlineFlowBox* firstLine = flow->firstLineBox();
+        InlineFlowBox* lastLine = flow->lastLineBox();
+        if (firstLine && lastLine && firstLine != lastLine) {
+            m_x = leftValue + m_marginLeft + lastLine->borderLeft() + (lastLine->xPos() - firstLine->xPos());
+            return;
+        }
+    }
+
+    m_x = leftValue + m_marginLeft + containerBlock->borderLeft();
+}
+
+void RenderBox::calcAbsoluteVerticalReplaced()
+{
+    // The following is based off of the W3C Working Draft from April 11, 2006 of
+    // CSS 2.1: Section 10.6.5 "Absolutly positioned, replaced elements"
+    // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-height>
+    // (block-style-comments in this function correspond to text from the spec and
+    // the numbers correspond to numbers in spec)
+
+    // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
+    const RenderObject* containerBlock = container();
+
+    const int containerHeight = containingBlockHeightForPositioned(containerBlock);
+
+    // Variables to solve.
+    Length top = style()->top();
+    Length bottom = style()->bottom();
+    Length marginTop = style()->marginTop();
+    Length marginBottom = style()->marginBottom();
+
+
+    /*-----------------------------------------------------------------------*\
+     * 1. The used value of 'height' is determined as for inline replaced
+     *    elements.
+    \*-----------------------------------------------------------------------*/
+    // NOTE: This value of height is FINAL in that the min/max height calculations
+    // are dealt with in calcReplacedHeight().  This means that the steps to produce
+    // correct max/min in the non-replaced version, are not necessary.
+    m_height = calcReplacedHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom();
+    const int availableSpace = containerHeight - m_height;
+
+    /*-----------------------------------------------------------------------*\
+     * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
+     *    with the element's static position.
+    \*-----------------------------------------------------------------------*/
+    // see FIXME 2
+    if (top.isAuto() && bottom.isAuto()) {
+        // staticY should already have been set through layout of the parent().
+        int staticTop = staticY() - containerBlock->borderTop();
+        for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
+            if (!po->isTableRow())
+                staticTop += po->yPos();
+        }
+        top.setValue(Fixed, staticTop);
+    }
+
+    /*-----------------------------------------------------------------------*\
+     * 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or
+     *    'margin-bottom' with '0'.
+    \*-----------------------------------------------------------------------*/
+    // FIXME: The spec. says that this step should only be taken when bottom is
+    // auto, but if only top is auto, this makes step 4 impossible.
+    if (top.isAuto() || bottom.isAuto()) {
+        if (marginTop.isAuto())
+            marginTop.setValue(Fixed, 0);
+        if (marginBottom.isAuto())
+            marginBottom.setValue(Fixed, 0);
+    }
+
+    /*-----------------------------------------------------------------------*\
+     * 4. If at this point both 'margin-top' and 'margin-bottom' are still
+     *    'auto', solve the equation under the extra constraint that the two
+     *    margins must get equal values.
+    \*-----------------------------------------------------------------------*/
+    int topValue = 0;
+    int bottomValue = 0;
+
+    if (marginTop.isAuto() && marginBottom.isAuto()) {
+        // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combinded.
+        ASSERT(!(top.isAuto() || bottom.isAuto()));
+
+        topValue = top.calcValue(containerHeight);
+        bottomValue = bottom.calcValue(containerHeight);
+
+        int difference = availableSpace - (topValue + bottomValue);
+        // NOTE: This may result in negative values.
+        m_marginTop =  difference / 2; // split the difference
+        m_marginBottom = difference - m_marginTop; // account for odd valued differences
+
+    /*-----------------------------------------------------------------------*\
+     * 5. If at this point there is only one 'auto' left, solve the equation
+     *    for that value.
+    \*-----------------------------------------------------------------------*/
+    } else if (top.isAuto()) {
+        m_marginTop = marginTop.calcValue(containerHeight);
+        m_marginBottom = marginBottom.calcValue(containerHeight);
+        bottomValue = bottom.calcValue(containerHeight);
+
+        // Solve for 'top'
+        topValue = availableSpace - (bottomValue + m_marginTop + m_marginBottom);
+    } else if (bottom.isAuto()) {
+        m_marginTop = marginTop.calcValue(containerHeight);
+        m_marginBottom = marginBottom.calcValue(containerHeight);
+        topValue = top.calcValue(containerHeight);
+
+        // Solve for 'bottom'
+        // NOTE: It is not necessary to solve for 'bottom' because we don't ever
+        // use the value.
+    } else if (marginTop.isAuto()) {
+        m_marginBottom = marginBottom.calcValue(containerHeight);
+        topValue = top.calcValue(containerHeight);
+        bottomValue = bottom.calcValue(containerHeight);
+
+        // Solve for 'margin-top'
+        m_marginTop = availableSpace - (topValue + bottomValue + m_marginBottom);
+    } else if (marginBottom.isAuto()) {
+        m_marginTop = marginTop.calcValue(containerHeight);
+        topValue = top.calcValue(containerHeight);
+        bottomValue = bottom.calcValue(containerHeight);
+
+        // Solve for 'margin-bottom'
+        m_marginBottom = availableSpace - (topValue + bottomValue + m_marginTop);
+    } else {
+        // Nothing is 'auto', just calculate the values.
+        m_marginTop = marginTop.calcValue(containerHeight);
+        m_marginBottom = marginBottom.calcValue(containerHeight);
+        topValue = top.calcValue(containerHeight);
+        // NOTE: It is not necessary to solve for 'bottom' because we don't ever
+        // use the value.
+     }
+
+    /*-----------------------------------------------------------------------*\
+     * 6. If at this point the values are over-constrained, ignore the value
+     *    for 'bottom' and solve for that value.
+    \*-----------------------------------------------------------------------*/
+    // NOTE: It is not necessary to do this step because we don't end up using
+    // the value of 'bottom' regardless of whether the values are over-constrained
+    // or not.
+
+    // Use computed values to calculate the vertical position.
+    m_y = topValue + m_marginTop + containerBlock->borderTop();
+}
+
+IntRect RenderBox::caretRect(InlineBox* box, int caretOffset, int* extraWidthToEndOfLine)
+{
+    // VisiblePositions at offsets inside containers either a) refer to the positions before/after
+    // those containers (tables and select elements) or b) refer to the position inside an empty block.
+    // They never refer to children.
+    // FIXME: Paint the carets inside empty blocks differently than the carets before/after elements.
+
+    // FIXME: What about border and padding?
+    const int caretWidth = 1;
+    IntRect rect(xPos(), yPos(), caretWidth, m_height);
+    TextDirection direction = box ? box->direction() : style()->direction();
+
+    if ((!caretOffset) ^ (direction == LTR))
+        rect.move(IntSize(m_width - caretWidth, 0));
+
+    if (box) {
+        RootInlineBox* rootBox = box->root();
+        int top = rootBox->topOverflow();
+        rect.setY(top);
+        rect.setHeight(rootBox->bottomOverflow() - top);
+    }
+
+    // If height of box is smaller than font height, use the latter one,
+    // otherwise the caret might become invisible.
+    //
+    // Also, if the box is not a replaced element, always use the font height.
+    // This prevents the "big caret" bug described in:
+    // <rdar://problem/3777804> Deleting all content in a document can result in giant tall-as-window insertion point
+    //
+    // FIXME: ignoring :first-line, missing good reason to take care of
+    int fontHeight = style()->font().height();
+    if (fontHeight > rect.height() || !isReplaced() && !isTable())
+        rect.setHeight(fontHeight);
+
+    RenderObject* cb = containingBlock();
+    int cbx, cby;
+    if (!cb || !cb->absolutePosition(cbx, cby))
+        // No point returning a relative position.
+        return IntRect();
+
+    if (extraWidthToEndOfLine)
+        *extraWidthToEndOfLine = xPos() + m_width - rect.right();
+
+    rect.move(cbx, cby);
+    return rect;
+}
+
+int RenderBox::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    if (!includeSelf || !m_width)
+        return 0;
+    int bottom = m_height;
+    if (isRelPositioned())
+        bottom += relativePositionOffsetY();
+    return bottom;
+}
+
+int RenderBox::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    if (!includeSelf || !m_height)
+        return 0;
+    int right = m_width;
+    if (isRelPositioned())
+        right += relativePositionOffsetX();
+    return right;
+}
+
+int RenderBox::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    if (!includeSelf || !m_height)
+        return m_width;
+    int left = 0;
+    if (isRelPositioned())
+        left += relativePositionOffsetX();
+    return left;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h
new file mode 100644
index 0000000..133ae37
--- /dev/null
+++ b/WebCore/rendering/RenderBox.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderBox_h
+#define RenderBox_h
+
+#include "RenderObject.h"
+
+namespace WebCore {
+
+    enum WidthType { Width, MinWidth, MaxWidth };
+
+class RenderBox : public RenderObject {
+public:
+    RenderBox(Node*);
+    virtual ~RenderBox();
+
+    virtual const char* renderName() const { return "RenderBox"; }
+
+    virtual void paint(PaintInfo&, int tx, int ty);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+    virtual void destroy();
+
+    virtual int minPrefWidth() const;
+    virtual int maxPrefWidth() const;
+
+    virtual int overrideSize() const;
+    virtual int overrideWidth() const;
+    virtual int overrideHeight() const;
+    virtual void setOverrideSize(int);
+
+    virtual bool absolutePosition(int& x, int& y, bool fixed = false) const;
+
+    virtual int xPos() const { return m_x; }
+    virtual int yPos() const { return m_y; }
+    virtual void setPos(int x, int y);
+
+    virtual int width() const { return m_width; }
+    virtual int height() const { return m_height; }
+    virtual void setWidth(int width) { m_width = width; }
+    virtual void setHeight(int height) { m_height = height; }
+
+    virtual int marginTop() const { return m_marginTop; }
+    virtual int marginBottom() const { return m_marginBottom; }
+    virtual int marginLeft() const { return m_marginLeft; }
+    virtual int marginRight() const { return m_marginRight; }
+
+    virtual IntRect borderBox() const { return IntRect(0, -borderTopExtra(), width(), height() + borderTopExtra() + borderBottomExtra()); }
+
+    int calcBorderBoxWidth(int width) const;
+    int calcBorderBoxHeight(int height) const;
+    int calcContentBoxWidth(int width) const;
+    int calcContentBoxHeight(int height) const;
+
+    virtual void borderFitAdjust(int& x, int& w) const {}; // Shrink the box in which the border paints if border-fit is set.
+
+    // This method is now public so that centered objects like tables that are
+    // shifted right by left-aligned floats can recompute their left and
+    // right margins (so that they can remain centered after being
+    // shifted. -dwh
+    void calcHorizontalMargins(const Length& marginLeft, const Length& marginRight, int containerWidth);
+
+    virtual void position(InlineBox*);
+
+    virtual void dirtyLineBoxes(bool fullLayout, bool isRootLineBox = false);
+
+    // For inline replaced elements, this function returns the inline box that owns us.  Enables
+    // the replaced RenderObject to quickly determine what line it is contained on and to easily
+    // iterate over structures on the line.
+    virtual InlineBox* inlineBoxWrapper() const { return m_inlineBoxWrapper; }
+    virtual void setInlineBoxWrapper(InlineBox* boxWrapper) { m_inlineBoxWrapper = boxWrapper; }
+    virtual void deleteLineBoxWrapper();
+
+    virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+    virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+    virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+
+    virtual IntRect absoluteClippedOverflowRect();
+    virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed = false);
+    IntSize offsetForPositionedInContainer(RenderObject*) const;
+
+    virtual void repaintDuringLayoutIfMoved(const IntRect&);
+
+    virtual int containingBlockWidth() const;
+
+    virtual void calcWidth();
+    virtual void calcHeight();
+
+    bool stretchesToViewHeight() const
+    {
+        return style()->htmlHacks() && style()->height().isAuto() && !isFloatingOrPositioned() && (isRoot() || isBody());
+    }
+
+    virtual IntSize intrinsicSize() const { return IntSize(); }
+
+    // Whether or not the element shrinks to its intrinsic width (rather than filling the width
+    // of a containing block).  HTML4 buttons, <select>s, <input>s, legends, and floating/compact elements do this.
+    bool sizesToIntrinsicWidth(WidthType) const;
+    virtual bool stretchesToMinIntrinsicWidth() const { return false; }
+
+    int calcWidthUsing(WidthType, int containerWidth);
+    int calcHeightUsing(const Length& height);
+    int calcReplacedWidthUsing(Length width) const;
+    int calcReplacedHeightUsing(Length height) const;
+
+    virtual int calcReplacedWidth(bool includeMaxWidth = true) const;
+    virtual int calcReplacedHeight() const;
+
+    int calcPercentageHeight(const Length& height);
+
+    virtual int availableHeight() const;
+    int availableHeightUsing(const Length&) const;
+
+    void calcVerticalMargins();
+
+    int relativePositionOffsetX() const;
+    int relativePositionOffsetY() const;
+
+    virtual RenderLayer* layer() const { return m_layer; }
+
+    virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
+
+    virtual void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, int clipY, int clipHeight,
+                                        int tx, int ty, int width, int height, InlineFlowBox* = 0, CompositeOperator = CompositeSourceOver);
+    IntSize calculateBackgroundSize(const FillLayer*, int scaledWidth, int scaledHeight) const;
+
+    virtual int staticX() const;
+    virtual int staticY() const;
+    virtual void setStaticX(int staticX);
+    virtual void setStaticY(int staticY);
+
+    virtual IntRect getOverflowClipRect(int tx, int ty);
+    virtual IntRect getClipRect(int tx, int ty);
+
+    virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
+    virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
+    virtual void imageChanged(WrappedImagePtr);
+
+    // Called when a positioned object moves but doesn't change size.  A simplified layout is done
+    // that just updates the object's position.
+    virtual void tryLayoutDoingPositionedMovementOnly()
+    {
+        int oldWidth = m_width;
+        calcWidth();
+        // If we shrink to fit our width may have changed, so we still need full layout.
+        if (oldWidth != m_width)
+            return;
+        calcHeight();
+        setNeedsLayout(false);
+    }
+
+    virtual IntRect maskClipRect();
+    
+protected:
+    virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+    void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, int clipY, int clipHeight, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver);
+    void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, int clipY, int clipHeight, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver);
+
+    void paintMaskImages(const PaintInfo&, int clipY, int clipHeight, int tx, int ty, int width, int height);
+
+#if PLATFORM(MAC)
+    void paintCustomHighlight(int tx, int ty, const AtomicString& type, bool behindText);
+#endif
+
+    void calcAbsoluteHorizontal();
+    
+    virtual bool shouldCalculateSizeAsReplaced() const { return isReplaced() && !isInlineBlockOrInlineTable(); }
+
+private:
+    void paintRootBoxDecorations(PaintInfo&, int tx, int ty);
+    // Returns true if we did a full repaint
+    bool repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer* layers, bool drawingBackground);
+
+    void calculateBackgroundImageGeometry(const FillLayer*, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize);
+    
+    int containingBlockWidthForPositioned(const RenderObject* containingBlock) const;
+    int containingBlockHeightForPositioned(const RenderObject* containingBlock) const;
+
+    void calcAbsoluteVertical();
+    void calcAbsoluteHorizontalValues(Length width, const RenderObject* cb, TextDirection containerDirection,
+                                      int containerWidth, int bordersPlusPadding,
+                                      Length left, Length right, Length marginLeft, Length marginRight,
+                                      int& widthValue, int& marginLeftValue, int& marginRightValue, int& xPos);
+    void calcAbsoluteVerticalValues(Length height, const RenderObject* cb,
+                                    int containerHeight, int bordersPlusPadding,
+                                    Length top, Length bottom, Length marginTop, Length marginBottom,
+                                    int& heightValue, int& marginTopValue, int& marginBottomValue, int& yPos);
+
+    void calcAbsoluteVerticalReplaced();
+    void calcAbsoluteHorizontalReplaced();
+
+    // This function calculates the minimum and maximum preferred widths for an object.
+    // These values are used in shrink-to-fit layout systems.
+    // These include tables, positioned objects, floats and flexible boxes.
+    virtual void calcPrefWidths() = 0;
+
+protected:
+    // The width/height of the contents + borders + padding.
+    int m_width;
+    int m_height;
+
+#ifdef ANDROID_LAYOUT
+    int m_visibleWidth;
+#endif
+
+    int m_x;
+    int m_y;
+
+    int m_marginLeft;
+    int m_marginRight;
+    int m_marginTop;
+    int m_marginBottom;
+
+    // The preferred width of the element if it were to break its lines at every possible opportunity.
+    int m_minPrefWidth;
+    
+    // The preferred width of the element if it never breaks any lines at all.
+    int m_maxPrefWidth;
+
+    // A pointer to our layer if we have one.
+    RenderLayer* m_layer;
+
+    // For inline replaced elements, the inline box that owns us.
+    InlineBox* m_inlineBoxWrapper;
+
+private:
+    // Used to store state between styleWillChange and styleDidChange
+    static bool s_wasFloating;
+    static bool s_hadOverflowClip;
+};
+
+} // namespace WebCore
+
+#endif // RenderBox_h
diff --git a/WebCore/rendering/RenderButton.cpp b/WebCore/rendering/RenderButton.cpp
new file mode 100644
index 0000000..cbde565
--- /dev/null
+++ b/WebCore/rendering/RenderButton.cpp
@@ -0,0 +1,155 @@
+/**
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2005 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderButton.h"
+
+#include "Document.h"
+#include "GraphicsContext.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "RenderTextFragment.h"
+#include "RenderTheme.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderButton::RenderButton(Node* node)
+    : RenderFlexibleBox(node)
+    , m_buttonText(0)
+    , m_inner(0)
+    , m_default(false)
+{
+}
+
+void RenderButton::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    if (!m_inner) {
+        // Create an anonymous block.
+        ASSERT(!firstChild());
+        m_inner = createAnonymousBlock();
+        m_inner->style()->setBoxFlex(1.0f);
+        RenderFlexibleBox::addChild(m_inner);
+    }
+    
+    m_inner->addChild(newChild, beforeChild);
+}
+
+void RenderButton::removeChild(RenderObject* oldChild)
+{
+    if (oldChild == m_inner || !m_inner) {
+        RenderFlexibleBox::removeChild(oldChild);
+        m_inner = 0;
+    } else
+        m_inner->removeChild(oldChild);
+}
+
+void RenderButton::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+{
+    if (m_inner) {
+        // RenderBlock::setStyle is going to apply a new style to the inner block, which
+        // will have the initial box flex value, 0. The current value is 1, because we set
+        // it right below. Here we change it back to 0 to avoid getting a spurious layout hint
+        // because of the difference.
+        m_inner->style()->setBoxFlex(0);
+    }
+    RenderBlock::styleWillChange(diff, newStyle);
+}
+
+void RenderButton::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+
+    if (m_buttonText)
+        m_buttonText->setStyle(style());
+    if (m_inner) // RenderBlock handled updating the anonymous block's style.
+        m_inner->style()->setBoxFlex(1.0f);
+    setReplaced(isInline());
+
+    if (!m_default && theme()->isDefault(this)) {
+        if (!m_timer)
+            m_timer.set(new Timer<RenderButton>(this, &RenderButton::timerFired));
+        m_timer->startRepeating(0.03);
+        m_default = true;
+    } else if (m_default && !theme()->isDefault(this)) {
+        m_default = false;
+        m_timer.clear();
+    }
+}
+
+void RenderButton::updateFromElement()
+{
+    // If we're an input element, we may need to change our button text.
+    if (element()->hasTagName(inputTag)) {
+        HTMLInputElement* input = static_cast<HTMLInputElement*>(element());
+        String value = input->valueWithDefault();
+        setText(value);
+    }
+}
+
+bool RenderButton::canHaveChildren() const
+{
+    // Input elements can't have children, but button elements can.  We'll
+    // write the code assuming any other button types that might emerge in the future
+    // can also have children.
+    return !element()->hasTagName(inputTag);
+}
+
+void RenderButton::setText(const String& str)
+{
+    if (str.isEmpty()) {
+        if (m_buttonText) {
+            m_buttonText->destroy();
+            m_buttonText = 0;
+        }
+    } else {
+        if (m_buttonText)
+            m_buttonText->setText(str.impl());
+        else {
+            m_buttonText = new (renderArena()) RenderTextFragment(document(), str.impl());
+            m_buttonText->setStyle(style());
+            addChild(m_buttonText);
+        }
+    }
+}
+
+void RenderButton::updateBeforeAfterContent(RenderStyle::PseudoId type)
+{
+    if (m_inner)
+        m_inner->updateBeforeAfterContentForContainer(type, this);
+    else
+        updateBeforeAfterContentForContainer(type, this);
+}
+
+IntRect RenderButton::controlClipRect(int tx, int ty) const
+{
+    // Clip to the padding box to at least give content the extra padding space.
+    return IntRect(tx + borderLeft(), ty + borderTop(), m_width - borderLeft() - borderRight(), m_height - borderTop() - borderBottom());
+}
+
+void RenderButton::timerFired(Timer<RenderButton>*)
+{
+    repaint();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderButton.h b/WebCore/rendering/RenderButton.h
new file mode 100644
index 0000000..a176c8d
--- /dev/null
+++ b/WebCore/rendering/RenderButton.h
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2005 Apple Computer
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderButton_h
+#define RenderButton_h
+
+#include "RenderFlexibleBox.h"
+#include "Timer.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class RenderTextFragment;
+
+// RenderButtons are just like normal flexboxes except that they will generate an anonymous block child.
+// For inputs, they will also generate an anonymous RenderText and keep its style and content up
+// to date as the button changes.
+class RenderButton : public RenderFlexibleBox {
+public:
+    RenderButton(Node*);
+
+    virtual const char* renderName() const { return "RenderButton"; }
+
+    virtual void addChild(RenderObject* newChild, RenderObject *beforeChild = 0);
+    virtual void removeChild(RenderObject*);
+    virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
+    virtual bool createsAnonymousWrapper() const { return true; }
+
+    virtual void updateFromElement();
+
+    virtual void updateBeforeAfterContent(RenderStyle::PseudoId);
+
+    virtual bool hasControlClip() const { return true; }
+    virtual IntRect controlClipRect(int /*tx*/, int /*ty*/) const;
+
+    void setText(const String&);
+    
+    virtual bool canHaveChildren() const;
+
+protected:
+    virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+    virtual bool hasLineIfEmpty() const { return true; }
+
+    void timerFired(Timer<RenderButton>*);
+
+    RenderTextFragment* m_buttonText;
+    RenderBlock* m_inner;
+
+    OwnPtr<Timer<RenderButton> > m_timer;
+    bool m_default;
+};
+
+} // namespace WebCore
+
+#endif // RenderButton_h
diff --git a/WebCore/rendering/RenderContainer.cpp b/WebCore/rendering/RenderContainer.cpp
new file mode 100644
index 0000000..947acac
--- /dev/null
+++ b/WebCore/rendering/RenderContainer.cpp
@@ -0,0 +1,703 @@
+/**
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ *           (C) 2004 Allan Sandfeld Jensen ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Andrew Wellington ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderContainer.h"
+
+#include "AXObjectCache.h"
+#include "Document.h"
+#include "RenderCounter.h"
+#include "RenderImageGeneratedContent.h"
+#include "RenderLayer.h"
+#include "RenderListItem.h"
+#include "RenderTable.h"
+#include "RenderTextFragment.h"
+#include "RenderView.h"
+#include "htmlediting.h"
+
+namespace WebCore {
+
+RenderContainer::RenderContainer(Node* node)
+    : RenderBox(node)
+    , m_firstChild(0)
+    , m_lastChild(0)
+{
+}
+
+RenderContainer::~RenderContainer()
+{
+}
+
+void RenderContainer::destroy()
+{
+    destroyLeftoverChildren();
+    RenderBox::destroy();
+}
+
+void RenderContainer::destroyLeftoverChildren()
+{
+    while (m_firstChild) {
+        if (m_firstChild->isListMarker() || (m_firstChild->style()->styleType() == RenderStyle::FIRST_LETTER && !m_firstChild->isText()))
+            m_firstChild->remove();  // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
+        else {
+        // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
+            if (m_firstChild->element())
+                m_firstChild->element()->setRenderer(0);
+            m_firstChild->destroy();
+        }
+    }
+}
+
+bool RenderContainer::canHaveChildren() const
+{
+    return true;
+}
+
+static void updateListMarkerNumbers(RenderObject* child)
+{
+    for (RenderObject* r = child; r; r = r->nextSibling())
+        if (r->isListItem())
+            static_cast<RenderListItem*>(r)->updateValue();
+}
+
+void RenderContainer::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    bool needsTable = false;
+
+    if (newChild->isListItem())
+        updateListMarkerNumbers(beforeChild ? beforeChild : m_lastChild);
+    else if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
+        needsTable = !isTable();
+    else if (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
+        needsTable = !isTable();
+    else if (newChild->isTableSection())
+        needsTable = !isTable();
+    else if (newChild->isTableRow())
+        needsTable = !isTableSection();
+    else if (newChild->isTableCell()) {
+        needsTable = !isTableRow();
+        // I'm not 100% sure this is the best way to fix this, but without this
+        // change we recurse infinitely when trying to render the CSS2 test page:
+        // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
+        // See Radar 2925291.
+        if (needsTable && isTableCell() && !m_firstChild && !newChild->isTableCell())
+            needsTable = false;
+    }
+
+    if (needsTable) {
+        RenderTable* table;
+        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : m_lastChild;
+        if (afterChild && afterChild->isAnonymous() && afterChild->isTable())
+            table = static_cast<RenderTable*>(afterChild);
+        else {
+            table = new (renderArena()) RenderTable(document() /* is anonymous */);
+            RefPtr<RenderStyle> newStyle = RenderStyle::create();
+            newStyle->inheritFrom(style());
+            newStyle->setDisplay(TABLE);
+            table->setStyle(newStyle.release());
+            addChild(table, beforeChild);
+        }
+        table->addChild(newChild);
+    } else {
+        // just add it...
+        insertChildNode(newChild, beforeChild);
+    }
+    
+    if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
+        RefPtr<StringImpl> textToTransform = static_cast<RenderText*>(newChild)->originalText();
+        if (textToTransform)
+            static_cast<RenderText*>(newChild)->setText(textToTransform.release(), true);
+    }
+}
+
+RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild, bool fullRemove)
+{
+    ASSERT(oldChild->parent() == this);
+
+    // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
+    // that a positioned child got yanked).  We also repaint, so that the area exposed when the child
+    // disappears gets repainted properly.
+    if (!documentBeingDestroyed() && fullRemove && oldChild->m_everHadLayout) {
+        oldChild->setNeedsLayoutAndPrefWidthsRecalc();
+        oldChild->repaint();
+    }
+        
+    // If we have a line box wrapper, delete it.
+    oldChild->deleteLineBoxWrapper();
+
+    if (!documentBeingDestroyed() && fullRemove) {
+        // if we remove visible child from an invisible parent, we don't know the layer visibility any more
+        RenderLayer* layer = 0;
+        if (m_style->visibility() != VISIBLE && oldChild->style()->visibility() == VISIBLE && !oldChild->hasLayer()) {
+            layer = enclosingLayer();
+            layer->dirtyVisibleContentStatus();
+        }
+
+         // Keep our layer hierarchy updated.
+        if (oldChild->firstChild() || oldChild->hasLayer()) {
+            if (!layer) layer = enclosingLayer();            
+            oldChild->removeLayers(layer);
+        }
+        
+        // renumber ordered lists
+        if (oldChild->isListItem())
+            updateListMarkerNumbers(oldChild->nextSibling());
+        
+        if (oldChild->isPositioned() && childrenInline())
+            dirtyLinesFromChangedChild(oldChild);
+    }
+    
+    // If oldChild is the start or end of the selection, then clear the selection to
+    // avoid problems of invalid pointers.
+    // FIXME: The SelectionController should be responsible for this when it
+    // is notified of DOM mutations.
+    if (!documentBeingDestroyed() && oldChild->isSelectionBorder())
+        view()->clearSelection();
+
+    // remove the child
+    if (oldChild->previousSibling())
+        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
+    if (oldChild->nextSibling())
+        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
+
+    if (m_firstChild == oldChild)
+        m_firstChild = oldChild->nextSibling();
+    if (m_lastChild == oldChild)
+        m_lastChild = oldChild->previousSibling();
+
+    oldChild->setPreviousSibling(0);
+    oldChild->setNextSibling(0);
+    oldChild->setParent(0);
+
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->childrenChanged(this);
+
+    return oldChild;
+}
+
+void RenderContainer::removeChild(RenderObject* oldChild)
+{
+    // We do this here instead of in removeChildNode, since the only extremely low-level uses of remove/appendChildNode
+    // cannot affect the positioned object list, and the floating object list is irrelevant (since the list gets cleared on
+    // layout anyway).
+    oldChild->removeFromObjectLists();
+    
+    removeChildNode(oldChild);
+}
+
+RenderObject* RenderContainer::beforeAfterContainer(RenderStyle::PseudoId type)
+{
+    if (type == RenderStyle::BEFORE) {
+        RenderObject* first = this;
+        do {
+            // Skip list markers.
+            first = first->firstChild();
+            while (first && first->isListMarker())
+                first = first->nextSibling();
+        } while (first && first->isAnonymous() && first->style()->styleType() == RenderStyle::NOPSEUDO);
+        if (first && first->style()->styleType() != type)
+            return 0;
+        return first;
+    }
+    if (type == RenderStyle::AFTER) {
+        RenderObject* last = this;
+        do {
+            last = last->lastChild();
+        } while (last && last->isAnonymous() && last->style()->styleType() == RenderStyle::NOPSEUDO && !last->isListMarker());
+        if (last && last->style()->styleType() != type)
+            return 0;
+        return last;
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+void RenderContainer::updateBeforeAfterContent(RenderStyle::PseudoId type)
+{
+    // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
+    if (parent() && parent()->createsAnonymousWrapper())
+        return;
+    updateBeforeAfterContentForContainer(type, this);
+}
+
+static RenderObject* findBeforeAfterParent(RenderObject* object)
+{
+    // Only table parts need to search for the :before or :after parent
+    if (!(object->isTable() || object->isTableSection() || object->isTableRow()))
+        return object;
+
+    RenderObject* beforeAfterParent = object;
+    while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterParent->isImage()))
+        beforeAfterParent = beforeAfterParent->firstChild();
+    return beforeAfterParent;
+}
+
+void RenderContainer::updateBeforeAfterContentForContainer(RenderStyle::PseudoId type, RenderContainer* styledObject)
+{
+    // In CSS2, before/after pseudo-content cannot nest.  Check this first.
+    if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER)
+        return;
+    
+    RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);
+    RenderObject* child = beforeAfterContainer(type);
+
+    // Whether or not we currently have generated content attached.
+    bool oldContentPresent = child;
+
+    // Whether or not we now want generated content.  
+    bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;
+
+    // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
+    // :after content and not :before content.
+    if (newContentWanted && type == RenderStyle::BEFORE && isInlineContinuation())
+        newContentWanted = false;
+
+    // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
+    // then we don't generate the :after content.
+    if (newContentWanted && type == RenderStyle::AFTER && isRenderInline() && continuation())
+        newContentWanted = false;
+    
+    // If we don't want generated content any longer, or if we have generated content, but it's no longer
+    // identical to the new content data we want to build render objects for, then we nuke all
+    // of the old generated content.
+    if (!newContentWanted || (oldContentPresent && Node::diff(child->style(), pseudoElementStyle) == Node::Detach)) {
+        // Nuke the child. 
+        if (child && child->style()->styleType() == type) {
+            oldContentPresent = false;
+            child->destroy();
+            child = (type == RenderStyle::BEFORE) ? m_firstChild : m_lastChild;
+        }
+    }
+
+    // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
+    // have no generated content and can now return.
+    if (!newContentWanted)
+        return;
+
+    if (isInlineFlow() && !pseudoElementStyle->isDisplayInlineType() && pseudoElementStyle->floating() == FNONE &&
+        !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition))
+        // According to the CSS2 spec (the end of section 12.1), the only allowed
+        // display values for the pseudo style are NONE and INLINE for inline flows.
+        // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
+        // For now we at least relax the restriction to allow all inline types like inline-block
+        // and inline-table.
+        pseudoElementStyle->setDisplay(INLINE);
+
+    if (oldContentPresent) {
+        if (child && child->style()->styleType() == type) {
+            // We have generated content present still.  We want to walk this content and update our
+            // style information with the new pseudo-element style.
+            child->setStyle(pseudoElementStyle);
+
+            RenderObject* beforeAfterParent = findBeforeAfterParent(child);
+            if (!beforeAfterParent)
+                return;
+
+            // Note that if we ever support additional types of generated content (which should be way off
+            // in the future), this code will need to be patched.
+            for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) {
+                if (genChild->isText())
+                    // Generated text content is a child whose style also needs to be set to the pseudo-element style.
+                    genChild->setStyle(pseudoElementStyle);
+                else if (genChild->isImage()) {
+                    // Images get an empty style that inherits from the pseudo.
+                    RefPtr<RenderStyle> style = RenderStyle::create();
+                    style->inheritFrom(pseudoElementStyle);
+                    genChild->setStyle(style.release());
+                } else
+                    // Must be a first-letter container. updateFirstLetter() will take care of it.
+                    ASSERT(genChild->style()->styleType() == RenderStyle::FIRST_LETTER);
+            }
+        }
+        return; // We've updated the generated content. That's all we needed to do.
+    }
+    
+    RenderObject* insertBefore = (type == RenderStyle::BEFORE) ? firstChild() : 0;
+
+    // Generated content consists of a single container that houses multiple children (specified
+    // by the content property).  This generated content container gets the pseudo-element style set on it.
+    RenderObject* generatedContentContainer = 0;
+    
+    // Walk our list of generated content and create render objects for each.
+    for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->m_next) {
+        RenderObject* renderer = 0;
+        switch (content->m_type) {
+            case CONTENT_NONE:
+                break;
+            case CONTENT_TEXT:
+                renderer = new (renderArena()) RenderTextFragment(document() /* anonymous object */, content->m_content.m_text);
+                renderer->setStyle(pseudoElementStyle);
+                break;
+            case CONTENT_OBJECT: {
+                RenderImageGeneratedContent* image = new (renderArena()) RenderImageGeneratedContent(document()); // anonymous object
+                RefPtr<RenderStyle> style = RenderStyle::create();
+                style->inheritFrom(pseudoElementStyle);
+                image->setStyle(style.release());
+                if (StyleImage* styleImage = content->m_content.m_image)
+                    image->setStyleImage(styleImage);
+                renderer = image;
+                break;
+            }
+            case CONTENT_COUNTER:
+                renderer = new (renderArena()) RenderCounter(document(), *content->m_content.m_counter);
+                renderer->setStyle(pseudoElementStyle);
+                break;
+        }
+
+        if (renderer) {
+            if (!generatedContentContainer) {
+                // Make a generated box that might be any display type now that we are able to drill down into children
+                // to find the original content properly.
+                generatedContentContainer = RenderObject::createObject(document(), pseudoElementStyle);
+                generatedContentContainer->setStyle(pseudoElementStyle);
+                addChild(generatedContentContainer, insertBefore);
+            }
+            generatedContentContainer->addChild(renderer);
+        }
+    }
+}
+
+bool RenderContainer::isAfterContent(RenderObject* child) const
+{
+    if (!child)
+        return false;
+    if (child->style()->styleType() != RenderStyle::AFTER)
+        return false;
+    // Text nodes don't have their own styles, so ignore the style on a text node.
+    if (child->isText() && !child->isBR())
+        return false;
+    return true;
+}
+
+static void invalidateCountersInContainer(RenderObject* container)
+{
+    if (!container)
+        return;
+    container = findBeforeAfterParent(container);
+    if (!container)
+        return;
+    for (RenderObject* content = container->firstChild(); content; content = content->nextSibling()) {
+        if (content->isCounter())
+            static_cast<RenderCounter*>(content)->invalidate();
+    }
+}
+
+void RenderContainer::invalidateCounters()
+{
+    if (documentBeingDestroyed())
+        return;
+
+    invalidateCountersInContainer(beforeAfterContainer(RenderStyle::BEFORE));
+    invalidateCountersInContainer(beforeAfterContainer(RenderStyle::AFTER));
+}
+
+void RenderContainer::appendChildNode(RenderObject* newChild, bool fullAppend)
+{
+    ASSERT(newChild->parent() == 0);
+    ASSERT(!isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
+
+    newChild->setParent(this);
+    RenderObject* lChild = m_lastChild;
+
+    if (lChild) {
+        newChild->setPreviousSibling(lChild);
+        lChild->setNextSibling(newChild);
+    } else
+        m_firstChild = newChild;
+
+    m_lastChild = newChild;
+    
+    if (fullAppend) {
+        // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
+        // and don't have a layer attached to ourselves.
+        RenderLayer* layer = 0;
+        if (newChild->firstChild() || newChild->hasLayer()) {
+            layer = enclosingLayer();
+            newChild->addLayers(layer, newChild);
+        }
+
+        // if the new child is visible but this object was not, tell the layer it has some visible content
+        // that needs to be drawn and layer visibility optimization can't be used
+        if (style()->visibility() != VISIBLE && newChild->style()->visibility() == VISIBLE && !newChild->hasLayer()) {
+            if (!layer)
+                layer = enclosingLayer();
+            if (layer)
+                layer->setHasVisibleContent(true);
+        }
+        
+        if (!newChild->isFloatingOrPositioned() && childrenInline())
+            dirtyLinesFromChangedChild(newChild);
+    }
+
+    newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
+    if (!normalChildNeedsLayout())
+        setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+    
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->childrenChanged(this);
+}
+
+void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild, bool fullInsert)
+{
+    if (!beforeChild) {
+        appendChildNode(child);
+        return;
+    }
+
+    ASSERT(!child->parent());
+    while (beforeChild->parent() != this && beforeChild->parent()->isAnonymousBlock())
+        beforeChild = beforeChild->parent();
+    ASSERT(beforeChild->parent() == this);
+
+    ASSERT(!isBlockFlow() || (!child->isTableSection() && !child->isTableRow() && !child->isTableCell()));
+
+    if (beforeChild == m_firstChild)
+        m_firstChild = child;
+
+    RenderObject* prev = beforeChild->previousSibling();
+    child->setNextSibling(beforeChild);
+    beforeChild->setPreviousSibling(child);
+    if(prev) prev->setNextSibling(child);
+    child->setPreviousSibling(prev);
+
+    child->setParent(this);
+    
+    if (fullInsert) {
+        // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
+        // and don't have a layer attached to ourselves.
+        RenderLayer* layer = 0;
+        if (child->firstChild() || child->hasLayer()) {
+            layer = enclosingLayer();
+            child->addLayers(layer, child);
+        }
+
+        // if the new child is visible but this object was not, tell the layer it has some visible content
+        // that needs to be drawn and layer visibility optimization can't be used
+        if (style()->visibility() != VISIBLE && child->style()->visibility() == VISIBLE && !child->hasLayer()) {
+            if (!layer)
+                layer = enclosingLayer();
+            if (layer)
+                layer->setHasVisibleContent(true);
+        }
+
+        
+        if (!child->isFloating() && childrenInline())
+            dirtyLinesFromChangedChild(child);
+    }
+
+    child->setNeedsLayoutAndPrefWidthsRecalc();
+    if (!normalChildNeedsLayout())
+        setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+    
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->childrenChanged(this);
+}
+
+void RenderContainer::layout()
+{
+    ASSERT(needsLayout());
+
+    view()->pushLayoutState(this, IntSize(m_x, m_y));
+
+    RenderObject* child = m_firstChild;
+    while (child) {
+        child->layoutIfNeeded();
+        ASSERT(child->isRenderInline() || !child->needsLayout());
+        child = child->nextSibling();
+    }
+
+    view()->popLayoutState();
+    setNeedsLayout(false);
+}
+
+void RenderContainer::removeLeftoverAnonymousBlock(RenderBlock* child)
+{
+    ASSERT(child->isAnonymousBlock());
+    ASSERT(!child->childrenInline());
+    
+    if (child->continuation()) 
+        return;
+    
+    RenderObject* firstAnChild = child->firstChild();
+    RenderObject* lastAnChild = child->lastChild();
+    if (firstAnChild) {
+        RenderObject* o = firstAnChild;
+        while(o) {
+            o->setParent(this);
+            o = o->nextSibling();
+        }
+        firstAnChild->setPreviousSibling(child->previousSibling());
+        lastAnChild->setNextSibling(child->nextSibling());
+        if (child->previousSibling())
+            child->previousSibling()->setNextSibling(firstAnChild);
+        if (child->nextSibling())
+            child->nextSibling()->setPreviousSibling(lastAnChild);
+    } else {
+        if (child->previousSibling())
+            child->previousSibling()->setNextSibling(child->nextSibling());
+        if (child->nextSibling())
+            child->nextSibling()->setPreviousSibling(child->previousSibling());
+    }
+    if (child == m_firstChild)
+        m_firstChild = firstAnChild;
+    if (child == m_lastChild)
+        m_lastChild = lastAnChild;
+    child->setParent(0);
+    child->setPreviousSibling(0);
+    child->setNextSibling(0);
+    if (!child->isText()) {
+        RenderContainer *c = static_cast<RenderContainer*>(child);
+        c->m_firstChild = 0;
+        c->m_next = 0;
+    }
+    child->destroy();
+}
+
+VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
+{
+    // no children...return this render object's element, if there is one, and offset 0
+    if (!m_firstChild)
+        return VisiblePosition(element(), 0, DOWNSTREAM);
+        
+    if (isTable() && element()) {
+        int right = contentWidth() + borderRight() + paddingRight() + borderLeft() + paddingLeft();
+        int bottom = contentHeight() + borderTop() + paddingTop() + borderBottom() + paddingBottom();
+        
+        if (x < 0 || x > right || y < 0 || y > bottom) {
+            if (x <= right / 2)
+                return VisiblePosition(Position(element(), 0));
+            else
+                return VisiblePosition(Position(element(), maxDeepOffset(element())));
+        }
+    }
+
+    // Pass off to the closest child.
+    int minDist = INT_MAX;
+    RenderObject* closestRenderer = 0;
+    int newX = x;
+    int newY = y;
+    if (isTableRow()) {
+        newX += xPos();
+        newY += yPos();
+    }
+    for (RenderObject* renderer = m_firstChild; renderer; renderer = renderer->nextSibling()) {
+        if (!renderer->firstChild() && !renderer->isInline() && !renderer->isBlockFlow() 
+            || renderer->style()->visibility() != VISIBLE)
+            continue;
+        
+        int top = borderTop() + paddingTop() + (isTableRow() ? 0 : renderer->yPos());
+        int bottom = top + renderer->contentHeight();
+        int left = borderLeft() + paddingLeft() + (isTableRow() ? 0 : renderer->xPos());
+        int right = left + renderer->contentWidth();
+        
+        if (x <= right && x >= left && y <= top && y >= bottom) {
+            if (renderer->isTableRow())
+                return renderer->positionForCoordinates(x + newX - renderer->xPos(), y + newY - renderer->yPos());
+            return renderer->positionForCoordinates(x - renderer->xPos(), y - renderer->yPos());
+        }
+
+        // Find the distance from (x, y) to the box.  Split the space around the box into 8 pieces
+        // and use a different compare depending on which piece (x, y) is in.
+        IntPoint cmp;
+        if (x > right) {
+            if (y < top)
+                cmp = IntPoint(right, top);
+            else if (y > bottom)
+                cmp = IntPoint(right, bottom);
+            else
+                cmp = IntPoint(right, y);
+        } else if (x < left) {
+            if (y < top)
+                cmp = IntPoint(left, top);
+            else if (y > bottom)
+                cmp = IntPoint(left, bottom);
+            else
+                cmp = IntPoint(left, y);
+        } else {
+            if (y < top)
+                cmp = IntPoint(x, top);
+            else
+                cmp = IntPoint(x, bottom);
+        }
+        
+        int x1minusx2 = cmp.x() - x;
+        int y1minusy2 = cmp.y() - y;
+        
+        int dist = x1minusx2 * x1minusx2 + y1minusy2 * y1minusy2;
+        if (dist < minDist) {
+            closestRenderer = renderer;
+            minDist = dist;
+        }
+    }
+    
+    if (closestRenderer)
+        return closestRenderer->positionForCoordinates(newX - closestRenderer->xPos(), newY - closestRenderer->yPos());
+    
+    return VisiblePosition(element(), 0, DOWNSTREAM);
+}
+
+void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end, bool)
+{
+    if (!m_firstChild && (isInline() || isAnonymousBlock())) {
+        int x, y;
+        absolutePositionForContent(x, y);
+        absoluteRects(rects, x, y);
+        return;
+    }
+
+    if (!m_firstChild)
+        return;
+
+    unsigned offset = start;
+    for (RenderObject* child = childAt(start); child && offset < end; child = child->nextSibling(), ++offset) {
+        if (child->isText() || child->isInline() || child->isAnonymousBlock()) {
+            int x, y;
+            child->absolutePositionForContent(x, y);
+            child->absoluteRects(rects, x, y);
+        }
+    }
+}
+
+    
+#ifdef ANDROID_LAYOUT
+bool RenderContainer::hasChildTable() const
+{
+    if (!firstChild())
+        return false;        
+	for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isTable()) {
+        	return true;
+        } else if (child->hasChildTable() == true) {
+        	return true;
+        }
+    }
+    return false;
+}
+#endif
+
+#undef DEBUG_LAYOUT
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderContainer.h b/WebCore/rendering/RenderContainer.h
new file mode 100644
index 0000000..174aa17
--- /dev/null
+++ b/WebCore/rendering/RenderContainer.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2001 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RenderContainer_h
+#define RenderContainer_h
+
+#include "RenderBox.h"
+
+namespace WebCore {
+
+// Base class for rendering objects that can have children.
+class RenderContainer : public RenderBox {
+public:
+    RenderContainer(Node*);
+    virtual ~RenderContainer();
+
+    virtual RenderObject* firstChild() const { return m_firstChild; }
+    virtual RenderObject* lastChild() const { return m_lastChild; }
+
+    virtual bool canHaveChildren() const;
+    virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject*);
+
+    virtual void destroy();
+    void destroyLeftoverChildren();
+
+    virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
+    virtual void appendChildNode(RenderObject*, bool fullAppend = true);
+    virtual void insertChildNode(RenderObject* child, RenderObject* before, bool fullInsert = true);
+    
+    // Designed for speed.  Don't waste time doing a bunch of work like layer updating and repainting when we know that our
+    // change in parentage is not going to affect anything.
+    virtual void moveChildNode(RenderObject* child) { appendChildNode(child->parent()->removeChildNode(child, false), false); }
+    
+    virtual void layout();
+    virtual void calcPrefWidths() { setPrefWidthsDirty(false); }
+
+    virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
+
+    RenderObject* beforeAfterContainer(RenderStyle::PseudoId);
+    virtual void updateBeforeAfterContent(RenderStyle::PseudoId);
+    void updateBeforeAfterContentForContainer(RenderStyle::PseudoId, RenderContainer*);
+    bool isAfterContent(RenderObject* child) const;
+    virtual void invalidateCounters();
+
+    virtual VisiblePosition positionForCoordinates(int x, int y);
+#ifdef ANDROID_LAYOUT
+    virtual bool hasChildTable() const;
+#endif
+
+    virtual void addLineBoxRects(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
+
+private:
+    RenderObject* m_firstChild;
+    RenderObject* m_lastChild;
+};
+
+} // namespace WebCore
+
+#endif // RenderContainer_h
diff --git a/WebCore/rendering/RenderCounter.cpp b/WebCore/rendering/RenderCounter.cpp
new file mode 100644
index 0000000..4b6deed
--- /dev/null
+++ b/WebCore/rendering/RenderCounter.cpp
@@ -0,0 +1,305 @@
+/**
+ * Copyright (C) 2004 Allan Sandfeld Jensen ([email protected])
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderCounter.h"
+
+#include "CounterNode.h"
+#include "Document.h"
+#include "HTMLNames.h"
+#include "HTMLOListElement.h"
+#include "RenderListItem.h"
+#include "RenderListMarker.h"
+#include "RenderStyle.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+typedef HashMap<RefPtr<AtomicStringImpl>, CounterNode*> CounterMap;
+typedef HashMap<const RenderObject*, CounterMap*> CounterMaps;
+
+static CounterNode* counter(RenderObject*, const AtomicString& counterName, bool alwaysCreateCounter);
+
+static CounterMaps& counterMaps()
+{
+    static CounterMaps staticCounterMaps;
+    return staticCounterMaps;
+}
+
+static inline RenderObject* previousSiblingOrParent(RenderObject* object)
+{
+    if (RenderObject* sibling = object->previousSibling())
+        return sibling;
+    return object->parent();
+}
+
+static CounterNode* lastDescendant(CounterNode* node)
+{
+    CounterNode* last = node->lastChild();
+    if (!last)
+        return 0;
+
+    while (CounterNode* lastChild = last->lastChild())
+        last = lastChild;
+
+    return last;
+}
+
+static CounterNode* previousInPreOrder(CounterNode* node)
+{
+    CounterNode* previous = node->previousSibling();
+    if (!previous)
+        return node->parent();
+
+    while (CounterNode* lastChild = previous->lastChild())
+        previous = lastChild;
+
+    return previous;
+}
+
+static bool planCounter(RenderObject* object, const AtomicString& counterName, bool& isReset, int& value)
+{
+    ASSERT(object);
+
+    // Real text nodes don't have their own style so they can't have counters.
+    // We can't even look at their styles or we'll see extra resets and increments!
+    if (object->isText() && !object->isBR())
+        return false;
+
+    RenderStyle* style = object->style();
+    ASSERT(style);
+
+    if (const CounterDirectiveMap* directivesMap = style->counterDirectives()) {
+        CounterDirectives directives = directivesMap->get(counterName.impl());
+        if (directives.m_reset) {
+            value = directives.m_resetValue;
+            if (directives.m_increment)
+                value += directives.m_incrementValue;
+            isReset = true;
+            return true;
+        }
+        if (directives.m_increment) {
+            value = directives.m_incrementValue;
+            isReset = false;
+            return true;
+        }
+    }
+
+    if (counterName == "list-item") {
+        if (object->isListItem()) {
+            if (static_cast<RenderListItem*>(object)->hasExplicitValue()) {
+                value = static_cast<RenderListItem*>(object)->explicitValue();
+                isReset = true;
+                return true;
+            }
+            value = 1;
+            isReset = false;
+            return true;
+        }
+        if (Node* e = object->element()) {
+            if (e->hasTagName(olTag)) {
+                value = static_cast<HTMLOListElement*>(e)->start();
+                isReset = true;
+                return true;
+            }
+            if (e->hasTagName(ulTag) || e->hasTagName(menuTag) || e->hasTagName(dirTag)) {
+                value = 0;
+                isReset = true;
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+static bool findPlaceForCounter(RenderObject* object, const AtomicString& counterName,
+    bool isReset, CounterNode*& parent, CounterNode*& previousSibling)
+{
+    // Find the appropriate previous sibling for insertion into the parent node
+    // by searching in render tree order for a child of the counter.
+    parent = 0;
+    previousSibling = 0;
+    RenderObject* resetCandidate = isReset ? object->parent() : previousSiblingOrParent(object);
+    RenderObject* prevCounterCandidate = object;
+    CounterNode* candidateCounter = 0;
+    while ((prevCounterCandidate = prevCounterCandidate->previousInPreOrder())) {
+        CounterNode* c = counter(prevCounterCandidate, counterName, false);
+        if (prevCounterCandidate == resetCandidate) {
+            if (!candidateCounter)
+                candidateCounter = c;
+            if (candidateCounter) {
+                if (candidateCounter->isReset()) {
+                    parent = candidateCounter;
+                    previousSibling = 0;
+                } else {
+                    parent = candidateCounter->parent();
+                    previousSibling = candidateCounter;
+                }
+                return true;
+            }
+            resetCandidate = previousSiblingOrParent(resetCandidate);
+        } else if (c) {
+            if (c->isReset())
+                candidateCounter = 0;
+            else if (!candidateCounter)
+                candidateCounter = c;
+        }
+    }
+
+    return false;
+}
+
+static CounterNode* counter(RenderObject* object, const AtomicString& counterName, bool alwaysCreateCounter)
+{
+    ASSERT(object);
+
+    if (object->m_hasCounterNodeMap)
+        if (CounterMap* nodeMap = counterMaps().get(object))
+            if (CounterNode* node = nodeMap->get(counterName.impl()))
+                return node;
+
+    bool isReset = false;
+    int value = 0;
+    if (!planCounter(object, counterName, isReset, value) && !alwaysCreateCounter)
+        return 0;
+
+    CounterNode* newParent = 0;
+    CounterNode* newPreviousSibling = 0;
+    CounterNode* newNode;
+    if (findPlaceForCounter(object, counterName, isReset, newParent, newPreviousSibling)) {
+        newNode = new CounterNode(object, isReset, value);
+        newParent->insertAfter(newNode, newPreviousSibling);
+    } else {
+        // Make a reset node for counters that aren't inside an existing reset node.
+        newNode = new CounterNode(object, true, value);
+    }
+
+    CounterMap* nodeMap;
+    if (object->m_hasCounterNodeMap)
+        nodeMap = counterMaps().get(object);
+    else {
+        nodeMap = new CounterMap;
+        counterMaps().set(object, nodeMap);
+        object->m_hasCounterNodeMap = true;
+    }
+    nodeMap->set(counterName.impl(), newNode);
+
+    return newNode;
+}
+
+RenderCounter::RenderCounter(Document* node, const CounterContent& counter)
+    : RenderText(node, StringImpl::empty())
+    , m_counter(counter)
+    , m_counterNode(0)
+{
+}
+
+const char* RenderCounter::renderName() const
+{
+    return "RenderCounter";
+}
+
+bool RenderCounter::isCounter() const
+{
+    return true;
+}
+
+PassRefPtr<StringImpl> RenderCounter::originalText() const
+{
+    if (!parent())
+        return 0;
+
+    if (!m_counterNode)
+        m_counterNode = counter(parent(), m_counter.identifier(), true);
+
+    CounterNode* child = m_counterNode;
+    int value = child->isReset() ? child->value() : child->countInParent();
+
+    String text = listMarkerText(m_counter.listStyle(), value);
+
+    if (!m_counter.separator().isNull()) {
+        if (!child->isReset())
+            child = child->parent();
+        while (CounterNode* parent = child->parent()) {
+            text = listMarkerText(m_counter.listStyle(), child->countInParent())
+                + m_counter.separator() + text;
+            child = parent;
+        }
+    }
+
+    return text.impl();
+}
+
+void RenderCounter::dirtyLineBoxes(bool fullLayout, bool dummy)
+{
+    if (prefWidthsDirty())
+        calcPrefWidths(0);
+    RenderText::dirtyLineBoxes(fullLayout, dummy);
+}
+
+void RenderCounter::calcPrefWidths(int lead)
+{
+    setTextInternal(originalText());
+    RenderText::calcPrefWidths(lead);
+}
+
+void RenderCounter::invalidate()
+{
+    m_counterNode = 0;
+    setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+static void destroyCounterNodeChildren(AtomicStringImpl* identifier, CounterNode* node)
+{
+    CounterNode* previous;
+    for (CounterNode* child = lastDescendant(node); child && child != node; child = previous) {
+        previous = previousInPreOrder(child);
+        child->parent()->removeChild(child);
+        ASSERT(counterMaps().get(child->renderer())->get(identifier) == child);
+        counterMaps().get(child->renderer())->remove(identifier);
+        child->renderer()->invalidateCounters();
+        delete child;
+    }
+}
+
+void RenderCounter::destroyCounterNodes(RenderObject* object)
+{
+    CounterMaps& maps = counterMaps();
+    CounterMap* map = maps.get(object);
+    if (!map)
+        return;
+    maps.remove(object);
+
+    CounterMap::const_iterator end = map->end();
+    for (CounterMap::const_iterator it = map->begin(); it != end; ++it) {
+        CounterNode* node = it->second;
+        destroyCounterNodeChildren(it->first.get(), node);
+        if (CounterNode* parent = node->parent())
+            parent->removeChild(node);
+        delete node;
+    }
+
+    delete map;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderCounter.h b/WebCore/rendering/RenderCounter.h
new file mode 100644
index 0000000..10be066
--- /dev/null
+++ b/WebCore/rendering/RenderCounter.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004 Allan Sandfeld Jensen ([email protected])
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderCounter_h
+#define RenderCounter_h
+
+#include "CounterContent.h"
+#include "RenderText.h"
+
+namespace WebCore {
+
+class CounterNode;
+
+class RenderCounter : public RenderText {
+public:
+    RenderCounter(Document*, const CounterContent&);
+
+    virtual const char* renderName() const;
+    virtual bool isCounter() const;
+    virtual PassRefPtr<StringImpl> originalText() const;
+    
+    virtual void dirtyLineBoxes(bool, bool);
+    virtual void calcPrefWidths(int leadWidth);
+
+    void invalidate();
+
+    static void destroyCounterNodes(RenderObject*);
+
+private:
+    CounterContent m_counter;
+    mutable CounterNode* m_counterNode;
+};
+
+} // namespace WebCore
+
+#endif // RenderCounter_h
diff --git a/WebCore/rendering/RenderFieldset.cpp b/WebCore/rendering/RenderFieldset.cpp
new file mode 100644
index 0000000..d16495b
--- /dev/null
+++ b/WebCore/rendering/RenderFieldset.cpp
@@ -0,0 +1,275 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderFieldset.h"
+
+#include "HTMLFormControlElement.h"
+#include "HTMLNames.h"
+#include "GraphicsContext.h"
+
+using std::min;
+using std::max;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderFieldset::RenderFieldset(HTMLFormControlElement* element)
+    : RenderBlock(element)
+{
+}
+
+void RenderFieldset::calcPrefWidths()
+{
+    RenderBlock::calcPrefWidths();
+    if (RenderObject* legend = findLegend()) {
+        int legendMinWidth = legend->minPrefWidth();
+
+        Length legendMarginLeft = legend->style()->marginLeft();
+        Length legendMarginRight = legend->style()->marginLeft();
+
+        if (legendMarginLeft.isFixed())
+            legendMinWidth += legendMarginLeft.value();
+
+        if (legendMarginRight.isFixed())
+            legendMinWidth += legendMarginRight.value();
+
+        m_minPrefWidth = max(m_minPrefWidth, legendMinWidth + paddingLeft() + paddingRight() + borderLeft() + borderRight());
+    }
+}
+
+RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren)
+{
+    RenderObject* legend = findLegend();
+    if (legend) {
+        if (relayoutChildren)
+            legend->setNeedsLayout(true);
+        legend->layoutIfNeeded();
+
+        int xPos;
+        if (style()->direction() == RTL) {
+            switch (legend->style()->textAlign()) {
+                case LEFT:
+                    xPos = borderLeft() + paddingLeft();
+                    break;
+                case CENTER:
+                    xPos = (m_width - legend->width()) / 2;
+                    break;
+                default:
+                    xPos = m_width - paddingRight() - borderRight() - legend->width() - legend->marginRight();
+            }
+        } else {
+            switch (legend->style()->textAlign()) {
+                case RIGHT:
+                    xPos = m_width - paddingRight() - borderRight() - legend->width();
+                    break;
+                case CENTER:
+                    xPos = (m_width - legend->width()) / 2;
+                    break;
+                default:
+                    xPos = borderLeft() + paddingLeft() + legend->marginLeft();
+            }
+        }
+        int b = borderTop();
+        int h = legend->height();
+        legend->setPos(xPos, max((b-h)/2, 0));
+        m_height = max(b,h) + paddingTop();
+    }
+    return legend;
+}
+
+RenderObject* RenderFieldset::findLegend() const
+{
+    for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) {
+        if (!legend->isFloatingOrPositioned() && legend->element() &&
+            legend->element()->hasTagName(legendTag))
+            return legend;
+    }
+    return 0;
+}
+
+void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
+{
+    int w = width();
+    int h = height() + borderTopExtra() + borderBottomExtra();
+    RenderObject* legend = findLegend();
+    if (!legend)
+        return RenderBlock::paintBoxDecorations(paintInfo, tx, ty);
+
+    int yOff = (legend->yPos() > 0) ? 0 : (legend->height() - borderTop()) / 2;
+    int legendBottom = ty + legend->yPos() + legend->height();
+    h -= yOff;
+    ty += yOff - borderTopExtra();
+
+    int my = max(ty, paintInfo.rect.y());
+    int end = min(paintInfo.rect.bottom(), ty + h);
+    int mh = end - my;
+
+    paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
+
+    paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), my, mh, tx, ty, w, h);
+
+    if (!style()->hasBorder())
+        return;
+
+    // Save time by not saving and restoring the GraphicsContext in the straight border case
+    if (!style()->hasBorderRadius())
+        return paintBorderMinusLegend(paintInfo.context, tx, ty, w, h, style(), legend->xPos(), legend->width(), legendBottom);
+    
+    // We have rounded borders, create a clipping region 
+    // around the legend and paint the border as normal
+    GraphicsContext* graphicsContext = paintInfo.context;
+    graphicsContext->save();
+
+    int clipTop = ty;
+    int clipHeight = max(static_cast<int>(style()->borderTopWidth()), legend->height());
+
+    graphicsContext->clipOut(IntRect(tx + legend->xPos(), clipTop,
+                                       legend->width(), clipHeight));
+    paintBorder(paintInfo.context, tx, ty, w, h, style(), true, true);
+
+    graphicsContext->restore();
+}
+
+void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+        return;
+
+    int w = width();
+    int h = height() + borderTopExtra() + borderBottomExtra();
+    RenderObject* legend = findLegend();
+    if (!legend)
+        return RenderBlock::paintMask(paintInfo, tx, ty);
+
+    int yOff = (legend->yPos() > 0) ? 0 : (legend->height() - borderTop()) / 2;
+    h -= yOff;
+    ty += yOff - borderTopExtra();
+
+    int my = max(ty, paintInfo.rect.y());
+    int end = min(paintInfo.rect.bottom(), ty + h);
+    int mh = end - my;
+
+    paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+}
+        
+void RenderFieldset::paintBorderMinusLegend(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
+                                            const RenderStyle* style, int lx, int lw, int lb)
+{
+    const Color& tc = style->borderTopColor();
+    const Color& bc = style->borderBottomColor();
+
+    EBorderStyle ts = style->borderTopStyle();
+    EBorderStyle bs = style->borderBottomStyle();
+    EBorderStyle ls = style->borderLeftStyle();
+    EBorderStyle rs = style->borderRightStyle();
+
+    bool render_t = ts > BHIDDEN;
+    bool render_l = ls > BHIDDEN;
+    bool render_r = rs > BHIDDEN;
+    bool render_b = bs > BHIDDEN;
+
+    int borderLeftWidth = style->borderLeftWidth();
+    int borderRightWidth = style->borderRightWidth();
+
+    if (render_t) {
+        if (lx >= borderLeftWidth)
+            drawBorder(graphicsContext, tx, ty, tx + min(lx, w), ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
+                       (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? borderLeftWidth : 0),
+                       (lx >= w && render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? borderRightWidth : 0));
+        if (lx + lw <=  w - borderRightWidth)
+            drawBorder(graphicsContext, tx + max(0, lx + lw), ty, tx + w, ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
+                       (lx + lw <= 0 && render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? borderLeftWidth : 0),
+                       (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? borderRightWidth : 0));
+    }
+
+    if (render_b)
+        drawBorder(graphicsContext, tx, ty + h - style->borderBottomWidth(), tx + w, ty + h, BSBottom, bc, style->color(), bs,
+                   (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? style->borderLeftWidth() : 0),
+                   (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? style->borderRightWidth() : 0));
+
+    if (render_l) {
+        const Color& lc = style->borderLeftColor();
+        int startY = ty;
+
+        bool ignore_top =
+            (tc == lc) &&
+            (ls >= OUTSET) &&
+            (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
+
+        bool ignore_bottom =
+            (bc == lc) &&
+            (ls >= OUTSET) &&
+            (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
+
+        if (lx < borderLeftWidth && lx + lw > 0) {
+            // The legend intersects the border.
+            ignore_top = true;
+            startY = lb;
+        }
+
+        drawBorder(graphicsContext, tx, startY, tx + borderLeftWidth, ty + h, BSLeft, lc, style->color(), ls,
+                   ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
+    }
+
+    if (render_r) {
+        const Color& rc = style->borderRightColor();
+        int startY = ty;
+
+        bool ignore_top =
+            (tc == rc) &&
+            (rs >= DOTTED || rs == INSET) &&
+            (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
+
+        bool ignore_bottom =
+            (bc == rc) &&
+            (rs >= DOTTED || rs == INSET) &&
+            (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
+
+        if (lx < w && lx + lw > w - borderRightWidth) {
+            // The legend intersects the border.
+            ignore_top = true;
+            startY = lb;
+        }
+
+        drawBorder(graphicsContext, tx + w - borderRightWidth, startY, tx + w, ty + h, BSRight, rc, style->color(), rs,
+                   ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
+    }
+}
+
+void RenderFieldset::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+
+    // WinIE renders fieldsets with display:inline like they're inline-blocks.  For us,
+    // an inline-block is just a block element with replaced set to true and inline set
+    // to true.  Ensure that if we ended up being inline that we set our replaced flag
+    // so that we're treated like an inline-block.
+    if (isInline())
+        setReplaced(true);
+}    
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderFieldset.h b/WebCore/rendering/RenderFieldset.h
new file mode 100644
index 0000000..87652fd
--- /dev/null
+++ b/WebCore/rendering/RenderFieldset.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderFieldset_h
+#define RenderFieldset_h
+
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+class HTMLFormControlElement;
+
+class RenderFieldset : public RenderBlock {
+public:
+    RenderFieldset(HTMLFormControlElement*);
+
+    virtual const char* renderName() const { return "RenderFieldSet"; }
+    virtual bool isFieldset() const { return true; }
+
+    virtual RenderObject* layoutLegend(bool relayoutChildren);
+
+    virtual void calcPrefWidths();
+    virtual bool avoidsFloats() const { return true; }
+    virtual bool expandsToEncloseOverhangingFloats() const { return style()->height().isAuto(); }
+    virtual bool stretchesToMinIntrinsicWidth() const { return true; }
+
+    RenderObject* findLegend() const;
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+private:
+    virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
+    virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
+    void paintBorderMinusLegend(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, int lx, int lw, int lb);
+};
+
+} // namespace WebCore
+
+#endif // RenderFieldset_h
diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp
new file mode 100644
index 0000000..fe9772e
--- /dev/null
+++ b/WebCore/rendering/RenderFileUploadControl.cpp
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderFileUploadControl.h"
+
+#include "FileList.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "Icon.h"
+#include "LocalizedStrings.h"
+#include "Page.h"
+#include "RenderButton.h"
+#include "RenderText.h"
+#include "RenderTheme.h"
+#include "RenderView.h"
+#include <math.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+const int afterButtonSpacing = 4;
+const int iconHeight = 16;
+const int iconWidth = 16;
+const int iconFilenameSpacing = 2;
+const int defaultWidthNumChars = 34;
+const int buttonShadowHeight = 2;
+
+class HTMLFileUploadInnerButtonElement : public HTMLInputElement {
+public:
+    HTMLFileUploadInnerButtonElement(Document*, Node* shadowParent);
+
+    virtual bool isShadowNode() const { return true; }
+    virtual Node* shadowParentNode() { return m_shadowParent; }
+
+private:
+    Node* m_shadowParent;    
+};
+
+RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement* input)
+    : RenderBlock(input)
+    , m_button(0)
+    , m_fileChooser(FileChooser::create(this, input->value()))
+{
+}
+
+RenderFileUploadControl::~RenderFileUploadControl()
+{
+    if (m_button)
+        m_button->detach();
+    m_fileChooser->disconnectClient();
+}
+
+void RenderFileUploadControl::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    if (m_button)
+        m_button->renderer()->setStyle(createButtonStyle(style()));
+
+    setReplaced(isInline());
+}
+
+void RenderFileUploadControl::valueChanged()
+{
+    // onChange may destroy this renderer
+    RefPtr<FileChooser> fileChooser = m_fileChooser;
+
+    HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(node());
+    inputElement->setFileListFromRenderer(fileChooser->filenames());
+    inputElement->onChange();
+ 
+    // only repaint if it doesn't seem we have been destroyed
+    if (!fileChooser->disconnected())
+        repaint();
+}
+
+bool RenderFileUploadControl::allowsMultipleFiles()
+{
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+    return !input->getAttribute(multipleAttr).isNull();
+}
+
+void RenderFileUploadControl::click()
+{
+    Frame* frame = node()->document()->frame();
+    if (!frame)
+        return;
+    Page* page = frame->page();
+    if (!page)
+        return;
+    page->chrome()->runOpenPanel(frame, m_fileChooser);
+}
+
+void RenderFileUploadControl::updateFromElement()
+{
+    HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(node());
+    ASSERT(inputElement->inputType() == HTMLInputElement::FILE);
+    
+    if (!m_button) {
+        m_button = new HTMLFileUploadInnerButtonElement(document(), inputElement);
+        m_button->setInputType("button");
+        m_button->setValue(fileButtonChooseFileLabel());
+        RefPtr<RenderStyle> buttonStyle = createButtonStyle(style());
+        RenderObject* renderer = m_button->createRenderer(renderArena(), buttonStyle.get());
+        m_button->setRenderer(renderer);
+        renderer->setStyle(buttonStyle.release());
+        renderer->updateFromElement();
+        m_button->setAttached();
+        m_button->setInDocument(true);
+
+        addChild(renderer);
+    }
+
+#ifndef ANDROID_DISABLE_UPLOAD
+    m_button->setDisabled(!theme()->isEnabled(this));
+#else
+    m_button->setDisabled(true);
+#endif
+
+    // This only supports clearing out the files, but that's OK because for
+    // security reasons that's the only change the DOM is allowed to make.
+    FileList* files = inputElement->files();
+    ASSERT(files);
+    if (files && files->isEmpty() && !m_fileChooser->filenames().isEmpty()) {
+        m_fileChooser->clear();
+        repaint();
+    }
+}
+
+int RenderFileUploadControl::maxFilenameWidth() const
+{
+    return max(0, contentWidth() - m_button->renderer()->width() - afterButtonSpacing
+        - (m_fileChooser->icon() ? iconWidth + iconFilenameSpacing : 0));
+}
+
+PassRefPtr<RenderStyle> RenderFileUploadControl::createButtonStyle(const RenderStyle* parentStyle) const
+{
+    RefPtr<RenderStyle> style = getCachedPseudoStyle(RenderStyle::FILE_UPLOAD_BUTTON);
+    if (!style) {
+        style = RenderStyle::create();
+        if (parentStyle)
+            style->inheritFrom(parentStyle);
+    }
+
+    // Button text will wrap on file upload controls with widths smaller than the intrinsic button width
+    // without this setWhiteSpace.
+    style->setWhiteSpace(NOWRAP);
+
+    return style.release();
+}
+
+void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (style()->visibility() != VISIBLE)
+        return;
+    
+    // Push a clip.
+    if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) {
+        IntRect clipRect(tx + borderLeft(), ty + borderTop(),
+                         width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop() + buttonShadowHeight);
+        if (clipRect.isEmpty())
+            return;
+        paintInfo.context->save();
+        paintInfo.context->clip(clipRect);
+    }
+
+    if (paintInfo.phase == PaintPhaseForeground) {
+        const String& displayedFilename = m_fileChooser->basenameForWidth(style()->font(), maxFilenameWidth());        
+        unsigned length = displayedFilename.length();
+        const UChar* string = displayedFilename.characters();
+        TextRun textRun(string, length, false, 0, 0, style()->direction() == RTL, style()->unicodeBidi() == Override);
+        
+        // Determine where the filename should be placed
+        int contentLeft = tx + borderLeft() + paddingLeft();
+        int buttonAndIconWidth = m_button->renderer()->width() + afterButtonSpacing
+            + (m_fileChooser->icon() ? iconWidth + iconFilenameSpacing : 0);
+        int textX;
+        if (style()->direction() == LTR)
+            textX = contentLeft + buttonAndIconWidth;
+        else
+            textX = contentLeft + contentWidth() - buttonAndIconWidth - style()->font().width(textRun);
+        // We want to match the button's baseline
+        RenderButton* buttonRenderer = static_cast<RenderButton*>(m_button->renderer());
+        int textY = buttonRenderer->absoluteBoundingBoxRect().y()
+            + buttonRenderer->marginTop() + buttonRenderer->borderTop() + buttonRenderer->paddingTop()
+            + buttonRenderer->baselinePosition(true, false);
+
+        paintInfo.context->setFont(style()->font());
+        paintInfo.context->setFillColor(style()->color());
+        
+        // Draw the filename
+        paintInfo.context->drawBidiText(textRun, IntPoint(textX, textY));
+        
+        if (m_fileChooser->icon()) {
+            // Determine where the icon should be placed
+            int iconY = ty + borderTop() + paddingTop() + (contentHeight() - iconHeight) / 2;
+            int iconX;
+            if (style()->direction() == LTR)
+                iconX = contentLeft + m_button->renderer()->width() + afterButtonSpacing;
+            else
+                iconX = contentLeft + contentWidth() - m_button->renderer()->width() - afterButtonSpacing - iconWidth;
+
+            // Draw the file icon
+            m_fileChooser->icon()->paint(paintInfo.context, IntRect(iconX, iconY, iconWidth, iconHeight));
+        }
+    }
+
+    // Paint the children.
+    RenderBlock::paintObject(paintInfo, tx, ty);
+
+    // Pop the clip.
+    if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds)
+        paintInfo.context->restore();
+}
+
+void RenderFileUploadControl::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+
+    m_minPrefWidth = 0;
+    m_maxPrefWidth = 0;
+
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
+    else {
+        // Figure out how big the filename space needs to be for a given number of characters
+        // (using "0" as the nominal character).
+        const UChar ch = '0';
+        float charWidth = style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, false, false, false));
+        m_maxPrefWidth = (int)ceilf(charWidth * defaultWidthNumChars);
+    }
+
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+        m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+    } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
+        m_minPrefWidth = 0;
+    else
+        m_minPrefWidth = m_maxPrefWidth;
+
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
+        m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+        m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+    }
+
+    int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+    m_minPrefWidth += toAdd;
+    m_maxPrefWidth += toAdd;
+
+    setPrefWidthsDirty(false);
+}
+
+void RenderFileUploadControl::receiveDroppedFiles(const Vector<String>& paths)
+{
+    if (allowsMultipleFiles())
+        m_fileChooser->chooseFiles(paths);
+    else
+        m_fileChooser->chooseFile(paths[0]);
+}
+
+String RenderFileUploadControl::buttonValue()
+{
+    if (!m_button)
+        return String();
+    
+    return m_button->value();
+}
+
+String RenderFileUploadControl::fileTextValue()
+{
+    return m_fileChooser->basenameForWidth(style()->font(), maxFilenameWidth());
+}
+    
+HTMLFileUploadInnerButtonElement::HTMLFileUploadInnerButtonElement(Document* doc, Node* shadowParent)
+    : HTMLInputElement(doc)
+    , m_shadowParent(shadowParent)
+{
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderFileUploadControl.h b/WebCore/rendering/RenderFileUploadControl.h
new file mode 100644
index 0000000..60e7a7b
--- /dev/null
+++ b/WebCore/rendering/RenderFileUploadControl.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2006, 2007 Apple 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderFileUploadControl_h
+#define RenderFileUploadControl_h
+
+#include "FileChooser.h"
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+class HTMLInputElement;
+    
+// Each RenderFileUploadControl contains a RenderButton (for opening the file chooser), and
+// sufficient space to draw a file icon and filename. The RenderButton has a shadow node
+// associated with it to receive click/hover events.
+
+class RenderFileUploadControl : public RenderBlock, private FileChooserClient {
+public:
+    RenderFileUploadControl(HTMLInputElement*);
+    ~RenderFileUploadControl();
+
+    virtual const char* renderName() const { return "RenderFileUploadControl"; }
+
+    virtual void updateFromElement();
+    virtual void calcPrefWidths();
+    virtual void paintObject(PaintInfo&, int tx, int ty);
+
+    void click();
+
+    void valueChanged();
+    
+    void receiveDroppedFiles(const Vector<String>&);
+
+    String buttonValue();
+    String fileTextValue();
+    
+    bool allowsMultipleFiles();
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+private:
+    int maxFilenameWidth() const;
+    PassRefPtr<RenderStyle> createButtonStyle(const RenderStyle* parentStyle) const;
+
+    RefPtr<HTMLInputElement> m_button;
+    RefPtr<FileChooser> m_fileChooser;
+};
+
+} // namespace WebCore
+
+#endif // RenderFileUploadControl_h
diff --git a/WebCore/rendering/RenderFlexibleBox.cpp b/WebCore/rendering/RenderFlexibleBox.cpp
new file mode 100644
index 0000000..f39bf74
--- /dev/null
+++ b/WebCore/rendering/RenderFlexibleBox.cpp
@@ -0,0 +1,1179 @@
+/*
+ * This file is part of the render object implementation for KHTML.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderFlexibleBox.h"
+
+#include "CharacterNames.h"
+#include "RenderLayer.h"
+#include "RenderView.h"
+
+#ifdef ANDROID_LAYOUT
+#include "Document.h"
+#include "Settings.h"
+#endif
+
+using namespace std;
+
+namespace WebCore {
+
+class FlexBoxIterator {
+public:
+    FlexBoxIterator(RenderFlexibleBox* parent) {
+        box = parent;
+        if (box->style()->boxOrient() == HORIZONTAL && box->style()->direction() == RTL)
+            forward = box->style()->boxDirection() != BNORMAL;
+        else
+            forward = box->style()->boxDirection() == BNORMAL;
+        lastOrdinal = 1; 
+        if (!forward) {
+            // No choice, since we're going backwards, we have to find out the highest ordinal up front.
+            RenderObject* child = box->firstChild();
+            while (child) {
+                if (child->style()->boxOrdinalGroup() > lastOrdinal)
+                    lastOrdinal = child->style()->boxOrdinalGroup();
+                child = child->nextSibling();
+            }
+        }
+        
+        reset();
+    }
+
+    void reset() {
+        current = 0;
+        currentOrdinal = forward ? 0 : lastOrdinal+1;
+    }
+
+    RenderObject* first() {
+        reset();
+        return next();
+    }
+    
+    RenderObject* next() {
+
+        do { 
+            if (!current) {
+                if (forward) {
+                    currentOrdinal++; 
+                    if (currentOrdinal > lastOrdinal)
+                        return 0;
+                    current = box->firstChild();
+                } else {
+                    currentOrdinal--;
+                    if (currentOrdinal == 0)
+                        return 0;
+                    current = box->lastChild();
+                }
+            }
+            else
+                current = forward ? current->nextSibling() : current->previousSibling();
+            if (current && current->style()->boxOrdinalGroup() > lastOrdinal)
+                lastOrdinal = current->style()->boxOrdinalGroup();
+        } while (!current || current->style()->boxOrdinalGroup() != currentOrdinal ||
+                 current->style()->visibility() == COLLAPSE);
+        return current;
+    }
+
+private:
+    RenderFlexibleBox* box;
+    RenderObject* current;
+    bool forward;
+    unsigned int currentOrdinal;
+    unsigned int lastOrdinal;
+};
+    
+RenderFlexibleBox::RenderFlexibleBox(Node* node)
+:RenderBlock(node)
+{
+    setChildrenInline(false); // All of our children must be block-level
+    m_flexingChildren = m_stretchingChildren = false;
+}
+
+RenderFlexibleBox::~RenderFlexibleBox()
+{
+}
+
+void RenderFlexibleBox::calcHorizontalPrefWidths()
+{
+    RenderObject *child = firstChild();
+    while (child) {
+        // positioned children don't affect the minmaxwidth
+        if (child->isPositioned() || child->style()->visibility() == COLLAPSE) {
+            child = child->nextSibling();
+            continue;
+        }
+
+        // A margin basically has three types: fixed, percentage, and auto (variable).
+        // Auto and percentage margins simply become 0 when computing min/max width.
+        // Fixed margins can be added in as is.
+        Length ml = child->style()->marginLeft();
+        Length mr = child->style()->marginRight();
+        int margin = 0, marginLeft = 0, marginRight = 0;
+        if (ml.isFixed())
+            marginLeft += ml.value();
+        if (mr.isFixed())
+            marginRight += mr.value();
+        margin = marginLeft + marginRight;
+
+        m_minPrefWidth += child->minPrefWidth() + margin;
+        m_maxPrefWidth += child->maxPrefWidth() + margin;
+
+        child = child->nextSibling();
+    }    
+}
+
+void RenderFlexibleBox::calcVerticalPrefWidths()
+{
+    RenderObject *child = firstChild();
+    while(child != 0)
+    {
+        // Positioned children and collapsed children don't affect the min/max width
+        if (child->isPositioned() || child->style()->visibility() == COLLAPSE) {
+            child = child->nextSibling();
+            continue;
+        }
+
+        // A margin basically has three types: fixed, percentage, and auto (variable).
+        // Auto/percentage margins simply become 0 when computing min/max width.
+        // Fixed margins can be added in as is.
+        Length ml = child->style()->marginLeft();
+        Length mr = child->style()->marginRight();
+        int margin = 0;
+        if (ml.isFixed())
+            margin += ml.value();
+        if (mr.isFixed())
+            margin += mr.value();
+        
+        int w = child->minPrefWidth() + margin;
+        m_minPrefWidth = max(w, m_minPrefWidth);
+        
+        w = child->maxPrefWidth() + margin;
+        m_maxPrefWidth = max(w, m_maxPrefWidth);
+
+        child = child->nextSibling();
+    }    
+}
+
+void RenderFlexibleBox::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
+    else {
+        m_minPrefWidth = m_maxPrefWidth = 0;
+
+        if (hasMultipleLines() || isVertical())
+            calcVerticalPrefWidths();
+        else
+            calcHorizontalPrefWidths();
+
+        m_maxPrefWidth = max(m_minPrefWidth, m_maxPrefWidth);
+    }
+
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+        m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+    }
+    
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
+        m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+        m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+    }
+
+    int toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
+    m_minPrefWidth += toAdd;
+    m_maxPrefWidth += toAdd;
+
+    setPrefWidthsDirty(false);
+}
+
+void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
+{
+    ASSERT(needsLayout());
+
+    if (!relayoutChildren && layoutOnlyPositionedObjects())
+        return;
+
+    IntRect oldBounds;
+    IntRect oldOutlineBox;
+    bool checkForRepaint = checkForRepaintDuringLayout();
+    if (checkForRepaint) {
+        oldBounds = absoluteClippedOverflowRect();
+        oldOutlineBox = absoluteOutlineBox();
+    }
+
+    if (!hasReflection())
+        view()->pushLayoutState(this, IntSize(m_x, m_y));
+    else
+        view()->disableLayoutState();
+
+    int previousWidth = m_width;
+    int previousHeight = m_height;
+
+#ifdef ANDROID_LAYOUT
+    int previousVisibleWidth = m_visibleWidth;
+#endif
+    
+    calcWidth();
+    calcHeight();
+    m_overflowWidth = m_width;
+
+    if (previousWidth != m_width || previousHeight != m_height ||
+        (parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL &&
+         parent()->style()->boxAlign() == BSTRETCH))
+        relayoutChildren = true;
+
+#ifdef ANDROID_LAYOUT
+    const Settings* settings = document()->settings();
+    ASSERT(settings);
+    if (previousVisibleWidth != m_visibleWidth
+            && settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
+        relayoutChildren = true;
+#endif
+
+    m_height = 0;
+    m_overflowHeight = 0;
+    m_flexingChildren = m_stretchingChildren = false;
+
+    initMaxMarginValues();
+
+    // For overflow:scroll blocks, ensure we have both scrollbars in place always.
+    if (scrollsOverflow()) {
+        if (style()->overflowX() == OSCROLL)
+            m_layer->setHasHorizontalScrollbar(true);
+        if (style()->overflowY() == OSCROLL)
+            m_layer->setHasVerticalScrollbar(true);
+    }
+
+    if (isHorizontal())
+        layoutHorizontalBox(relayoutChildren);
+    else
+        layoutVerticalBox(relayoutChildren);
+
+    int oldHeight = m_height;
+    calcHeight();
+    if (oldHeight != m_height) {
+        // If the block got expanded in size, then increase our overflowheight to match.
+        if (m_overflowHeight > m_height)
+            m_overflowHeight -= (borderBottom() + paddingBottom() + horizontalScrollbarHeight());
+        if (m_overflowHeight < m_height)
+            m_overflowHeight = m_height;
+    }
+    if (previousHeight != m_height)
+        relayoutChildren = true;
+
+    layoutPositionedObjects(relayoutChildren || isRoot());
+
+    if (!isFloatingOrPositioned() && m_height == 0) {
+        // We are a block with no border and padding and a computed height
+        // of 0.  The CSS spec states that zero-height blocks collapse their margins
+        // together.
+        // When blocks are self-collapsing, we just use the top margin values and set the
+        // bottom margin max values to 0.  This way we don't factor in the values
+        // twice when we collapse with our previous vertically adjacent and
+        // following vertically adjacent blocks.
+        int pos = maxTopPosMargin();
+        int neg = maxTopNegMargin();
+        if (maxBottomPosMargin() > pos)
+            pos = maxBottomPosMargin();
+        if (maxBottomNegMargin() > neg)
+            neg = maxBottomNegMargin();
+        setMaxTopMargins(pos, neg);
+        setMaxBottomMargins(0, 0);
+    }
+
+    // Always ensure our overflow width is at least as large as our width.
+    if (m_overflowWidth < m_width)
+        m_overflowWidth = m_width;
+
+    if (!hasOverflowClip()) {
+        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+            m_overflowLeft = min(m_overflowLeft, boxShadow->x - boxShadow->blur);
+            m_overflowWidth = max(m_overflowWidth, m_width + boxShadow->x + boxShadow->blur);
+            m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur);
+            m_overflowHeight = max(m_overflowHeight, m_height + boxShadow->y + boxShadow->blur);
+        }
+        
+        if (hasReflection()) {
+            IntRect reflection(reflectionBox());
+            m_overflowTop = min(m_overflowTop, reflection.y());
+            m_overflowHeight = max(m_overflowHeight, reflection.bottom());
+            m_overflowLeft = min(m_overflowLeft, reflection.x());
+            m_overflowHeight = max(m_overflowWidth, reflection.right());
+        }
+    }
+
+    if (!hasReflection())
+        view()->popLayoutState();
+    else
+        view()->enableLayoutState();
+
+    // Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if
+    // we overflow or not.
+    if (hasOverflowClip())
+        m_layer->updateScrollInfoAfterLayout();
+
+    // Repaint with our new bounds if they are different from our old bounds.
+    if (checkForRepaint)
+        repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+    
+    setNeedsLayout(false);
+}
+
+void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
+{
+    int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
+    int yPos = borderTop() + paddingTop();
+    int xPos = borderLeft() + paddingLeft();
+    bool heightSpecified = false;
+    int oldHeight = 0;
+    
+    unsigned int highestFlexGroup = 0;
+    unsigned int lowestFlexGroup = 0;
+    bool haveFlex = false;
+    int remainingSpace = 0;
+    m_overflowHeight = m_height;
+
+    // The first walk over our kids is to find out if we have any flexible children.
+    FlexBoxIterator iterator(this);
+    RenderObject* child = iterator.next();
+    while (child) {
+        // Check to see if this child flexes.
+        if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) {
+            // We always have to lay out flexible objects again, since the flex distribution
+            // may have changed, and we need to reallocate space.
+            child->setOverrideSize(-1);
+            if (!relayoutChildren)
+                child->setChildNeedsLayout(true, false);
+            haveFlex = true;
+            unsigned int flexGroup = child->style()->boxFlexGroup();
+            if (lowestFlexGroup == 0)
+                lowestFlexGroup = flexGroup;
+            if (flexGroup < lowestFlexGroup)
+                lowestFlexGroup = flexGroup;
+            if (flexGroup > highestFlexGroup)
+                highestFlexGroup = flexGroup;
+        }
+        child = iterator.next();
+    }
+    
+    // We do 2 passes.  The first pass is simply to lay everyone out at
+    // their preferred widths.  The second pass handles flexing the children.
+    do {
+        // Reset our height.
+        m_height = yPos;
+        m_overflowHeight = m_height;
+        xPos = borderLeft() + paddingLeft();
+                
+        // Our first pass is done without flexing.  We simply lay the children
+        // out within the box.  We have to do a layout first in order to determine
+        // our box's intrinsic height.
+        int maxAscent = 0, maxDescent = 0;
+        child = iterator.first();
+        while (child) {
+            // make sure we relayout children if we need it.
+            if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))
+                child->setChildNeedsLayout(true, false);
+            
+            if (child->isPositioned()) {
+                child = iterator.next();
+                continue;
+            }
+    
+            // Compute the child's vertical margins.
+            child->calcVerticalMargins();
+    
+            // Now do the layout.
+            child->layoutIfNeeded();
+    
+            // Update our height and overflow height.
+            if (style()->boxAlign() == BBASELINE) {
+                int ascent = child->marginTop() + child->getBaselineOfFirstLineBox();
+                if (ascent == -1)
+                    ascent = child->marginTop() + child->height() + child->marginBottom();
+                int descent = (child->marginTop() + child->height() + child->marginBottom()) - ascent;
+                
+                // Update our maximum ascent.
+                maxAscent = max(maxAscent, ascent);
+                
+                // Update our maximum descent.
+                maxDescent = max(maxDescent, descent);
+                
+                // Now update our height.
+                m_height = max(yPos + maxAscent + maxDescent, m_height);
+            }
+            else
+                m_height = max(m_height, yPos + child->marginTop() + child->height() + child->marginBottom());
+
+            child = iterator.next();
+        }
+        
+        if (!iterator.first() && hasLineIfEmpty())
+            m_height += lineHeight(true, true);
+        
+        m_height += toAdd;
+
+        // Always make sure our overflowheight is at least our height.
+        if (m_overflowHeight < m_height)
+            m_overflowHeight = m_height;
+        
+        oldHeight = m_height;
+        calcHeight();
+
+        relayoutChildren = false;
+        if (oldHeight != m_height)
+            heightSpecified = true;
+        
+        // Now that our height is actually known, we can place our boxes.
+        m_stretchingChildren = (style()->boxAlign() == BSTRETCH);
+        child = iterator.first();
+        while (child) {
+            if (child->isPositioned()) {
+                child->containingBlock()->insertPositionedObject(child);
+                if (child->hasStaticX()) {
+                    if (style()->direction() == LTR)
+                        child->setStaticX(xPos);
+                    else child->setStaticX(width() - xPos);
+                }
+                if (child->hasStaticY())
+                    child->setStaticY(yPos);
+                child = iterator.next();
+                continue;
+            }
+    
+            // We need to see if this child's height has changed, since we make block elements
+            // fill the height of a containing box by default.
+            // Now do a layout.
+            int oldChildHeight = child->height();
+            static_cast<RenderBox*>(child)->calcHeight();
+            if (oldChildHeight != child->height())
+                child->setChildNeedsLayout(true, false);
+            child->layoutIfNeeded();
+    
+            // We can place the child now, using our value of box-align.
+            xPos += child->marginLeft();
+            int childY = yPos;
+            switch (style()->boxAlign()) {
+                case BCENTER:
+                    childY += child->marginTop() + max(0, (contentHeight() - (child->height() + child->marginTop() + child->marginBottom()))/2);
+                    break;
+                case BBASELINE: {
+                    int ascent = child->marginTop() + child->getBaselineOfFirstLineBox();
+                    if (ascent == -1)
+                        ascent = child->marginTop() + child->height() + child->marginBottom();
+                    childY += child->marginTop() + (maxAscent - ascent);
+                    break;
+                }
+                case BEND:
+                    childY += contentHeight() - child->marginBottom() - child->height();
+                    break;
+                default: // BSTART
+                    childY += child->marginTop();
+                    break;
+            }
+
+            placeChild(child, xPos, childY);
+
+            if (child->isRenderBlock())
+                static_cast<RenderBlock*>(child)->addVisualOverflow(static_cast<RenderBlock*>(child)->floatRect());
+
+            m_overflowHeight = max(m_overflowHeight, childY + child->overflowHeight(false));
+            m_overflowTop = min(m_overflowTop, child->yPos() + child->overflowTop(false));
+            
+            xPos += child->width() + child->marginRight();
+    
+            child = iterator.next();
+        }
+
+        remainingSpace = borderLeft() + paddingLeft() + contentWidth() - xPos;
+        
+        m_stretchingChildren = false;
+        if (m_flexingChildren)
+            haveFlex = false; // We're done.
+        else if (haveFlex) {
+            // We have some flexible objects.  See if we need to grow/shrink them at all.
+            if (!remainingSpace)
+                break;
+
+            // Allocate the remaining space among the flexible objects.  If we are trying to
+            // grow, then we go from the lowest flex group to the highest flex group.  For shrinking,
+            // we go from the highest flex group to the lowest group.
+            bool expanding = remainingSpace > 0;
+            unsigned int start = expanding ? lowestFlexGroup : highestFlexGroup;
+            unsigned int end = expanding? highestFlexGroup : lowestFlexGroup;
+            for (unsigned int i = start; i <= end && remainingSpace; i++) {
+                // Always start off by assuming the group can get all the remaining space.
+                int groupRemainingSpace = remainingSpace;
+                do {
+                    // Flexing consists of multiple passes, since we have to change ratios every time an object hits its max/min-width
+                    // For a given pass, we always start off by computing the totalFlex of all objects that can grow/shrink at all, and
+                    // computing the allowed growth before an object hits its min/max width (and thus
+                    // forces a totalFlex recomputation).
+                    int groupRemainingSpaceAtBeginning = groupRemainingSpace;
+                    float totalFlex = 0.0f;
+                    child = iterator.first();
+                    while (child) {
+                        if (allowedChildFlex(child, expanding, i))
+                            totalFlex += child->style()->boxFlex();
+                        child = iterator.next();
+                    }
+                    child = iterator.first();
+                    int spaceAvailableThisPass = groupRemainingSpace;
+                    while (child) {
+                        int allowedFlex = allowedChildFlex(child, expanding, i);
+                        if (allowedFlex) {
+                            int projectedFlex = (allowedFlex == INT_MAX) ? allowedFlex : (int)(allowedFlex * (totalFlex / child->style()->boxFlex()));
+                            spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
+                        }
+                        child = iterator.next();
+                    }
+
+                    // The flex groups may not have any flexible objects this time around. 
+                    if (!spaceAvailableThisPass || totalFlex == 0.0f) {
+                        // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group.
+                        groupRemainingSpace = 0;
+                        continue;
+                    }
+
+                    // Now distribute the space to objects.
+                    child = iterator.first();
+                    while (child && spaceAvailableThisPass && totalFlex) {
+                        if (allowedChildFlex(child, expanding, i)) {
+                            int spaceAdd = (int)(spaceAvailableThisPass * (child->style()->boxFlex()/totalFlex));
+                            if (spaceAdd) {
+                                child->setOverrideSize(child->overrideWidth() + spaceAdd);
+                                m_flexingChildren = true;
+                                relayoutChildren = true;
+                            }
+
+                            spaceAvailableThisPass -= spaceAdd;
+                            remainingSpace -= spaceAdd;
+                            groupRemainingSpace -= spaceAdd;
+                            
+                            totalFlex -= child->style()->boxFlex();
+                        }
+                        child = iterator.next();
+                    }
+                    if (groupRemainingSpace == groupRemainingSpaceAtBeginning) {
+                        // this is not advancing, avoid getting stuck by distributing the remaining pixels
+                        child = iterator.first();
+                        int spaceAdd = groupRemainingSpace > 0 ? 1 : -1;
+                        while (child && groupRemainingSpace) {
+                            if (allowedChildFlex(child, expanding, i)) {
+                                child->setOverrideSize(child->overrideWidth() + spaceAdd);
+                                m_flexingChildren = true;
+                                relayoutChildren = true;
+                                remainingSpace -= spaceAdd;
+                                groupRemainingSpace -= spaceAdd;
+                            }
+                            child = iterator.next();
+                        }
+                    }
+                } while (groupRemainingSpace);
+            }
+
+            // We didn't find any children that could grow.
+            if (haveFlex && !m_flexingChildren)
+                haveFlex = false;
+        }
+    } while (haveFlex);
+
+    m_flexingChildren = false;
+    
+    if (remainingSpace > 0 && ((style()->direction() == LTR && style()->boxPack() != BSTART) ||
+                               (style()->direction() == RTL && style()->boxPack() != BEND))) {
+        // Children must be repositioned.
+        int offset = 0;
+        if (style()->boxPack() == BJUSTIFY) {
+            // Determine the total number of children.
+            int totalChildren = 0;
+            child = iterator.first();
+            while (child) {
+                if (child->isPositioned()) {
+                    child = iterator.next();
+                    continue;
+                }
+                totalChildren++;
+                child = iterator.next();
+            }
+
+            // Iterate over the children and space them out according to the
+            // justification level.
+            if (totalChildren > 1) {
+                totalChildren--;
+                bool firstChild = true;
+                child = iterator.first();
+                while (child) {
+                    if (child->isPositioned()) {
+                        child = iterator.next();
+                        continue;
+                    }
+
+                    if (firstChild) {
+                        firstChild = false;
+                        child = iterator.next();
+                        continue;
+                    }
+
+                    offset += remainingSpace/totalChildren;
+                    remainingSpace -= (remainingSpace/totalChildren);
+                    totalChildren--;
+
+                    placeChild(child, child->xPos()+offset, child->yPos());
+                    child = iterator.next();
+                }
+            }
+        } else {
+            if (style()->boxPack() == BCENTER)
+                offset += remainingSpace/2;
+            else // END for LTR, START for RTL
+                offset += remainingSpace;
+            child = iterator.first();
+            while (child) {
+                if (child->isPositioned()) {
+                    child = iterator.next();
+                    continue;
+                }
+                placeChild(child, child->xPos()+offset, child->yPos());
+                child = iterator.next();
+            }
+        }
+    }
+    
+    child = iterator.first();
+    while (child && child->isPositioned()) {
+        child = iterator.next();
+    }
+    
+    if (child) {
+        m_overflowLeft = min(child->xPos() + child->overflowLeft(false), m_overflowLeft);
+
+        RenderObject* lastChild = child;
+        while ((child = iterator.next())) {
+            if (!child->isPositioned())
+                lastChild = child;
+        }
+        m_overflowWidth = max(lastChild->xPos() + lastChild->overflowWidth(false), m_overflowWidth);
+    }
+    
+    // So that the calcHeight in layoutBlock() knows to relayout positioned objects because of
+    // a height change, we revert our height back to the intrinsic height before returning.
+    if (heightSpecified)
+        m_height = oldHeight;
+}
+
+void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
+{
+    int xPos = borderLeft() + paddingLeft();
+    int yPos = borderTop() + paddingTop();
+    if( style()->direction() == RTL )
+        xPos = m_width - paddingRight() - borderRight();
+    int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
+    bool heightSpecified = false;
+    int oldHeight = 0;
+    
+    unsigned int highestFlexGroup = 0;
+    unsigned int lowestFlexGroup = 0;
+    bool haveFlex = false;
+    int remainingSpace = 0;
+    
+    // The first walk over our kids is to find out if we have any flexible children.
+    FlexBoxIterator iterator(this);
+    RenderObject *child = iterator.next();
+    while (child) {
+        // Check to see if this child flexes.
+        if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) {
+            // We always have to lay out flexible objects again, since the flex distribution
+            // may have changed, and we need to reallocate space.
+            child->setOverrideSize(-1);
+            if (!relayoutChildren)
+                child->setChildNeedsLayout(true, false);
+            haveFlex = true;
+            unsigned int flexGroup = child->style()->boxFlexGroup();
+            if (lowestFlexGroup == 0)
+                lowestFlexGroup = flexGroup;
+            if (flexGroup < lowestFlexGroup)
+                lowestFlexGroup = flexGroup;
+            if (flexGroup > highestFlexGroup)
+                highestFlexGroup = flexGroup;
+        }
+        child = iterator.next();
+    }
+
+    // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of
+    // mainstream block layout); this is not really part of the XUL box model.
+    bool haveLineClamp = style()->lineClamp() >= 0 && style()->lineClamp() <= 100;
+    if (haveLineClamp) {
+        int maxLineCount = 0;
+        child = iterator.first();
+        while (child) {
+            if (!child->isPositioned()) {
+                if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())) ||
+                    (child->style()->height().isAuto() && child->isBlockFlow() && !child->needsLayout())) {
+                    child->setChildNeedsLayout(true, false);
+                    
+                    // Dirty all the positioned objects.
+                    if (child->isRenderBlock()) {
+                        static_cast<RenderBlock*>(child)->markPositionedObjectsForLayout();
+                        static_cast<RenderBlock*>(child)->clearTruncation();
+                    }
+                }
+                child->layoutIfNeeded();
+                if (child->style()->height().isAuto() && child->isBlockFlow())
+                    maxLineCount = max(maxLineCount, static_cast<RenderBlock*>(child)->lineCount());
+            }
+            child = iterator.next();
+        }
+        
+        // Get the # of lines and then alter all block flow children with auto height to use the
+        // specified height. We always try to leave room for at least one line.
+        int numVisibleLines = max(1, static_cast<int>((maxLineCount + 1) * style()->lineClamp() / 100.0));
+        if (numVisibleLines < maxLineCount) {
+            for (child = iterator.first(); child; child = iterator.next()) {
+                if (child->isPositioned() || !child->style()->height().isAuto() || !child->isBlockFlow())
+                    continue;
+                
+                RenderBlock* blockChild = static_cast<RenderBlock*>(child);
+                int lineCount = blockChild->lineCount();
+                if (lineCount <= numVisibleLines)
+                    continue;
+                
+                int newHeight = blockChild->heightForLineCount(numVisibleLines);
+                if (newHeight == child->height())
+                    continue;
+                
+                child->setChildNeedsLayout(true, false);
+                child->setOverrideSize(newHeight);
+                m_flexingChildren = true;
+                child->layoutIfNeeded();
+                m_flexingChildren = false;
+                child->setOverrideSize(-1);
+                
+                // FIXME: For now don't support RTL.
+                if (style()->direction() != LTR)
+                    continue;
+                
+                // Get the last line
+                RootInlineBox* lastLine = blockChild->lineAtIndex(lineCount-1);
+                if (!lastLine)
+                    continue;
+                
+                // See if the last item is an anchor
+                InlineBox* anchorBox = lastLine->lastChild();
+                if (!anchorBox)
+                    continue;
+                if (!anchorBox->object()->element())
+                    continue;
+                if (!anchorBox->object()->element()->isLink())
+                    continue;
+                
+                RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines-1);
+                if (!lastVisibleLine)
+                    continue;
+
+                const UChar ellipsisAndSpace[2] = { horizontalEllipsis, ' ' };
+                static AtomicString ellipsisAndSpaceStr(ellipsisAndSpace, 2);
+
+                const Font& font = style(numVisibleLines == 1)->font();
+                int ellipsisAndSpaceWidth = font.width(TextRun(ellipsisAndSpace, 2));
+
+                // Get ellipsis width + " " + anchor width
+                int totalWidth = ellipsisAndSpaceWidth + anchorBox->width();
+                
+                // See if this width can be accommodated on the last visible line
+                RenderBlock* destBlock = static_cast<RenderBlock*>(lastVisibleLine->object());
+                RenderBlock* srcBlock = static_cast<RenderBlock*>(lastLine->object());
+                
+                // FIXME: Directions of src/destBlock could be different from our direction and from one another.
+                if (srcBlock->style()->direction() != LTR)
+                    continue;
+                if (destBlock->style()->direction() != LTR)
+                    continue;
+
+                int blockEdge = destBlock->rightOffset(lastVisibleLine->yPos());
+                if (!lastVisibleLine->canAccommodateEllipsis(true, blockEdge, 
+                                                             lastVisibleLine->xPos() + lastVisibleLine->width(),
+                                                             totalWidth))
+                    continue;
+
+                // Let the truncation code kick in.
+                lastVisibleLine->placeEllipsis(ellipsisAndSpaceStr, true, blockEdge, totalWidth, anchorBox);
+                destBlock->setHasMarkupTruncation(true);
+            }
+        }
+    }
+
+    // We do 2 passes.  The first pass is simply to lay everyone out at
+    // their preferred widths.  The second pass handles flexing the children.
+    // Our first pass is done without flexing.  We simply lay the children
+    // out within the box.
+    do {
+        m_height = borderTop() + paddingTop();
+        int minHeight = m_height + toAdd;
+        m_overflowHeight = m_height;
+
+        child = iterator.first();
+        while (child) {
+            // make sure we relayout children if we need it.
+            if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))))
+                child->setChildNeedsLayout(true, false);
+    
+            if (child->isPositioned())
+            {
+                child->containingBlock()->insertPositionedObject(child);
+                if (child->hasStaticX()) {
+                    if (style()->direction() == LTR)
+                        child->setStaticX(borderLeft()+paddingLeft());
+                    else
+                        child->setStaticX(borderRight()+paddingRight());
+                }
+                if (child->hasStaticY())
+                    child->setStaticY(m_height);
+                child = iterator.next();
+                continue;
+            } 
+    
+            // Compute the child's vertical margins.
+            child->calcVerticalMargins();
+    
+            // Add in the child's marginTop to our height.
+            m_height += child->marginTop();
+    
+            // Now do a layout.
+            child->layoutIfNeeded();
+    
+            // We can place the child now, using our value of box-align.
+            int childX = borderLeft() + paddingLeft();
+            switch (style()->boxAlign()) {
+                case BCENTER:
+                case BBASELINE: // Baseline just maps to center for vertical boxes
+                    childX += child->marginLeft() + max(0, (contentWidth() - (child->width() + child->marginLeft() + child->marginRight()))/2);
+                    break;
+                case BEND:
+                    if (style()->direction() == RTL)
+                        childX += child->marginLeft();
+                    else
+                        childX += contentWidth() - child->marginRight() - child->width();
+                    break;
+                default: // BSTART/BSTRETCH
+                    if (style()->direction() == LTR)
+                        childX += child->marginLeft();
+                    else
+                        childX += contentWidth() - child->marginRight() - child->width();
+                    break;
+            }
+    
+            // Place the child.
+            placeChild(child, childX, m_height);
+            m_height += child->height() + child->marginBottom();
+    
+            if (child->isRenderBlock())
+                static_cast<RenderBlock*>(child)->addVisualOverflow(static_cast<RenderBlock*>(child)->floatRect());
+
+            // See if this child has made our overflow need to grow.
+            m_overflowWidth = max(child->xPos() + child->overflowWidth(false), m_overflowWidth);
+            m_overflowLeft = min(child->xPos() + child->overflowLeft(false), m_overflowLeft);
+            
+            child = iterator.next();
+        }
+
+        yPos = m_height;
+        
+        if (!iterator.first() && hasLineIfEmpty())
+            m_height += lineHeight(true, true);
+    
+        m_height += toAdd;
+
+        // Negative margins can cause our height to shrink below our minimal height (border/padding).
+        // If this happens, ensure that the computed height is increased to the minimal height.
+        if (m_height < minHeight)
+            m_height = minHeight;
+
+        // Always make sure our overflowheight is at least our height.
+        if (m_overflowHeight < m_height)
+            m_overflowHeight = m_height;
+
+        // Now we have to calc our height, so we know how much space we have remaining.
+        oldHeight = m_height;
+        calcHeight();
+        if (oldHeight != m_height)
+            heightSpecified = true;
+
+        remainingSpace = borderTop() + paddingTop() + contentHeight() - yPos;
+        
+        if (m_flexingChildren)
+            haveFlex = false; // We're done.
+        else if (haveFlex) {
+            // We have some flexible objects.  See if we need to grow/shrink them at all.
+            if (!remainingSpace)
+                break;
+
+            // Allocate the remaining space among the flexible objects.  If we are trying to
+            // grow, then we go from the lowest flex group to the highest flex group.  For shrinking,
+            // we go from the highest flex group to the lowest group.
+            bool expanding = remainingSpace > 0;
+            unsigned int start = expanding ? lowestFlexGroup : highestFlexGroup;
+            unsigned int end = expanding? highestFlexGroup : lowestFlexGroup;
+            for (unsigned int i = start; i <= end && remainingSpace; i++) {
+                // Always start off by assuming the group can get all the remaining space.
+                int groupRemainingSpace = remainingSpace;
+                do {
+                    // Flexing consists of multiple passes, since we have to change ratios every time an object hits its max/min-width
+                    // For a given pass, we always start off by computing the totalFlex of all objects that can grow/shrink at all, and
+                    // computing the allowed growth before an object hits its min/max width (and thus
+                    // forces a totalFlex recomputation).
+                    int groupRemainingSpaceAtBeginning = groupRemainingSpace;
+                    float totalFlex = 0.0f;
+                    child = iterator.first();
+                    while (child) {
+                        if (allowedChildFlex(child, expanding, i))
+                            totalFlex += child->style()->boxFlex();
+                        child = iterator.next();
+                    }
+                    child = iterator.first();
+                    int spaceAvailableThisPass = groupRemainingSpace;
+                    while (child) {
+                        int allowedFlex = allowedChildFlex(child, expanding, i);
+                        if (allowedFlex) {
+                            int projectedFlex = (allowedFlex == INT_MAX) ? allowedFlex : (int)(allowedFlex * (totalFlex / child->style()->boxFlex()));
+                            spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
+                        }
+                        child = iterator.next();
+                    }
+
+                    // The flex groups may not have any flexible objects this time around. 
+                    if (!spaceAvailableThisPass || totalFlex == 0.0f) {
+                        // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group.
+                        groupRemainingSpace = 0;
+                        continue;
+                    }
+            
+                    // Now distribute the space to objects.
+                    child = iterator.first();
+                    while (child && spaceAvailableThisPass && totalFlex) {
+                        if (allowedChildFlex(child, expanding, i)) {
+                            int spaceAdd = (int)(spaceAvailableThisPass * (child->style()->boxFlex()/totalFlex));
+                            if (spaceAdd) {
+                                child->setOverrideSize(child->overrideHeight() + spaceAdd);
+                                m_flexingChildren = true;
+                                relayoutChildren = true;
+                            }
+
+                            spaceAvailableThisPass -= spaceAdd;
+                            remainingSpace -= spaceAdd;
+                            groupRemainingSpace -= spaceAdd;
+                            
+                            totalFlex -= child->style()->boxFlex();
+                        }
+                        child = iterator.next();
+                    }
+                    if (groupRemainingSpace == groupRemainingSpaceAtBeginning) {
+                        // this is not advancing, avoid getting stuck by distributing the remaining pixels
+                        child = iterator.first();
+                        int spaceAdd = groupRemainingSpace > 0 ? 1 : -1;
+                        while (child && groupRemainingSpace) {
+                            if (allowedChildFlex(child, expanding, i)) {
+                                child->setOverrideSize(child->overrideHeight() + spaceAdd);
+                                m_flexingChildren = true;
+                                relayoutChildren = true;
+                                remainingSpace -= spaceAdd;
+                                groupRemainingSpace -= spaceAdd;
+                            }
+                            child = iterator.next();
+                        }
+                    }
+                } while (groupRemainingSpace);
+            }
+
+            // We didn't find any children that could grow.
+            if (haveFlex && !m_flexingChildren)
+                haveFlex = false;
+        }        
+    } while (haveFlex);
+
+    if (style()->boxPack() != BSTART && remainingSpace > 0) {
+        // Children must be repositioned.
+        int offset = 0;
+        if (style()->boxPack() == BJUSTIFY) {
+            // Determine the total number of children.
+            int totalChildren = 0;
+            child = iterator.first();
+            while (child) {
+                if (child->isPositioned()) {
+                    child = iterator.next();
+                    continue;
+                }
+                totalChildren++;
+                child = iterator.next();
+            }
+            
+            // Iterate over the children and space them out according to the
+            // justification level.
+            if (totalChildren > 1) {
+                totalChildren--;
+                bool firstChild = true;
+                child = iterator.first();
+                while (child) {
+                    if (child->isPositioned()) {
+                        child = iterator.next();
+                        continue;
+                    }
+                    
+                    if (firstChild) {
+                        firstChild = false;
+                        child = iterator.next();
+                        continue;
+                    }
+
+                    offset += remainingSpace/totalChildren;
+                    remainingSpace -= (remainingSpace/totalChildren);
+                    totalChildren--;
+                    placeChild(child, child->xPos(), child->yPos()+offset);
+                    child = iterator.next();
+                }
+            }
+        } else {
+            if (style()->boxPack() == BCENTER)
+                offset += remainingSpace/2;
+            else // END
+                offset += remainingSpace;
+            child = iterator.first();
+            while (child) {
+                if (child->isPositioned()) {
+                    child = iterator.next();
+                    continue;
+                }
+                placeChild(child, child->xPos(), child->yPos()+offset);
+                child = iterator.next();
+            }
+        }
+    }
+    
+    child = iterator.first();
+    while (child && child->isPositioned()) {
+        child = iterator.next();
+    }
+    
+    if (child) {
+        m_overflowTop = min(child->yPos() + child->overflowTop(false), m_overflowTop);
+
+        RenderObject* lastChild = child;
+        while ((child = iterator.next())) {
+            if (!child->isPositioned())
+                lastChild = child;
+        }
+        m_overflowHeight = max(lastChild->yPos() + lastChild->overflowHeight(false), m_overflowHeight);
+    }
+
+    // So that the calcHeight in layoutBlock() knows to relayout positioned objects because of
+    // a height change, we revert our height back to the intrinsic height before returning.
+    if (heightSpecified)
+        m_height = oldHeight; 
+}
+
+void RenderFlexibleBox::placeChild(RenderObject* child, int x, int y)
+{
+    IntRect oldRect(child->xPos(), child->yPos() , child->width(), child->height());
+
+    // Place the child.
+    child->setPos(x, y);
+
+    // If the child moved, we have to repaint it as well as any floating/positioned
+    // descendants.  An exception is if we need a layout.  In this case, we know we're going to
+    // repaint ourselves (and the child) anyway.
+    if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
+        child->repaintDuringLayoutIfMoved(oldRect);
+}
+
+int RenderFlexibleBox::allowedChildFlex(RenderObject* child, bool expanding, unsigned int group)
+{
+    if (child->isPositioned() || child->style()->boxFlex() == 0.0f || child->style()->boxFlexGroup() != group)
+        return 0;
+                        
+    if (expanding) {
+        if (isHorizontal()) {
+            // FIXME: For now just handle fixed values.
+            int maxW = INT_MAX;
+            int w = child->overrideWidth() - (child->borderLeft() + child->borderRight() + child->paddingLeft() + child->paddingRight());
+            if (!child->style()->maxWidth().isUndefined() &&
+                child->style()->maxWidth().isFixed())
+                maxW = child->style()->maxWidth().value();
+            else if (child->style()->maxWidth().type() == Intrinsic)
+                maxW = child->maxPrefWidth();
+            else if (child->style()->maxWidth().type() == MinIntrinsic)
+                maxW = child->minPrefWidth();
+            if (maxW == INT_MAX)
+                return maxW;
+            return max(0, maxW - w);
+        } else {
+            // FIXME: For now just handle fixed values.
+            int maxH = INT_MAX;
+            int h = child->overrideHeight() - (child->borderTop() + child->borderBottom() + child->paddingTop() + child->paddingBottom());
+            if (!child->style()->maxHeight().isUndefined() &&
+                child->style()->maxHeight().isFixed())
+                maxH = child->style()->maxHeight().value();
+            if (maxH == INT_MAX)
+                return maxH;
+            return max(0, maxH - h);
+        }
+    }
+
+    // FIXME: For now just handle fixed values.
+    if (isHorizontal()) {
+        int minW = child->minPrefWidth();
+        int w = child->overrideWidth() - (child->borderLeft() + child->borderRight() + child->paddingLeft() + child->paddingRight());
+        if (child->style()->minWidth().isFixed())
+            minW = child->style()->minWidth().value();
+        else if (child->style()->minWidth().type() == Intrinsic)
+            minW = child->maxPrefWidth();
+        else if (child->style()->minWidth().type() == MinIntrinsic)
+            minW = child->minPrefWidth();
+            
+        int allowedShrinkage = min(0, minW - w);
+        return allowedShrinkage;
+    } else {
+        if (child->style()->minHeight().isFixed()) {
+            int minH = child->style()->minHeight().value();
+            int h = child->overrideHeight() - (child->borderLeft() + child->borderRight() + child->paddingLeft() + child->paddingRight());
+            int allowedShrinkage = min(0, minH - h);
+            return allowedShrinkage;
+        }
+    }
+    
+    return 0;
+}
+
+const char *RenderFlexibleBox::renderName() const
+{
+    if (isFloating())
+        return "RenderFlexibleBox (floating)";
+    if (isPositioned())
+        return "RenderFlexibleBox (positioned)";
+    if (isRelPositioned())
+        return "RenderFlexibleBox (relative positioned)";
+    return "RenderFlexibleBox";
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderFlexibleBox.h b/WebCore/rendering/RenderFlexibleBox.h
new file mode 100644
index 0000000..f48caf5
--- /dev/null
+++ b/WebCore/rendering/RenderFlexibleBox.h
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the render object implementation for KHTML.
+ *
+ * Copyright (C) 2003 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderFlexibleBox_h
+#define RenderFlexibleBox_h
+
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+class RenderFlexibleBox : public RenderBlock {
+public:
+    RenderFlexibleBox(Node*);
+    virtual ~RenderFlexibleBox();
+
+    virtual const char* renderName() const;
+
+    virtual void calcPrefWidths();
+    void calcHorizontalPrefWidths();
+    void calcVerticalPrefWidths();
+
+    virtual void layoutBlock(bool relayoutChildren);
+    void layoutHorizontalBox(bool relayoutChildren);
+    void layoutVerticalBox(bool relayoutChildren);
+
+    virtual bool avoidsFloats() const { return true; }
+
+    virtual bool isFlexibleBox() const { return true; }
+    virtual bool isFlexingChildren() const { return m_flexingChildren; }
+    virtual bool isStretchingChildren() const { return m_stretchingChildren; }
+
+    void placeChild(RenderObject* child, int x, int y);
+
+protected:
+    int allowedChildFlex(RenderObject* child, bool expanding, unsigned group);
+
+    bool hasMultipleLines() const { return style()->boxLines() == MULTIPLE; }
+    bool isVertical() const { return style()->boxOrient() == VERTICAL; }
+    bool isHorizontal() const { return style()->boxOrient() == HORIZONTAL; }
+
+    bool m_flexingChildren : 1;
+    bool m_stretchingChildren : 1;
+};
+
+} // namespace WebCore
+
+#endif // RenderFlexibleBox_h
diff --git a/WebCore/rendering/RenderFlow.cpp b/WebCore/rendering/RenderFlow.cpp
new file mode 100644
index 0000000..eb689cf
--- /dev/null
+++ b/WebCore/rendering/RenderFlow.cpp
@@ -0,0 +1,888 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RenderFlow.h"
+
+#include "Document.h"
+#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "InlineTextBox.h"
+#include "RenderArena.h"
+#include "RenderInline.h"
+#include "RenderLayer.h"
+#include "RenderView.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+#ifndef NDEBUG
+
+RenderFlow::~RenderFlow()
+{
+    ASSERT(!m_firstLineBox);
+    ASSERT(!m_lastLineBox);
+}
+
+#endif
+
+RenderFlow* RenderFlow::createAnonymousFlow(Document* doc, PassRefPtr<RenderStyle> style)
+{
+    RenderFlow* result;
+    if (style->display() == INLINE)
+        result = new (doc->renderArena()) RenderInline(doc);
+    else
+        result = new (doc->renderArena()) RenderBlock(doc);
+    result->setStyle(style);
+    return result;
+}
+
+RenderFlow* RenderFlow::continuationBefore(RenderObject* beforeChild)
+{
+    if (beforeChild && beforeChild->parent() == this)
+        return this;
+
+    RenderFlow* curr = continuation();
+    RenderFlow* nextToLast = this;
+    RenderFlow* last = this;
+    while (curr) {
+        if (beforeChild && beforeChild->parent() == curr) {
+            if (curr->firstChild() == beforeChild)
+                return last;
+            return curr;
+        }
+
+        nextToLast = last;
+        last = curr;
+        curr = curr->continuation();
+    }
+
+    if (!beforeChild && !last->firstChild())
+        return nextToLast;
+    return last;
+}
+
+void RenderFlow::addChildWithContinuation(RenderObject* newChild, RenderObject* beforeChild)
+{
+    if (beforeChild && (beforeChild->parent()->isTableRow() || beforeChild->parent()->isTableSection() || beforeChild->parent()->isTable())) {
+        RenderObject* anonymousTablePart = beforeChild->parent();
+        ASSERT(anonymousTablePart->isAnonymous());
+        while (!anonymousTablePart->isTable()) {
+            anonymousTablePart = anonymousTablePart->parent();
+            ASSERT(anonymousTablePart->isAnonymous());
+        }
+        return anonymousTablePart->addChild(newChild, beforeChild);
+    }
+
+    RenderFlow* flow = continuationBefore(beforeChild);
+    ASSERT(!beforeChild || beforeChild->parent()->isRenderBlock() ||
+                beforeChild->parent()->isRenderInline());
+    RenderFlow* beforeChildParent = beforeChild ? static_cast<RenderFlow*>(beforeChild->parent()) : 
+                                    (flow->continuation() ? flow->continuation() : flow);
+
+    if (newChild->isFloatingOrPositioned())
+        return beforeChildParent->addChildToFlow(newChild, beforeChild);
+
+    // A continuation always consists of two potential candidates: an inline or an anonymous
+    // block box holding block children.
+    bool childInline = newChild->isInline();
+    bool bcpInline = beforeChildParent->isInline();
+    bool flowInline = flow->isInline();
+
+    if (flow == beforeChildParent)
+        return flow->addChildToFlow(newChild, beforeChild);
+    else {
+        // The goal here is to match up if we can, so that we can coalesce and create the
+        // minimal # of continuations needed for the inline.
+        if (childInline == bcpInline)
+            return beforeChildParent->addChildToFlow(newChild, beforeChild);
+        else if (flowInline == childInline)
+            return flow->addChildToFlow(newChild, 0); // Just treat like an append.
+        else
+            return beforeChildParent->addChildToFlow(newChild, beforeChild);
+    }
+}
+
+void RenderFlow::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    if (continuation())
+        return addChildWithContinuation(newChild, beforeChild);
+    return addChildToFlow(newChild, beforeChild);
+}
+
+void RenderFlow::extractLineBox(InlineFlowBox* box)
+{
+    checkConsistency();
+
+    m_lastLineBox = box->prevFlowBox();
+    if (box == m_firstLineBox)
+        m_firstLineBox = 0;
+    if (box->prevLineBox())
+        box->prevLineBox()->setNextLineBox(0);
+    box->setPreviousLineBox(0);
+    for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox())
+        curr->setExtracted();
+
+    checkConsistency();
+}
+
+void RenderFlow::attachLineBox(InlineFlowBox* box)
+{
+    checkConsistency();
+
+    if (m_lastLineBox) {
+        m_lastLineBox->setNextLineBox(box);
+        box->setPreviousLineBox(m_lastLineBox);
+    } else
+        m_firstLineBox = box;
+    InlineFlowBox* last = box;
+    for (InlineFlowBox* curr = box; curr; curr = curr->nextFlowBox()) {
+        curr->setExtracted(false);
+        last = curr;
+    }
+    m_lastLineBox = last;
+
+    checkConsistency();
+}
+
+void RenderFlow::removeLineBox(InlineFlowBox* box)
+{
+    checkConsistency();
+
+    if (box == m_firstLineBox)
+        m_firstLineBox = box->nextFlowBox();
+    if (box == m_lastLineBox)
+        m_lastLineBox = box->prevFlowBox();
+    if (box->nextLineBox())
+        box->nextLineBox()->setPreviousLineBox(box->prevLineBox());
+    if (box->prevLineBox())
+        box->prevLineBox()->setNextLineBox(box->nextLineBox());
+
+    checkConsistency();
+}
+
+void RenderFlow::deleteLineBoxes()
+{
+    if (m_firstLineBox) {
+        RenderArena* arena = renderArena();
+        InlineRunBox* next;
+        for (InlineRunBox* curr = m_firstLineBox; curr; curr = next) {
+            next = curr->nextLineBox();
+            curr->destroy(arena);
+        }
+        m_firstLineBox = 0;
+        m_lastLineBox = 0;
+    }
+}
+
+void RenderFlow::destroy()
+{
+    // Detach our continuation first.
+    if (m_continuation)
+        m_continuation->destroy();
+    m_continuation = 0;
+
+    // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
+    // properly dirty line boxes that they are removed from.  Effects that do :before/:after only on hover could crash otherwise.
+    RenderContainer::destroyLeftoverChildren();
+
+    if (!documentBeingDestroyed()) {
+        if (m_firstLineBox) {
+            // We can't wait for RenderContainer::destroy to clear the selection,
+            // because by then we will have nuked the line boxes.
+            // FIXME: The SelectionController should be responsible for this when it
+            // is notified of DOM mutations.
+            if (isSelectionBorder())
+                view()->clearSelection();
+
+            // If line boxes are contained inside a root, that means we're an inline.
+            // In that case, we need to remove all the line boxes so that the parent
+            // lines aren't pointing to deleted children. If the first line box does
+            // not have a parent that means they are either already disconnected or
+            // root lines that can just be destroyed without disconnecting.
+            if (m_firstLineBox->parent()) {
+                for (InlineRunBox* box = m_firstLineBox; box; box = box->nextLineBox())
+                    box->remove();
+            }
+
+            // If we are an anonymous block, then our line boxes might have children
+            // that will outlast this block. In the non-anonymous block case those
+            // children will be destroyed by the time we return from this function.
+            if (isAnonymousBlock()) {
+                for (InlineFlowBox* box = m_firstLineBox; box; box = box->nextFlowBox()) {
+                    while (InlineBox* childBox = box->firstChild())
+                        childBox->remove();
+                }
+            }
+        } else if (isInline() && parent())
+            parent()->dirtyLinesFromChangedChild(this);
+    }
+
+    deleteLineBoxes();
+
+    RenderContainer::destroy();
+}
+
+void RenderFlow::dirtyLinesFromChangedChild(RenderObject* child)
+{
+    if (!parent() || (selfNeedsLayout() && !isInlineFlow()) || isTable())
+        return;
+
+    // If we have no first line box, then just bail early.
+    if (!firstLineBox()) {
+        // For an empty inline, go ahead and propagate the check up to our parent, unless the parent
+        // is already dirty.
+        if (isInline() && !parent()->selfNeedsLayout())
+            parent()->dirtyLinesFromChangedChild(this);
+        return;
+    }
+
+    // Try to figure out which line box we belong in.  First try to find a previous
+    // line box by examining our siblings.  If we didn't find a line box, then use our 
+    // parent's first line box.
+    RootInlineBox* box = 0;
+    RenderObject* curr = 0;
+    for (curr = child->previousSibling(); curr; curr = curr->previousSibling()) {
+        if (curr->isFloatingOrPositioned())
+            continue;
+
+        if (curr->isReplaced()) {
+            InlineBox* wrapper = curr->inlineBoxWrapper();
+            if (wrapper)
+                box = wrapper->root();
+        } else if (curr->isText()) {
+            InlineTextBox* textBox = static_cast<RenderText*>(curr)->lastTextBox();
+            if (textBox)
+                box = textBox->root();
+        } else if (curr->isInlineFlow()) {
+            InlineRunBox* runBox = static_cast<RenderFlow*>(curr)->lastLineBox();
+            if (runBox)
+                box = runBox->root();
+        }
+
+        if (box)
+            break;
+    }
+    if (!box)
+        box = firstLineBox()->root();
+
+    // If we found a line box, then dirty it.
+    if (box) {
+        RootInlineBox* adjacentBox;
+        box->markDirty();
+
+        // dirty the adjacent lines that might be affected
+        // NOTE: we dirty the previous line because RootInlineBox objects cache
+        // the address of the first object on the next line after a BR, which we may be
+        // invalidating here.  For more info, see how RenderBlock::layoutInlineChildren
+        // calls setLineBreakInfo with the result of findNextLineBreak.  findNextLineBreak,
+        // despite the name, actually returns the first RenderObject after the BR.
+        // <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize."
+        adjacentBox = box->prevRootBox();
+        if (adjacentBox)
+            adjacentBox->markDirty();
+        if (child->isBR() || (curr && curr->isBR())) {
+            adjacentBox = box->nextRootBox();
+            if (adjacentBox)
+                adjacentBox->markDirty();
+        }
+    }
+}
+
+int RenderFlow::lineHeight(bool firstLine, bool isRootLineBox) const
+{
+    if (firstLine) {
+        RenderStyle* s = style(firstLine);
+        Length lh = s->lineHeight();
+        if (lh.isNegative()) {
+            if (s == style()) {
+                if (m_lineHeight == -1)
+                    m_lineHeight = RenderObject::lineHeight(false);
+                return m_lineHeight;
+            }
+            return s->font().lineSpacing();
+        }
+        if (lh.isPercent())
+            return lh.calcMinValue(s->fontSize());
+        return lh.value();
+    }
+
+    if (m_lineHeight == -1)
+        m_lineHeight = RenderObject::lineHeight(false);
+    return m_lineHeight;
+}
+
+void RenderFlow::dirtyLineBoxes(bool fullLayout, bool isRootLineBox)
+{
+    if (!isRootLineBox && isReplaced())
+        return RenderContainer::dirtyLineBoxes(fullLayout, isRootLineBox);
+
+    if (fullLayout)
+        deleteLineBoxes();
+    else {
+        for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+            curr->dirtyLineBoxes();
+    }
+}
+
+InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun)
+{
+    checkConsistency();
+
+    if (!isRootLineBox &&
+        (isReplaced() || makePlaceHolderBox))                     // Inline tables and inline blocks
+        return RenderContainer::createInlineBox(false, isRootLineBox);  // (or positioned element placeholders).
+
+    InlineFlowBox* flowBox = 0;
+    if (isInlineFlow())
+        flowBox = new (renderArena()) InlineFlowBox(this);
+    else
+        flowBox = new (renderArena()) RootInlineBox(this);
+
+    if (!m_firstLineBox)
+        m_firstLineBox = m_lastLineBox = flowBox;
+    else {
+        m_lastLineBox->setNextLineBox(flowBox);
+        flowBox->setPreviousLineBox(m_lastLineBox);
+        m_lastLineBox = flowBox;
+    }
+
+    checkConsistency();
+
+    return flowBox;
+}
+
+void RenderFlow::paintLines(PaintInfo& paintInfo, int tx, int ty)
+{
+    // Only paint during the foreground/selection phases.
+    if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseOutline 
+        && paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines && paintInfo.phase != PaintPhaseTextClip
+        && paintInfo.phase != PaintPhaseMask)
+        return;
+
+    bool inlineFlow = isInlineFlow();
+    if (inlineFlow)
+        ASSERT(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
+
+    // If we have no lines then we have no work to do.
+    if (!firstLineBox())
+        return;
+
+    // We can check the first box and last box and avoid painting if we don't
+    // intersect.  This is a quick short-circuit that we can take to avoid walking any lines.
+    // FIXME: This check is flawed in the following extremely obscure way:
+    // if some line in the middle has a huge overflow, it might actually extend below the last line.
+    int yPos = firstLineBox()->root()->topOverflow() - maximalOutlineSize(paintInfo.phase);
+    int h = maximalOutlineSize(paintInfo.phase) + lastLineBox()->root()->bottomOverflow() - yPos;
+    yPos += ty;
+    if (yPos >= paintInfo.rect.bottom() || yPos + h <= paintInfo.rect.y())
+        return;
+
+    PaintInfo info(paintInfo);
+    RenderFlowSequencedSet outlineObjects;
+    info.outlineObjects = &outlineObjects;
+
+    // See if our root lines intersect with the dirty rect.  If so, then we paint
+    // them.  Note that boxes can easily overlap, so we can't make any assumptions
+    // based off positions of our first line box or our last line box.
+    RenderView* v = view();
+    bool usePrintRect = !v->printRect().isEmpty();
+    for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) {
+        if (usePrintRect) {
+            // FIXME: This is a feeble effort to avoid splitting a line across two pages.
+            // It is utterly inadequate, and this should not be done at paint time at all.
+            // The whole way objects break across pages needs to be redone.
+            // Try to avoid splitting a line vertically, but only if it's less than the height
+            // of the entire page.
+            if (curr->root()->bottomOverflow() - curr->root()->topOverflow() <= v->printRect().height()) {
+                if (ty + curr->root()->bottomOverflow() > v->printRect().bottom()) {
+                    if (ty + curr->root()->topOverflow() < v->truncatedAt())
+                        v->setBestTruncatedAt(ty + curr->root()->topOverflow(), this);
+                    // If we were able to truncate, don't paint.
+                    if (ty + curr->root()->topOverflow() >= v->truncatedAt())
+                        break;
+                }
+            }
+        }
+
+        int top = min(curr->root()->topOverflow(), curr->root()->selectionTop()) - maximalOutlineSize(info.phase);
+        int bottom = curr->root()->bottomOverflow() + maximalOutlineSize(info.phase);
+        h = bottom - top;
+        yPos = ty + top;
+        if (yPos < info.rect.bottom() && yPos + h > info.rect.y())
+            curr->paint(info, tx, ty);
+    }
+
+    if (info.phase == PaintPhaseOutline || info.phase == PaintPhaseSelfOutline || info.phase == PaintPhaseChildOutlines) {
+        RenderFlowSequencedSet::iterator end = info.outlineObjects->end();
+        for (RenderFlowSequencedSet::iterator it = info.outlineObjects->begin(); it != end; ++it) {
+            RenderFlow* flow = *it;
+            flow->paintOutline(info.context, tx, ty);
+        }
+        info.outlineObjects->clear();
+    }
+}
+
+bool RenderFlow::hitTestLines(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
+{
+    if (hitTestAction != HitTestForeground)
+        return false;
+
+    bool inlineFlow = isInlineFlow();
+    if (inlineFlow)
+        ASSERT(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
+
+    // If we have no lines then we have no work to do.
+    if (!firstLineBox())
+        return false;
+
+    // We can check the first box and last box and avoid hit testing if we don't
+    // contain the point.  This is a quick short-circuit that we can take to avoid walking any lines.
+    // FIXME: This check is flawed in the following extremely obscure way:
+    // if some line in the middle has a huge overflow, it might actually extend below the last line.
+    if ((y >= ty + lastLineBox()->root()->bottomOverflow()) || (y < ty + firstLineBox()->root()->topOverflow()))
+        return false;
+
+    // See if our root lines contain the point.  If so, then we hit test
+    // them further.  Note that boxes can easily overlap, so we can't make any assumptions
+    // based off positions of our first line box or our last line box.
+    for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevFlowBox()) {
+        if (y >= ty + curr->root()->topOverflow() && y < ty + curr->root()->bottomOverflow()) {
+            bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty);
+            if (inside) {
+                updateHitTestResult(result, IntPoint(x - tx, y - ty));
+                return true;
+            }
+        }
+    }
+    
+    return false;
+}
+
+IntRect RenderFlow::absoluteClippedOverflowRect()
+{
+    if (isInlineFlow()) {
+        // Only compacts and run-ins are allowed in here during layout.
+        ASSERT(!view() || !view()->layoutState() || isCompact() || isRunIn());
+
+        if (!firstLineBox() && !continuation())
+            return IntRect();
+
+        // Find our leftmost position.
+        int left = 0;
+        int top = firstLineBox() ? firstLineBox()->yPos() : 0;
+        for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+            if (curr == firstLineBox() || curr->xPos() < left)
+                left = curr->xPos();
+        }
+
+        // Now invalidate a rectangle.
+        int ow = style() ? style()->outlineSize() : 0;
+        if (isCompact())
+            left -= m_x;
+        
+        // We need to add in the relative position offsets of any inlines (including us) up to our
+        // containing block.
+        RenderBlock* cb = containingBlock();
+        for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isInlineFlow() && inlineFlow != cb; 
+             inlineFlow = inlineFlow->parent()) {
+             if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer())
+                inlineFlow->layer()->relativePositionOffset(left, top);
+        }
+
+        IntRect r(-ow + left, -ow + top, width() + ow * 2, height() + ow * 2);
+        if (cb->hasColumns())
+            cb->adjustRectForColumns(r);
+
+        if (cb->hasOverflowClip()) {
+            // cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the
+            // layer's size instead.  Even if the layer's size is wrong, the layer itself will repaint
+            // anyway if its size does change.
+            int x = r.x();
+            int y = r.y();
+            IntRect boxRect(0, 0, cb->layer()->width(), cb->layer()->height());
+            cb->layer()->subtractScrollOffset(x, y); // For overflow:auto/scroll/hidden.
+            IntRect repaintRect(x, y, r.width(), r.height());
+            r = intersection(repaintRect, boxRect);
+        }
+        cb->computeAbsoluteRepaintRect(r);
+
+        if (ow) {
+            for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+                if (!curr->isText()) {
+                    IntRect childRect = curr->getAbsoluteRepaintRectWithOutline(ow);
+                    r.unite(childRect);
+                }
+            }
+
+            if (continuation() && !continuation()->isInline()) {
+                IntRect contRect = continuation()->getAbsoluteRepaintRectWithOutline(ow);
+                r.unite(contRect);
+            }
+        }
+
+        return r;
+    }
+
+    return RenderContainer::absoluteClippedOverflowRect();
+}
+
+int RenderFlow::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    ASSERT(!isInlineFlow());
+    if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
+        return includeSelf && m_width > 0 ? overflowHeight(false) : 0;
+
+    int bottom = includeSelf && m_width > 0 ? m_height : 0;
+    if (!hasColumns()) {
+        // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
+        // For now, we have to descend into all the children, since we may have a huge abs div inside
+        // a tiny rel div buried somewhere deep in our child tree.  In this case we have to get to
+        // the abs div.
+        for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
+            if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow())
+                bottom = max(bottom, c->yPos() + c->lowestPosition(false));
+        }
+    }
+
+    if (includeSelf && isRelPositioned())
+        bottom += relativePositionOffsetY();         
+
+    return bottom;
+}
+
+int RenderFlow::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    ASSERT(!isInlineFlow());
+    if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
+        return includeSelf && m_height > 0 ? overflowWidth(false) : 0;
+
+    int right = includeSelf && m_height > 0 ? m_width : 0;
+    if (!hasColumns()) {
+        // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
+        // For now, we have to descend into all the children, since we may have a huge abs div inside
+        // a tiny rel div buried somewhere deep in our child tree.  In this case we have to get to
+        // the abs div.
+        for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
+            if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow())
+                right = max(right, c->xPos() + c->rightmostPosition(false));
+        }
+    }
+
+    if (includeSelf && isRelPositioned())
+        right += relativePositionOffsetX();
+
+    return right;
+}
+
+int RenderFlow::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    ASSERT(!isInlineFlow());
+    if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
+        return includeSelf && m_height > 0 ? overflowLeft(false) : m_width;
+
+    int left = includeSelf && m_height > 0 ? 0 : m_width;
+    if (!hasColumns()) {
+        // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
+        // For now, we have to descend into all the children, since we may have a huge abs div inside
+        // a tiny rel div buried somewhere deep in our child tree.  In this case we have to get to
+        // the abs div.
+        for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
+            if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow())
+                left = min(left, c->xPos() + c->leftmostPosition(false));
+        }
+    }
+
+    if (includeSelf && isRelPositioned())
+        left += relativePositionOffsetX(); 
+
+    return left;
+}
+
+IntRect RenderFlow::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
+{
+    // Do the normal calculation in most cases.
+    if (firstChild() || style()->display() == INLINE)
+        return RenderContainer::caretRect(inlineBox, caretOffset, extraWidthToEndOfLine);
+
+    // This is a special case:
+    // The element is not an inline element, and it's empty. So we have to
+    // calculate a fake position to indicate where objects are to be inserted.
+    
+    // FIXME: This does not take into account either :first-line or :first-letter
+    // However, as soon as some content is entered, the line boxes will be
+    // constructed and this kludge is not called any more. So only the caret size
+    // of an empty :first-line'd block is wrong. I think we can live with that.
+    RenderStyle* currentStyle = firstLineStyle();
+    int height = lineHeight(true);
+    const int caretWidth = 1;
+
+    enum CaretAlignment { alignLeft, alignRight, alignCenter };
+
+    CaretAlignment alignment = alignLeft;
+
+    switch (currentStyle->textAlign()) {
+        case TAAUTO:
+        case JUSTIFY:
+            if (currentStyle->direction() == RTL)
+                alignment = alignRight;
+            break;
+        case LEFT:
+        case WEBKIT_LEFT:
+            break;
+        case CENTER:
+        case WEBKIT_CENTER:
+            alignment = alignCenter;
+            break;
+        case RIGHT:
+        case WEBKIT_RIGHT:
+            alignment = alignRight;
+            break;
+    }
+
+    int x = borderLeft() + paddingLeft();
+    int w = width();
+
+    switch (alignment) {
+        case alignLeft:
+            break;
+        case alignCenter:
+            x = (x + w - (borderRight() + paddingRight())) / 2;
+            break;
+        case alignRight:
+            x = w - (borderRight() + paddingRight());
+            break;
+    }
+
+    if (extraWidthToEndOfLine) {
+        if (isRenderBlock()) {
+            *extraWidthToEndOfLine = w - (x + caretWidth);
+        } else {
+            // FIXME: This code looks wrong.
+            // myRight and containerRight are set up, but then clobbered.
+            // So *extraWidthToEndOfLine will always be 0 here.
+
+            int myRight = x + caretWidth;
+            int ignore;
+            absolutePositionForContent(myRight, ignore);
+
+            int containerRight = containingBlock()->xPos() + containingBlockWidth();
+            absolutePositionForContent(containerRight, ignore);
+
+            *extraWidthToEndOfLine = containerRight - myRight;
+        }
+    }
+
+    int absx, absy;
+    absolutePositionForContent(absx, absy);
+    x += absx;
+    int y = absy + paddingTop() + borderTop();
+
+    return IntRect(x, y, caretWidth, height);
+}
+
+void RenderFlow::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
+{
+    if (isRenderBlock()) {
+        // Continuations should include their margins in the outline rect.
+        if (continuation()) {
+            bool nextInlineHasLineBox = continuation()->firstLineBox();
+            bool prevInlineHasLineBox = static_cast<RenderFlow*>(continuation()->element()->renderer())->firstLineBox();
+            int topMargin = prevInlineHasLineBox ? collapsedMarginTop() : 0;
+            int bottomMargin = nextInlineHasLineBox ? collapsedMarginBottom() : 0;
+            graphicsContext->addFocusRingRect(IntRect(tx, ty - topMargin, 
+                                                      width(), height() + topMargin + bottomMargin));
+        } else
+            graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
+    }
+
+    if (!hasOverflowClip() && !hasControlClip()) {
+        for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+            graphicsContext->addFocusRingRect(IntRect(tx + curr->xPos(), ty + curr->yPos(), curr->width(), curr->height()));
+
+        for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+            if (!curr->isText() && !curr->isListMarker()) {
+                int x = 0;
+                int y = 0;
+                if (curr->layer()) 
+                    curr->absolutePosition(x, y);
+                else {
+                    x = tx + curr->xPos();
+                    y = ty + curr->yPos();
+                }
+                curr->addFocusRingRects(graphicsContext, x, y);
+            }
+    }
+
+    if (continuation()) {
+        if (isInline())
+            continuation()->addFocusRingRects(graphicsContext, 
+                                              tx - containingBlock()->xPos() + continuation()->xPos(),
+                                              ty - containingBlock()->yPos() + continuation()->yPos());
+        else
+            continuation()->addFocusRingRects(graphicsContext, 
+                                              tx - xPos() + continuation()->containingBlock()->xPos(),
+                                              ty - yPos() + continuation()->containingBlock()->yPos());
+    }
+}
+
+void RenderFlow::paintOutline(GraphicsContext* graphicsContext, int tx, int ty)
+{
+    if (!hasOutline())
+        return;
+    
+    if (style()->outlineStyleIsAuto() || hasOutlineAnnotation()) {
+        int ow = style()->outlineWidth();
+        Color oc = style()->outlineColor();
+        if (!oc.isValid())
+            oc = style()->color();
+
+        graphicsContext->initFocusRing(ow, style()->outlineOffset());
+        addFocusRingRects(graphicsContext, tx, ty);
+        if (style()->outlineStyleIsAuto())
+            graphicsContext->drawFocusRing(oc);
+        else
+            addPDFURLRect(graphicsContext, graphicsContext->focusRingBoundingRect());
+        graphicsContext->clearFocusRing();
+    }
+
+    if (style()->outlineStyleIsAuto() || style()->outlineStyle() == BNONE)
+        return;
+
+    Vector<IntRect> rects;
+
+    rects.append(IntRect());
+    for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+        rects.append(IntRect(curr->xPos(), curr->yPos(), curr->width(), curr->height()));
+
+    rects.append(IntRect());
+
+    for (unsigned i = 1; i < rects.size() - 1; i++)
+        paintOutlineForLine(graphicsContext, tx, ty, rects.at(i - 1), rects.at(i), rects.at(i + 1));
+}
+
+void RenderFlow::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, int ty,
+                                     const IntRect& lastline, const IntRect& thisline, const IntRect& nextline)
+{
+    int ow = style()->outlineWidth();
+    EBorderStyle os = style()->outlineStyle();
+    Color oc = style()->outlineColor();
+    if (!oc.isValid())
+        oc = style()->color();
+
+    int offset = style()->outlineOffset();
+
+    int t = ty + thisline.y() - offset;
+    int l = tx + thisline.x() - offset;
+    int b = ty + thisline.bottom() + offset;
+    int r = tx + thisline.right() + offset;
+    
+    // left edge
+    drawBorder(graphicsContext,
+               l - ow,
+               t - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.right() - 1) <= thisline.x() ? ow : 0),
+               l,
+               b + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.right() - 1) <= thisline.x() ? ow : 0),
+               BSLeft,
+               oc, style()->color(), os,
+               (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.right() - 1) <= thisline.x() ? ow : -ow),
+               (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.right() - 1) <= thisline.x() ? ow : -ow));
+    
+    // right edge
+    drawBorder(graphicsContext,
+               r,
+               t - (lastline.isEmpty() || lastline.right() < thisline.right() || (thisline.right() - 1) <= lastline.x() ? ow : 0),
+               r + ow,
+               b + (nextline.isEmpty() || nextline.right() <= thisline.right() || (thisline.right() - 1) <= nextline.x() ? ow : 0),
+               BSRight,
+               oc, style()->color(), os,
+               (lastline.isEmpty() || lastline.right() < thisline.right() || (thisline.right() - 1) <= lastline.x() ? ow : -ow),
+               (nextline.isEmpty() || nextline.right() <= thisline.right() || (thisline.right() - 1) <= nextline.x() ? ow : -ow));
+    // upper edge
+    if (thisline.x() < lastline.x())
+        drawBorder(graphicsContext,
+                   l - ow,
+                   t - ow,
+                   min(r+ow, (lastline.isEmpty() ? 1000000 : tx + lastline.x())),
+                   t ,
+                   BSTop, oc, style()->color(), os,
+                   ow,
+                   (!lastline.isEmpty() && tx + lastline.x() + 1 < r + ow) ? -ow : ow);
+    
+    if (lastline.right() < thisline.right())
+        drawBorder(graphicsContext,
+                   max(lastline.isEmpty() ? -1000000 : tx + lastline.right(), l - ow),
+                   t - ow,
+                   r + ow,
+                   t ,
+                   BSTop, oc, style()->color(), os,
+                   (!lastline.isEmpty() && l - ow < tx + lastline.right()) ? -ow : ow,
+                   ow);
+    
+    // lower edge
+    if (thisline.x() < nextline.x())
+        drawBorder(graphicsContext,
+                   l - ow,
+                   b,
+                   min(r + ow, !nextline.isEmpty() ? tx + nextline.x() + 1 : 1000000),
+                   b + ow,
+                   BSBottom, oc, style()->color(), os,
+                   ow,
+                   (!nextline.isEmpty() && tx + nextline.x() + 1 < r + ow) ? -ow : ow);
+    
+    if (nextline.right() < thisline.right())
+        drawBorder(graphicsContext,
+                   max(!nextline.isEmpty() ? tx + nextline.right() : -1000000, l - ow),
+                   b,
+                   r + ow,
+                   b + ow,
+                   BSBottom, oc, style()->color(), os,
+                   (!nextline.isEmpty() && l - ow < tx + nextline.right()) ? -ow : ow,
+                   ow);
+}
+
+void RenderFlow::calcMargins(int containerWidth)
+{
+    m_marginLeft = style()->marginLeft().calcMinValue(containerWidth);
+    m_marginRight = style()->marginRight().calcMinValue(containerWidth);
+}
+
+#ifndef NDEBUG
+
+void RenderFlow::checkConsistency() const
+{
+#ifdef CHECK_CONSISTENCY
+    const InlineFlowBox* prev = 0;
+    for (const InlineFlowBox* child = m_firstLineBox; child != 0; child = child->nextFlowBox()) {
+        ASSERT(child->object() == this);
+        ASSERT(child->prevFlowBox() == prev);
+        prev = child;
+    }
+    ASSERT(prev == m_lastLineBox);
+#endif
+}
+
+#endif
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderFlow.h b/WebCore/rendering/RenderFlow.h
new file mode 100644
index 0000000..c284ed8
--- /dev/null
+++ b/WebCore/rendering/RenderFlow.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderFlow_h
+#define RenderFlow_h
+
+#include "RenderContainer.h"
+
+namespace WebCore {
+
+/**
+ * all geometry managing stuff is only in the block elements.
+ *
+ * Inline elements don't layout themselves, but the whole paragraph
+ * gets flowed by the surrounding block element. This is, because
+ * one needs to know the whole paragraph to calculate bidirectional
+ * behaviour of text, so putting the layouting routines in the inline
+ * elements is impossible.
+ */
+class RenderFlow : public RenderContainer {
+public:
+    RenderFlow(Node* node)
+        : RenderContainer(node)
+        , m_continuation(0)
+        , m_firstLineBox(0)
+        , m_lastLineBox(0)
+        , m_lineHeight(-1)
+        , m_childrenInline(true)
+        , m_firstLine(false)
+        , m_topMarginQuirk(false) 
+        , m_bottomMarginQuirk(false)
+        , m_hasMarkupTruncation(false)
+        , m_selectionState(SelectionNone)
+        , m_hasColumns(false)
+        , m_isContinuation(false)
+    {
+    }
+#ifndef NDEBUG
+    virtual ~RenderFlow();
+#endif
+
+    virtual RenderFlow* continuation() const { return m_continuation; }
+    void setContinuation(RenderFlow* c) { m_continuation = c; }
+    RenderFlow* continuationBefore(RenderObject* beforeChild);
+
+    void addChildWithContinuation(RenderObject* newChild, RenderObject* beforeChild);
+    virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild) = 0;
+    virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+
+    static RenderFlow* createAnonymousFlow(Document*, PassRefPtr<RenderStyle>);
+
+    void extractLineBox(InlineFlowBox*);
+    void attachLineBox(InlineFlowBox*);
+    void removeLineBox(InlineFlowBox*);
+    void deleteLineBoxes();
+    virtual void destroy();
+
+    virtual void dirtyLinesFromChangedChild(RenderObject* child);
+
+    virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
+
+    InlineFlowBox* firstLineBox() const { return m_firstLineBox; }
+    InlineFlowBox* lastLineBox() const { return m_lastLineBox; }
+
+    virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun=false);
+    virtual void dirtyLineBoxes(bool fullLayout, bool isRootLineBox = false);
+
+    void paintLines(PaintInfo&, int tx, int ty);
+    bool hitTestLines(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+    virtual IntRect absoluteClippedOverflowRect();
+
+    virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+    virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+    virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+
+    virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
+
+    virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+    void paintOutlineForLine(GraphicsContext*, int tx, int ty, const IntRect& prevLine, const IntRect& thisLine, const IntRect& nextLine);
+    void paintOutline(GraphicsContext*, int tx, int ty);
+
+    virtual bool hasColumns() const { return m_hasColumns; }
+
+    void calcMargins(int containerWidth);
+
+    void checkConsistency() const;
+
+private:
+    // An inline can be split with blocks occurring in between the inline content.
+    // When this occurs we need a pointer to our next object.  We can basically be
+    // split into a sequence of inlines and blocks.  The continuation will either be
+    // an anonymous block (that houses other blocks) or it will be an inline flow.
+    RenderFlow* m_continuation;
+
+protected:
+    // For block flows, each box represents the root inline box for a line in the
+    // paragraph.
+    // For inline flows, each box represents a portion of that inline.
+    InlineFlowBox* m_firstLineBox;
+    InlineFlowBox* m_lastLineBox;
+
+    mutable int m_lineHeight;
+    
+    // These bitfields are moved here from subclasses to pack them together
+    // from RenderBlock
+    bool m_childrenInline : 1;
+    bool m_firstLine : 1;
+    bool m_topMarginQuirk : 1;
+    bool m_bottomMarginQuirk : 1;
+    bool m_hasMarkupTruncation : 1;
+    unsigned m_selectionState : 3; // SelectionState
+    bool m_hasColumns : 1;
+    
+    // from RenderInline
+    bool m_isContinuation : 1; // Whether or not we're a continuation of an inline.
+};
+
+#ifdef NDEBUG
+inline void RenderFlow::checkConsistency() const
+{
+}
+#endif
+
+} // namespace WebCore
+
+#endif // RenderFlow_h
diff --git a/WebCore/rendering/RenderForeignObject.cpp b/WebCore/rendering/RenderForeignObject.cpp
new file mode 100644
index 0000000..5070b97
--- /dev/null
+++ b/WebCore/rendering/RenderForeignObject.cpp
@@ -0,0 +1,132 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT)
+#include "RenderForeignObject.h"
+
+#include "GraphicsContext.h"
+#include "RenderView.h"
+#include "SVGForeignObjectElement.h"
+#include "SVGLength.h"
+#include "SVGTransformList.h"
+
+namespace WebCore {
+
+RenderForeignObject::RenderForeignObject(SVGForeignObjectElement* node) 
+    : RenderSVGBlock(node)
+{
+}
+
+AffineTransform RenderForeignObject::translationForAttributes()
+{
+    SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(element());
+    return AffineTransform().translate(foreign->x().value(foreign), foreign->y().value(foreign));
+}
+
+void RenderForeignObject::paint(PaintInfo& paintInfo, int parentX, int parentY)
+{
+    if (paintInfo.context->paintingDisabled())
+        return;
+
+    paintInfo.context->save();
+    paintInfo.context->concatCTM(AffineTransform().translate(parentX, parentY));
+    paintInfo.context->concatCTM(localTransform());
+    paintInfo.context->concatCTM(translationForAttributes());
+    paintInfo.context->clip(getClipRect(parentX, parentY));
+
+    float opacity = style()->opacity();
+    if (opacity < 1.0f)
+        // FIXME: Possible optimization by clipping to bbox here, once relativeBBox is implemented & clip, mask and filter support added.
+        paintInfo.context->beginTransparencyLayer(opacity);
+
+    PaintInfo pi(paintInfo);
+    pi.rect = absoluteTransform().inverse().mapRect(paintInfo.rect);
+    RenderBlock::paint(pi, 0, 0);
+
+    if (opacity < 1.0f)
+        paintInfo.context->endTransparencyLayer();
+
+    paintInfo.context->restore();
+}
+
+void RenderForeignObject::computeAbsoluteRepaintRect(IntRect& r, bool f)
+{
+    AffineTransform transform = translationForAttributes() * localTransform();
+    r = transform.mapRect(r);
+
+    RenderBlock::computeAbsoluteRepaintRect(r, f);
+}
+
+bool RenderForeignObject::requiresLayer()
+{
+    return false;
+}
+
+bool RenderForeignObject::calculateLocalTransform()
+{
+    AffineTransform oldTransform = m_localTransform;
+    m_localTransform = static_cast<SVGForeignObjectElement*>(element())->animatedLocalTransform();
+    return (oldTransform != m_localTransform);
+}
+
+void RenderForeignObject::layout()
+{
+    ASSERT(needsLayout());
+
+    // Arbitrary affine transforms are incompatible with LayoutState.
+    view()->disableLayoutState();
+
+    IntRect oldBounds;
+    IntRect oldOutlineBox;
+    bool checkForRepaint = checkForRepaintDuringLayout();
+    if (checkForRepaint) {
+        oldBounds = m_absoluteBounds;
+        oldOutlineBox = absoluteOutlineBox();
+    }
+    
+    calculateLocalTransform();
+    
+    RenderBlock::layout();
+
+    m_absoluteBounds = absoluteClippedOverflowRect();
+
+    if (checkForRepaint)
+        repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+
+    view()->enableLayoutState();
+    setNeedsLayout(false);
+}
+
+bool RenderForeignObject::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
+{
+    AffineTransform totalTransform = absoluteTransform();
+    totalTransform *= translationForAttributes();
+    double localX, localY;
+    totalTransform.inverse().map(x, y, &localX, &localY);
+    return RenderBlock::nodeAtPoint(request, result, static_cast<int>(localX), static_cast<int>(localY), tx, ty, hitTestAction);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT)
diff --git a/WebCore/rendering/RenderForeignObject.h b/WebCore/rendering/RenderForeignObject.h
new file mode 100644
index 0000000..b624683
--- /dev/null
+++ b/WebCore/rendering/RenderForeignObject.h
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderForeignObject_h
+#define RenderForeignObject_h
+#if ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT)
+
+#include "AffineTransform.h"
+#include "RenderSVGBlock.h"
+
+namespace WebCore {
+
+class SVGForeignObjectElement;
+
+class RenderForeignObject : public RenderSVGBlock {
+public:
+    RenderForeignObject(SVGForeignObjectElement*);
+
+    virtual const char* renderName() const { return "RenderForeignObject"; }
+
+    virtual void paint(PaintInfo&, int parentX, int parentY);
+
+    virtual AffineTransform localTransform() const { return m_localTransform; }
+    virtual bool calculateLocalTransform();
+
+    virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed);
+    virtual bool requiresLayer();
+    virtual void layout();
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+ private:
+    AffineTransform translationForAttributes();
+
+    AffineTransform m_localTransform;
+    IntRect m_absoluteBounds;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT)
+#endif // RenderForeignObject_h
diff --git a/WebCore/rendering/RenderFrame.cpp b/WebCore/rendering/RenderFrame.cpp
new file mode 100644
index 0000000..c996138
--- /dev/null
+++ b/WebCore/rendering/RenderFrame.cpp
@@ -0,0 +1,96 @@
+/**
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 2000 Simon Hausmann <[email protected]>
+ *           (C) 2000 Stefan Schimanski ([email protected])
+ * Copyright (C) 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderFrame.h"
+#include "RenderFrameSet.h"
+#include "FrameView.h"
+#include "HTMLFrameSetElement.h"
+#include "HTMLNames.h"
+
+#ifdef FLATTEN_FRAMESET
+#include "Frame.h"
+#include "Document.h"
+#include "RenderView.h"
+#endif
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderFrame::RenderFrame(HTMLFrameElement* frame)
+    : RenderPart(frame)
+{
+    setInline(false);
+}
+
+FrameEdgeInfo RenderFrame::edgeInfo() const
+{
+    return FrameEdgeInfo(element()->noResize(), element()->hasFrameBorder());
+}
+
+void RenderFrame::viewCleared()
+{
+    if (element() && m_widget && m_widget->isFrameView()) {
+        FrameView* view = static_cast<FrameView*>(m_widget);
+        int marginw = element()->getMarginWidth();
+        int marginh = element()->getMarginHeight();
+
+        if (marginw != -1)
+            view->setMarginWidth(marginw);
+        if (marginh != -1)
+            view->setMarginHeight(marginh);
+    }
+}
+
+#ifdef FLATTEN_FRAMESET
+void RenderFrame::layout()
+{
+    if (m_widget && m_widget->isFrameView()) {
+        FrameView* view = static_cast<FrameView*>(m_widget);
+        RenderView* root = NULL;
+        if (view->frame() && view->frame()->document() && 
+            view->frame()->document()->renderer() && view->frame()->document()->renderer()->isRenderView())
+            root = static_cast<RenderView*>(view->frame()->document()->renderer());
+        if (root) {
+            // Resize the widget so that the RenderView will layout according to those dimensions.
+            view->resize(m_width, m_height);
+            view->layout();
+            // We can only grow in width and height because if positionFrames gives us a width and we become smaller,
+            // then the fixup process of forcing the frame to fill extra space will fail.
+            if (m_width > root->docWidth()) {
+                view->resize(root->docWidth(), 0);
+                view->layout();
+            }
+            // Honor the height set by RenderFrameSet::positionFrames unless our document height is larger.
+            m_height = max(root->docHeight(), m_height);
+            m_width = max(root->docWidth(), m_width);
+        }
+    }
+    setNeedsLayout(false);
+}
+#endif
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderFrame.h b/WebCore/rendering/RenderFrame.h
new file mode 100644
index 0000000..d7c8c5a
--- /dev/null
+++ b/WebCore/rendering/RenderFrame.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 2000 Simon Hausmann <[email protected]>
+ * Copyright (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderFrame_h
+#define RenderFrame_h
+
+#include "HTMLFrameElement.h"
+#include "RenderPart.h"
+#include "RenderFrameSet.h"
+
+namespace WebCore {
+
+class RenderFrame : public RenderPart {
+public:
+    RenderFrame(HTMLFrameElement*);
+
+    virtual const char* renderName() const { return "RenderFrame"; }
+    virtual bool isFrame() const { return true; }
+
+#ifdef FLATTEN_FRAMESET
+    virtual void layout();
+#endif
+    HTMLFrameElement* element() const { return static_cast<HTMLFrameElement*>(RenderPart::element()); }
+
+    FrameEdgeInfo edgeInfo() const;
+
+    virtual void viewCleared();
+};
+
+} // namespace WebCore
+
+#endif // RenderFrame_h
diff --git a/WebCore/rendering/RenderFrameSet.cpp b/WebCore/rendering/RenderFrameSet.cpp
new file mode 100644
index 0000000..2b74d8a
--- /dev/null
+++ b/WebCore/rendering/RenderFrameSet.cpp
@@ -0,0 +1,771 @@
+/**
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 2000 Simon Hausmann <[email protected]>
+ *           (C) 2000 Stefan Schimanski ([email protected])
+ * Copyright (C) 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderFrameSet.h"
+
+#include "Document.h"
+#include "EventHandler.h"
+#include "EventNames.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLFrameSetElement.h"
+#include "HitTestRequest.h"
+#include "HitTestResult.h"
+#include "MouseEvent.h"
+#include "RenderFrame.h"
+#include "RenderView.h"
+
+namespace WebCore {
+
+RenderFrameSet::RenderFrameSet(HTMLFrameSetElement* frameSet)
+    : RenderContainer(frameSet)
+    , m_isResizing(false)
+    , m_isChildResizing(false)
+#ifdef FLATTEN_FRAMESET
+    , m_gridCalculated(false)
+#endif
+{
+    setInline(false);
+}
+
+RenderFrameSet::~RenderFrameSet()
+{
+}
+
+RenderFrameSet::GridAxis::GridAxis()
+    : m_splitBeingResized(noSplit)
+{
+}
+
+inline HTMLFrameSetElement* RenderFrameSet::frameSet() const
+{
+    return static_cast<HTMLFrameSetElement*>(node());
+}
+
+static Color borderStartEdgeColor()
+{
+    return Color(170,170,170);
+}
+
+static Color borderEndEdgeColor()
+{
+    return Color::black;
+}
+
+static Color borderFillColor()
+{
+    return Color(208, 208, 208);
+}
+
+void RenderFrameSet::paintColumnBorder(const PaintInfo& paintInfo, const IntRect& borderRect)
+{
+    if (!paintInfo.rect.intersects(borderRect))
+        return;
+        
+    // FIXME: We should do something clever when borders from distinct framesets meet at a join.
+    
+    // Fill first.
+    GraphicsContext* context = paintInfo.context;
+    context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->borderLeftColor() : borderFillColor());
+    
+    // Now stroke the edges but only if we have enough room to paint both edges with a little
+    // bit of the fill color showing through.
+    if (borderRect.width() >= 3) {
+        context->fillRect(IntRect(borderRect.topLeft(), IntSize(1, height())), borderStartEdgeColor());
+        context->fillRect(IntRect(borderRect.topRight(), IntSize(1, height())), borderEndEdgeColor());
+    }
+}
+
+void RenderFrameSet::paintRowBorder(const PaintInfo& paintInfo, const IntRect& borderRect)
+{
+    if (!paintInfo.rect.intersects(borderRect))
+        return;
+
+    // FIXME: We should do something clever when borders from distinct framesets meet at a join.
+    
+    // Fill first.
+    GraphicsContext* context = paintInfo.context;
+    context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->borderLeftColor() : borderFillColor());
+
+    // Now stroke the edges but only if we have enough room to paint both edges with a little
+    // bit of the fill color showing through.
+    if (borderRect.height() >= 3) {
+        context->fillRect(IntRect(borderRect.topLeft(), IntSize(width(), 1)), borderStartEdgeColor());
+        context->fillRect(IntRect(borderRect.bottomLeft(), IntSize(width(), 1)), borderEndEdgeColor());
+    }
+}
+
+void RenderFrameSet::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (paintInfo.phase != PaintPhaseForeground)
+        return;
+    
+    RenderObject* child = firstChild();
+    if (!child)
+        return;
+
+    // Add in our offsets.
+    tx += m_x;
+    ty += m_y;
+
+    int rows = frameSet()->totalRows();
+    int cols = frameSet()->totalCols();
+    int borderThickness = frameSet()->border();
+    
+    int yPos = 0;
+    for (int r = 0; r < rows; r++) {
+        int xPos = 0;
+        for (int c = 0; c < cols; c++) {
+            child->paint(paintInfo, tx, ty);
+            xPos += m_cols.m_sizes[c];
+            if (borderThickness && m_cols.m_allowBorder[c + 1]) {
+                paintColumnBorder(paintInfo, IntRect(tx + xPos, ty + yPos, borderThickness, height()));
+                xPos += borderThickness;
+            }
+            child = child->nextSibling();
+            if (!child)
+                return;
+        }
+        yPos += m_rows.m_sizes[r];
+        if (borderThickness && m_rows.m_allowBorder[r + 1]) {
+            paintRowBorder(paintInfo, IntRect(tx, ty + yPos, width(), borderThickness));
+            yPos += borderThickness;
+        }
+    }
+}
+
+bool RenderFrameSet::nodeAtPoint(const HitTestRequest& request, HitTestResult& result,
+    int x, int y, int tx, int ty, HitTestAction action)
+{
+    if (action != HitTestForeground)
+        return false;
+
+    bool inside = RenderContainer::nodeAtPoint(request, result, x, y, tx, ty, action)
+        || m_isResizing || canResize(IntPoint(x, y));
+
+    if (inside && frameSet()->noResize()
+            && !request.readonly && !result.innerNode()) {
+        result.setInnerNode(node());
+        result.setInnerNonSharedNode(node());
+    }
+
+    return inside || m_isChildResizing;
+}
+
+void RenderFrameSet::GridAxis::resize(int size)
+{
+    m_sizes.resize(size);
+    m_deltas.resize(size);
+    m_deltas.fill(0);
+    
+    // To track edges for resizability and borders, we need to be (size + 1).  This is because a parent frameset
+    // may ask us for information about our left/top/right/bottom edges in order to make its own decisions about
+    // what to do.  We are capable of tainting that parent frameset's borders, so we have to cache this info.
+    m_preventResize.resize(size + 1);
+    m_allowBorder.resize(size + 1);
+}
+
+void RenderFrameSet::layOutAxis(GridAxis& axis, const Length* grid, int availableLen)
+{
+    availableLen = max(availableLen, 0);
+
+    int* gridLayout = axis.m_sizes.data();
+
+    if (!grid) {
+        gridLayout[0] = availableLen;
+        return;
+    }
+
+    int gridLen = axis.m_sizes.size();
+    ASSERT(gridLen);
+
+    int totalRelative = 0;
+    int totalFixed = 0;
+    int totalPercent = 0;
+    int countRelative = 0;
+    int countFixed = 0;
+    int countPercent = 0;
+
+    // First we need to investigate how many columns of each type we have and
+    // how much space these columns are going to require.
+    for (int i = 0; i < gridLen; ++i) {
+        // Count the total length of all of the fixed columns/rows -> totalFixed
+        // Count the number of columns/rows which are fixed -> countFixed
+        if (grid[i].isFixed()) {
+            gridLayout[i] = max(grid[i].value(), 0);
+            totalFixed += gridLayout[i];
+            countFixed++;
+        }
+        
+        // Count the total percentage of all of the percentage columns/rows -> totalPercent
+        // Count the number of columns/rows which are percentages -> countPercent
+        if (grid[i].isPercent()) {
+            gridLayout[i] = max(grid[i].calcValue(availableLen), 0);
+            totalPercent += gridLayout[i];
+            countPercent++;
+        }
+
+        // Count the total relative of all the relative columns/rows -> totalRelative
+        // Count the number of columns/rows which are relative -> countRelative
+        if (grid[i].isRelative()) {
+            totalRelative += max(grid[i].value(), 1);
+            countRelative++;
+        }            
+    }
+
+    int remainingLen = availableLen;
+
+    // Fixed columns/rows are our first priority. If there is not enough space to fit all fixed
+    // columns/rows we need to proportionally adjust their size. 
+    if (totalFixed > remainingLen) {
+        int remainingFixed = remainingLen;
+
+        for (int i = 0; i < gridLen; ++i) {
+            if (grid[i].isFixed()) {
+                gridLayout[i] = (gridLayout[i] * remainingFixed) / totalFixed;
+                remainingLen -= gridLayout[i];
+            }
+        }
+    } else
+        remainingLen -= totalFixed;
+
+    // Percentage columns/rows are our second priority. Divide the remaining space proportionally 
+    // over all percentage columns/rows. IMPORTANT: the size of each column/row is not relative 
+    // to 100%, but to the total percentage. For example, if there are three columns, each of 75%,
+    // and the available space is 300px, each column will become 100px in width.
+    if (totalPercent > remainingLen) {
+        int remainingPercent = remainingLen;
+
+        for (int i = 0; i < gridLen; ++i) {
+            if (grid[i].isPercent()) {
+                gridLayout[i] = (gridLayout[i] * remainingPercent) / totalPercent;
+                remainingLen -= gridLayout[i];
+            }
+        }
+    } else
+        remainingLen -= totalPercent;
+
+    // Relative columns/rows are our last priority. Divide the remaining space proportionally
+    // over all relative columns/rows. IMPORTANT: the relative value of 0* is treated as 1*.
+    if (countRelative) {
+        int lastRelative = 0;
+        int remainingRelative = remainingLen;
+
+        for (int i = 0; i < gridLen; ++i) {
+            if (grid[i].isRelative()) {
+                gridLayout[i] = (max(grid[i].value(), 1) * remainingRelative) / totalRelative;
+                remainingLen -= gridLayout[i];
+                lastRelative = i;
+            }
+        }
+        
+        // If we could not evenly distribute the available space of all of the relative  
+        // columns/rows, the remainder will be added to the last column/row.
+        // For example: if we have a space of 100px and three columns (*,*,*), the remainder will
+        // be 1px and will be added to the last column: 33px, 33px, 34px.
+        if (remainingLen) {
+            gridLayout[lastRelative] += remainingLen;
+            remainingLen = 0;
+        }
+    }
+
+    // If we still have some left over space we need to divide it over the already existing
+    // columns/rows
+    if (remainingLen) {
+        // Our first priority is to spread if over the percentage columns. The remaining
+        // space is spread evenly, for example: if we have a space of 100px, the columns 
+        // definition of 25%,25% used to result in two columns of 25px. After this the 
+        // columns will each be 50px in width. 
+        if (countPercent && totalPercent) {
+            int remainingPercent = remainingLen;
+            int changePercent = 0;
+
+            for (int i = 0; i < gridLen; ++i) {
+                if (grid[i].isPercent()) {
+                    changePercent = (remainingPercent * gridLayout[i]) / totalPercent;
+                    gridLayout[i] += changePercent;
+                    remainingLen -= changePercent;
+                }
+            }
+        } else if (totalFixed) {
+            // Our last priority is to spread the remaining space over the fixed columns.
+            // For example if we have 100px of space and two column of each 40px, both
+            // columns will become exactly 50px.
+            int remainingFixed = remainingLen;
+            int changeFixed = 0;
+
+            for (int i = 0; i < gridLen; ++i) {
+                if (grid[i].isFixed()) {
+                    changeFixed = (remainingFixed * gridLayout[i]) / totalFixed;
+                    gridLayout[i] += changeFixed;
+                    remainingLen -= changeFixed;
+                } 
+            }
+        }
+    }
+    
+    // If we still have some left over space we probably ended up with a remainder of
+    // a division. We cannot spread it evenly anymore. If we have any percentage 
+    // columns/rows simply spread the remainder equally over all available percentage columns, 
+    // regardless of their size.
+    if (remainingLen && countPercent) {
+        int remainingPercent = remainingLen;
+        int changePercent = 0;
+
+        for (int i = 0; i < gridLen; ++i) {
+            if (grid[i].isPercent()) {
+                changePercent = remainingPercent / countPercent;
+                gridLayout[i] += changePercent;
+                remainingLen -= changePercent;
+            }
+        }
+    } 
+    
+    // If we don't have any percentage columns/rows we only have fixed columns. Spread
+    // the remainder equally over all fixed columns/rows.
+    else if (remainingLen && countFixed) {
+        int remainingFixed = remainingLen;
+        int changeFixed = 0;
+        
+        for (int i = 0; i < gridLen; ++i) {
+            if (grid[i].isFixed()) {
+                changeFixed = remainingFixed / countFixed;
+                gridLayout[i] += changeFixed;
+                remainingLen -= changeFixed;
+            }
+        }
+    }
+
+    // Still some left over. Add it to the last column, because it is impossible
+    // spread it evenly or equally.
+    if (remainingLen)
+        gridLayout[gridLen - 1] += remainingLen;
+
+    // now we have the final layout, distribute the delta over it
+    bool worked = true;
+    int* gridDelta = axis.m_deltas.data();
+    for (int i = 0; i < gridLen; ++i) {
+        if (gridLayout[i] && gridLayout[i] + gridDelta[i] <= 0)
+            worked = false;
+        gridLayout[i] += gridDelta[i];
+    }
+    // if the deltas broke something, undo them
+    if (!worked) {
+        for (int i = 0; i < gridLen; ++i)
+            gridLayout[i] -= gridDelta[i];
+        axis.m_deltas.fill(0);
+    }
+}
+
+void RenderFrameSet::fillFromEdgeInfo(const FrameEdgeInfo& edgeInfo, int r, int c)
+{
+    if (edgeInfo.allowBorder(LeftFrameEdge))
+        m_cols.m_allowBorder[c] = true;
+    if (edgeInfo.allowBorder(RightFrameEdge))
+        m_cols.m_allowBorder[c + 1] = true;
+    if (edgeInfo.preventResize(LeftFrameEdge))
+        m_cols.m_preventResize[c] = true;
+    if (edgeInfo.preventResize(RightFrameEdge))
+        m_cols.m_preventResize[c + 1] = true;
+    
+    if (edgeInfo.allowBorder(TopFrameEdge))
+        m_rows.m_allowBorder[r] = true;
+    if (edgeInfo.allowBorder(BottomFrameEdge))
+        m_rows.m_allowBorder[r + 1] = true;
+    if (edgeInfo.preventResize(TopFrameEdge))
+        m_rows.m_preventResize[r] = true;
+    if (edgeInfo.preventResize(BottomFrameEdge))
+        m_rows.m_preventResize[r + 1] = true;
+}
+
+void RenderFrameSet::computeEdgeInfo()
+{
+    m_rows.m_preventResize.fill(frameSet()->noResize());    
+    m_rows.m_allowBorder.fill(false);
+    m_cols.m_preventResize.fill(frameSet()->noResize());    
+    m_cols.m_allowBorder.fill(false);
+    
+    RenderObject* child = firstChild();
+    if (!child)
+        return;
+
+    int rows = frameSet()->totalRows();
+    int cols = frameSet()->totalCols();
+    for (int r = 0; r < rows; ++r) {
+        for (int c = 0; c < cols; ++c) {
+            FrameEdgeInfo edgeInfo;
+            if (child->isFrameSet())
+                edgeInfo = static_cast<RenderFrameSet*>(child)->edgeInfo();
+            else
+                edgeInfo = static_cast<RenderFrame*>(child)->edgeInfo();
+            fillFromEdgeInfo(edgeInfo, r, c);
+            child = child->nextSibling();
+            if (!child)
+                return;
+        }
+    }
+}
+
+FrameEdgeInfo RenderFrameSet::edgeInfo() const
+{
+    FrameEdgeInfo result(frameSet()->noResize(), true);
+    
+    int rows = frameSet()->totalRows();
+    int cols = frameSet()->totalCols();
+    if (rows && cols) {
+        result.setPreventResize(LeftFrameEdge, m_cols.m_preventResize[0]);
+        result.setAllowBorder(LeftFrameEdge, m_cols.m_allowBorder[0]);
+        result.setPreventResize(RightFrameEdge, m_cols.m_preventResize[cols]);
+        result.setAllowBorder(RightFrameEdge, m_cols.m_allowBorder[cols]);
+        result.setPreventResize(TopFrameEdge, m_rows.m_preventResize[0]);
+        result.setAllowBorder(TopFrameEdge, m_rows.m_allowBorder[0]);
+        result.setPreventResize(BottomFrameEdge, m_rows.m_preventResize[rows]);
+        result.setAllowBorder(BottomFrameEdge, m_rows.m_allowBorder[rows]);
+    }
+    
+    return result;
+}
+
+void RenderFrameSet::layout()
+{
+    ASSERT(needsLayout());
+
+    bool doFullRepaint = selfNeedsLayout() && checkForRepaintDuringLayout();
+    IntRect oldBounds;
+    if (doFullRepaint)
+        oldBounds = absoluteClippedOverflowRect();
+
+    if (!parent()->isFrameSet() && !document()->printing()) {
+#ifdef FLATTEN_FRAMESET
+        // Force a grid recalc.
+        m_gridCalculated = false;
+#endif
+        m_width = view()->viewWidth();
+        m_height = view()->viewHeight();
+    }
+
+    size_t cols = frameSet()->totalCols();
+    size_t rows = frameSet()->totalRows();
+
+    if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) {
+        m_rows.resize(rows);
+        m_cols.resize(cols);
+#ifdef FLATTEN_FRAMESET
+        m_gridCalculated = false;
+#endif
+    }
+
+#ifdef FLATTEN_FRAMESET
+    if (!m_gridCalculated) {
+        m_gridCalculated = true;
+        // Make all the child framesets recalculate their grid.
+        RenderObject* child = firstChild();
+        for (; child; child = child->nextSibling()) {
+            if (child->isFrameSet())
+                static_cast<RenderFrameSet*>(child)->setGridNeedsLayout();
+        }
+#endif
+    int borderThickness = frameSet()->border();
+    layOutAxis(m_rows, frameSet()->rowLengths(), m_height - (rows - 1) * borderThickness);
+    layOutAxis(m_cols, frameSet()->colLengths(), m_width - (cols - 1) * borderThickness);
+#ifdef FLATTEN_FRAMESET
+    }
+#endif
+
+    positionFrames();
+
+    RenderContainer::layout();
+
+    computeEdgeInfo();
+
+    if (doFullRepaint) {
+        view()->repaintViewRectangle(oldBounds);
+        IntRect newBounds = absoluteClippedOverflowRect();
+        if (newBounds != oldBounds)
+            view()->repaintViewRectangle(newBounds);
+    }
+
+    setNeedsLayout(false);
+}
+
+void RenderFrameSet::positionFrames()
+{
+    RenderObject* child = firstChild();
+    if (!child)
+        return;
+
+    int rows = frameSet()->totalRows();
+    int cols = frameSet()->totalCols();
+    
+    int yPos = 0;
+    int borderThickness = frameSet()->border();
+#ifdef FLATTEN_FRAMESET
+    // Keep track of the maximum width of a row which will become the maximum width of the frameset.
+    int maxWidth = 0;
+    const Length* rowLengths = frameSet()->rowLengths();
+    const Length* colLengths = frameSet()->colLengths();
+
+    for (int r = 0; r < rows && child; r++) {
+        int xPos = 0;
+        int height = m_rows.m_sizes[r];
+        int rowHeight = -1;
+        if (rowLengths) {
+            Length l = rowLengths[r];
+            if (l.isFixed())
+                rowHeight = l.value();
+        }
+        for (int c = 0; c < cols && child; c++) {
+            child->setPos(xPos, yPos);
+            child->setWidth(m_cols.m_sizes[c]);
+            child->setHeight(height);
+            int colWidth = -1;
+            if (colLengths) {
+                Length l = colLengths[c];
+                if (l.isFixed())
+                    colWidth = l.value();
+            }
+            if (colWidth && rowHeight) {
+                child->setNeedsLayout(true);
+                child->layout();
+            } else {
+                child->layoutIfNeeded();
+            }
+
+            ASSERT(child->width() >= m_cols.m_sizes[c]);
+            m_cols.m_sizes[c] = child->width();
+
+            height = max(child->height(), height);
+            xPos += child->width() + borderThickness;
+            child = child->nextSibling();
+        }
+        ASSERT(height >= m_rows.m_sizes[r]);
+        m_rows.m_sizes[r] = height;
+        maxWidth = max(xPos, maxWidth);
+        yPos += height + borderThickness;
+    }
+
+    // Compute a new width and height according to the positioning of each expanded child frame.
+    // Note: we subtract borderThickness because we only count borders between frames.
+    int newWidth = maxWidth - borderThickness;
+    int newHeight = yPos - borderThickness;
+
+    // Distribute the extra width and height evenly across the grid.
+    int dWidth = (m_width - newWidth) / cols;
+    int dHeight = (m_height - newHeight) / rows;
+    if (dWidth > 0) {
+        int availableWidth = m_width - (cols - 1) * borderThickness;
+        for (int c = 0; c < cols; c++)
+            availableWidth -= m_cols.m_sizes[c] += dWidth;
+        // If the extra width did not distribute evenly, add the remainder to
+        // the last column.
+        if (availableWidth)
+            m_cols.m_sizes[cols - 1] += availableWidth;
+    }
+    if (dHeight > 0) {
+        int availableHeight = m_height - (rows - 1) * borderThickness;
+        for (int r = 0; r < rows; r++)
+            availableHeight -= m_rows.m_sizes[r] += dHeight;
+        // If the extra height did not distribute evenly, add the remainder to
+        // the last row.
+        if (availableHeight)
+            m_rows.m_sizes[rows - 1] += availableHeight;
+    }
+    // Ensure the rows and columns are filled by falling through to the normal
+    // layout
+    m_height = max(m_height, newHeight);
+    m_width = max(m_width, newWidth);
+    child = firstChild();
+    yPos = 0;
+#endif // FLATTEN_FRAMESET
+    
+    for (int r = 0; r < rows; r++) {
+        int xPos = 0;
+        int height = m_rows.m_sizes[r];
+        for (int c = 0; c < cols; c++) {
+            child->setPos(xPos, yPos);
+            int width = m_cols.m_sizes[c];
+
+            // has to be resized and itself resize its contents
+            if (width != child->width() || height != child->height()) {
+                child->setWidth(width);
+                child->setHeight(height);
+                child->setNeedsLayout(true);
+                child->layout();
+            }
+
+            xPos += width + borderThickness;
+
+            child = child->nextSibling();
+            if (!child)
+                return;
+        }
+        yPos += height + borderThickness;
+    }
+
+    // all the remaining frames are hidden to avoid ugly spurious unflowed frames
+    for (; child; child = child->nextSibling()) {
+        child->setWidth(0);
+        child->setHeight(0);
+        child->setNeedsLayout(false);
+    }
+}
+
+void RenderFrameSet::startResizing(GridAxis& axis, int position)
+{
+    int split = hitTestSplit(axis, position);
+    if (split == noSplit || !axis.m_allowBorder[split] || axis.m_preventResize[split]) {
+        axis.m_splitBeingResized = noSplit;
+        return;
+    }
+    axis.m_splitBeingResized = split;
+    axis.m_splitResizeOffset = position - splitPosition(axis, split);
+}
+
+void RenderFrameSet::continueResizing(GridAxis& axis, int position)
+{
+    if (needsLayout())
+        return;
+    if (axis.m_splitBeingResized == noSplit)
+        return;
+    int currentSplitPosition = splitPosition(axis, axis.m_splitBeingResized);
+    int delta = (position - currentSplitPosition) - axis.m_splitResizeOffset;
+    if (delta == 0)
+        return;
+    axis.m_deltas[axis.m_splitBeingResized - 1] += delta;
+    axis.m_deltas[axis.m_splitBeingResized] -= delta;
+    setNeedsLayout(true);
+}
+
+bool RenderFrameSet::userResize(MouseEvent* evt)
+{
+    if (!m_isResizing) {
+        if (needsLayout())
+            return false;
+        if (evt->type() == eventNames().mousedownEvent && evt->button() == LeftButton) {
+            startResizing(m_cols, evt->pageX() - xPos());
+            startResizing(m_rows, evt->pageY() - yPos());
+            if (m_cols.m_splitBeingResized != noSplit || m_rows.m_splitBeingResized != noSplit) {
+                setIsResizing(true);
+                return true;
+            }
+        }
+    } else {
+        if (evt->type() == eventNames().mousemoveEvent || (evt->type() == eventNames().mouseupEvent && evt->button() == LeftButton)) {
+            continueResizing(m_cols, evt->pageX() - xPos());
+            continueResizing(m_rows, evt->pageY() - yPos());
+            if (evt->type() == eventNames().mouseupEvent && evt->button() == LeftButton) {
+                setIsResizing(false);
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+void RenderFrameSet::setIsResizing(bool isResizing)
+{
+    m_isResizing = isResizing;
+    for (RenderObject* p = parent(); p; p = p->parent())
+        if (p->isFrameSet())
+            static_cast<RenderFrameSet*>(p)->m_isChildResizing = isResizing;
+    if (Frame* frame = document()->frame())
+        frame->eventHandler()->setResizingFrameSet(isResizing ? frameSet() : 0);
+}
+
+bool RenderFrameSet::isResizingRow() const
+{
+    return m_isResizing && m_rows.m_splitBeingResized != noSplit;
+}
+
+bool RenderFrameSet::isResizingColumn() const
+{
+    return m_isResizing && m_cols.m_splitBeingResized != noSplit;
+}
+
+bool RenderFrameSet::canResize(const IntPoint& p) const
+{
+    return hitTestSplit(m_cols, p.x()) != noSplit || hitTestSplit(m_rows, p.y()) != noSplit;
+}
+
+bool RenderFrameSet::canResizeRow(const IntPoint& p) const
+{
+    int r = hitTestSplit(m_rows, p.y());
+    return r != noSplit && m_rows.m_allowBorder[r] && !m_rows.m_preventResize[r];
+}
+
+bool RenderFrameSet::canResizeColumn(const IntPoint& p) const
+{
+    int c = hitTestSplit(m_cols, p.x());
+    return c != noSplit && m_cols.m_allowBorder[c] && !m_cols.m_preventResize[c];
+}
+
+int RenderFrameSet::splitPosition(const GridAxis& axis, int split) const
+{
+    if (needsLayout())
+        return 0;
+
+    int borderThickness = frameSet()->border();
+
+    int size = axis.m_sizes.size();
+    if (!size)
+        return 0;
+
+    int position = 0;
+    for (int i = 0; i < split && i < size; ++i)
+        position += axis.m_sizes[i] + borderThickness;
+    return position - borderThickness;
+}
+
+int RenderFrameSet::hitTestSplit(const GridAxis& axis, int position) const
+{
+    if (needsLayout())
+        return noSplit;
+
+    int borderThickness = frameSet()->border();
+    if (borderThickness <= 0)
+        return noSplit;
+
+    size_t size = axis.m_sizes.size();
+    if (!size)
+        return noSplit;
+
+    int splitPosition = axis.m_sizes[0];
+    for (size_t i = 1; i < size; ++i) {
+        if (position >= splitPosition && position < splitPosition + borderThickness)
+            return i;
+        splitPosition += borderThickness + axis.m_sizes[i];
+    }
+    return noSplit;
+}
+
+bool RenderFrameSet::isChildAllowed(RenderObject* child, RenderStyle* style) const
+{
+    return child->isFrame() || child->isFrameSet();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderFrameSet.h b/WebCore/rendering/RenderFrameSet.h
new file mode 100644
index 0000000..066dbab
--- /dev/null
+++ b/WebCore/rendering/RenderFrameSet.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 2000 Simon Hausmann <[email protected]>
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderFrameSet_h
+#define RenderFrameSet_h
+
+#include "RenderContainer.h"
+
+namespace WebCore {
+
+class HTMLFrameSetElement;
+class MouseEvent;
+
+enum FrameEdge { LeftFrameEdge, RightFrameEdge, TopFrameEdge, BottomFrameEdge };
+
+struct FrameEdgeInfo
+{
+    FrameEdgeInfo(bool preventResize = false, bool allowBorder = true)
+        : m_preventResize(4)
+        , m_allowBorder(4)
+    {
+        m_preventResize.fill(preventResize);
+        m_allowBorder.fill(allowBorder);
+    }
+
+    bool preventResize(FrameEdge edge) const { return m_preventResize[edge]; }
+    bool allowBorder(FrameEdge edge) const { return m_allowBorder[edge]; }
+
+    void setPreventResize(FrameEdge edge, bool preventResize) { m_preventResize[edge] = preventResize; }
+    void setAllowBorder(FrameEdge edge, bool allowBorder) { m_allowBorder[edge] = allowBorder; }
+
+private:
+    Vector<bool> m_preventResize;
+    Vector<bool> m_allowBorder;
+};
+
+class RenderFrameSet : public RenderContainer {
+public:
+    RenderFrameSet(HTMLFrameSetElement*);
+    virtual ~RenderFrameSet();
+
+    virtual const char* renderName() const { return "RenderFrameSet"; }
+    virtual bool isFrameSet() const { return true; }
+
+    virtual void layout();
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+    virtual void paint(PaintInfo& paintInfo, int tx, int ty);
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+    
+    FrameEdgeInfo edgeInfo() const;
+
+    bool userResize(MouseEvent*);
+
+    bool isResizingRow() const;
+    bool isResizingColumn() const;
+
+    bool canResizeRow(const IntPoint&) const;
+    bool canResizeColumn(const IntPoint&) const;
+
+#ifdef FLATTEN_FRAMESET
+    void setGridNeedsLayout() { m_gridCalculated = false; }
+#endif
+    
+private:
+    static const int noSplit = -1;
+
+    class GridAxis : Noncopyable {
+    public:
+        GridAxis();
+        void resize(int);
+        Vector<int> m_sizes;
+        Vector<int> m_deltas;
+        Vector<bool> m_preventResize;
+        Vector<bool> m_allowBorder;
+        int m_splitBeingResized;
+        int m_splitResizeOffset;
+    };
+
+    inline HTMLFrameSetElement* frameSet() const;
+
+    bool canResize(const IntPoint&) const;
+    void setIsResizing(bool);
+
+    void layOutAxis(GridAxis&, const Length*, int availableSpace);
+    void computeEdgeInfo();
+    void fillFromEdgeInfo(const FrameEdgeInfo& edgeInfo, int r, int c);
+    void positionFrames();
+
+    int splitPosition(const GridAxis&, int split) const;
+    int hitTestSplit(const GridAxis&, int position) const;
+
+    void startResizing(GridAxis&, int position);
+    void continueResizing(GridAxis&, int position);
+
+    void paintRowBorder(const PaintInfo& paintInfo, const IntRect& rect);
+    void paintColumnBorder(const PaintInfo& paintInfo, const IntRect& rect);
+
+    GridAxis m_rows;
+    GridAxis m_cols;
+
+    bool m_isResizing;
+    bool m_isChildResizing;
+#ifdef FLATTEN_FRAMESET
+    bool m_gridCalculated;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // RenderFrameSet_h
diff --git a/WebCore/rendering/RenderHTMLCanvas.cpp b/WebCore/rendering/RenderHTMLCanvas.cpp
new file mode 100644
index 0000000..cc8c2c1
--- /dev/null
+++ b/WebCore/rendering/RenderHTMLCanvas.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "RenderHTMLCanvas.h"
+
+#include "Document.h"
+#include "GraphicsContext.h"
+#include "HTMLCanvasElement.h"
+#include "HTMLNames.h"
+#include "RenderView.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderHTMLCanvas::RenderHTMLCanvas(HTMLCanvasElement* element)
+    : RenderReplaced(element, element->size())
+{
+}
+
+void RenderHTMLCanvas::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
+{
+    IntRect rect = contentBox();
+    rect.move(tx, ty);
+    static_cast<HTMLCanvasElement*>(node())->paint(paintInfo.context, rect);
+}
+
+void RenderHTMLCanvas::canvasSizeChanged()
+{
+    IntSize size = static_cast<HTMLCanvasElement*>(node())->size();
+    IntSize zoomedSize(size.width() * style()->effectiveZoom(), size.height() * style()->effectiveZoom());
+
+    if (size == intrinsicSize())
+        return;
+
+    setIntrinsicSize(size);
+
+    if (!prefWidthsDirty())
+        setPrefWidthsDirty(true);
+
+    IntSize oldSize = IntSize(m_width, m_height);
+    calcWidth();
+    calcHeight();
+    if (oldSize == IntSize(m_width, m_height))
+        return;
+
+    if (!selfNeedsLayout())
+        setNeedsLayout(true);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderHTMLCanvas.h b/WebCore/rendering/RenderHTMLCanvas.h
new file mode 100644
index 0000000..ad6c505
--- /dev/null
+++ b/WebCore/rendering/RenderHTMLCanvas.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RenderHTMLCanvas_h
+#define RenderHTMLCanvas_h
+
+#include "RenderReplaced.h"
+
+namespace WebCore {
+
+class HTMLCanvasElement;
+
+class RenderHTMLCanvas : public RenderReplaced {
+public:
+    RenderHTMLCanvas(HTMLCanvasElement*);
+
+    virtual const char* renderName() const { return "RenderHTMLCanvas"; }
+
+    virtual void paintReplaced(PaintInfo& paintInfo, int tx, int ty);
+
+    void canvasSizeChanged();
+    
+protected:
+    virtual void intrinsicSizeChanged() { canvasSizeChanged(); }
+
+};
+
+} // namespace WebCore
+
+#endif // RenderHTMLCanvas_h
diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp
new file mode 100644
index 0000000..604c407
--- /dev/null
+++ b/WebCore/rendering/RenderImage.cpp
@@ -0,0 +1,593 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ *           (C) 2006 Allan Sandfeld Jensen ([email protected])
+ *           (C) 2006 Samuel Weinig ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderImage.h"
+
+#include "BitmapImage.h"
+#include "Document.h"
+#include "GraphicsContext.h"
+#include "HTMLImageElement.h"
+#include "HTMLInputElement.h"
+#include "HTMLMapElement.h"
+#include "HTMLNames.h"
+#include "HitTestResult.h"
+#include "Page.h"
+#include "RenderView.h"
+#ifdef ANDROID_LAYOUT
+#include "Settings.h"
+#endif
+
+#include "SystemTime.h"
+
+using namespace std;
+
+namespace WebCore {
+
+static const double cInterpolationCutoff = 800. * 800.;
+static const double cLowQualityTimeThreshold = 0.050; // 50 ms
+
+class RenderImageScaleData {
+public:
+    RenderImageScaleData(RenderImage* image, const IntSize& size, double time, bool lowQualityScale)
+        : m_size(size)
+        , m_time(time)
+        , m_lowQualityScale(lowQualityScale)
+        , m_highQualityRepaintTimer(image, &RenderImage::highQualityRepaintTimerFired)
+    {
+    }
+
+    ~RenderImageScaleData()
+    {
+        m_highQualityRepaintTimer.stop();
+    }
+    
+    const IntSize& size() const { return m_size; }
+    double time() const { return m_time; }
+    bool useLowQualityScale() const { return m_lowQualityScale; }
+    Timer<RenderImage>& hiqhQualityRepaintTimer() { return m_highQualityRepaintTimer; }
+
+    void setSize(const IntSize& s) { m_size = s; }
+    void setTime(double t) { m_time = t; }
+    void setUseLowQualityScale(bool b)
+    {
+        m_highQualityRepaintTimer.stop();
+        m_lowQualityScale = b;
+        if (b)
+            m_highQualityRepaintTimer.startOneShot(cLowQualityTimeThreshold);
+    }
+    
+private:
+    IntSize m_size;
+    double m_time;
+    bool m_lowQualityScale;
+    Timer<RenderImage> m_highQualityRepaintTimer;
+};
+
+class RenderImageScaleObserver
+{
+public:
+    static bool shouldImagePaintAtLowQuality(RenderImage*, const IntSize&);
+
+    static void imageDestroyed(RenderImage* image)
+    {
+        if (gImages) {
+            RenderImageScaleData* data = gImages->take(image);
+            delete data;
+            if (gImages->size() == 0) {
+                delete gImages;
+                gImages = 0;
+            }
+        }
+    }
+    
+    static void highQualityRepaintTimerFired(RenderImage* image)
+    {
+        RenderImageScaleObserver::imageDestroyed(image);
+        image->repaint();
+    }
+    
+    static HashMap<RenderImage*, RenderImageScaleData*>* gImages;
+};
+
+bool RenderImageScaleObserver::shouldImagePaintAtLowQuality(RenderImage* image, const IntSize& size)
+{
+    // If the image is not a bitmap image, then none of this is relevant and we just paint at high
+    // quality.
+    if (!image->image() || !image->image()->isBitmapImage())
+        return false;
+
+    // Make sure to use the unzoomed image size, since if a full page zoom is in effect, the image
+    // is actually being scaled.
+    IntSize imageSize(image->image()->width(), image->image()->height());
+
+    // Look ourselves up in the hashtable.
+    RenderImageScaleData* data = 0;
+    if (gImages)
+        data = gImages->get(image);
+
+    if (imageSize == size) {
+        // There is no scale in effect.  If we had a scale in effect before, we can just delete this data.
+        if (data) {
+            gImages->remove(image);
+            delete data;
+        }
+        return false;
+    }
+
+    // There is no need to hash scaled images that always use low quality mode when the page demands it.  This is the iChat case.
+    if (image->document()->page()->inLowQualityImageInterpolationMode()) {
+        double totalPixels = static_cast<double>(image->image()->width()) * static_cast<double>(image->image()->height());
+        if (totalPixels > cInterpolationCutoff)
+            return true;
+    }
+
+    // If there is no data yet, we will paint the first scale at high quality and record the paint time in case a second scale happens
+    // very soon.
+    if (!data) {
+        data = new RenderImageScaleData(image, size, currentTime(), false);
+        if (!gImages)
+            gImages = new HashMap<RenderImage*, RenderImageScaleData*>;
+        gImages->set(image, data);
+        return false;
+    }
+
+    // We are scaled, but we painted already at this size, so just keep using whatever mode we last painted with.
+    if (data->size() == size)
+        return data->useLowQualityScale();
+
+    // We have data and our size just changed.  If this change happened quickly, go into low quality mode and then set a repaint
+    // timer to paint in high quality mode.  Otherwise it is ok to just paint in high quality mode.
+    double newTime = currentTime();
+    data->setUseLowQualityScale(newTime - data->time() < cLowQualityTimeThreshold);
+    data->setTime(newTime);
+    data->setSize(size);
+    return data->useLowQualityScale();
+}
+
+HashMap<RenderImage*, RenderImageScaleData*>* RenderImageScaleObserver::gImages = 0;
+
+void RenderImage::highQualityRepaintTimerFired(Timer<RenderImage>* timer)
+{
+    RenderImageScaleObserver::highQualityRepaintTimerFired(this);
+}
+
+using namespace HTMLNames;
+
+RenderImage::RenderImage(Node* node)
+    : RenderReplaced(node, IntSize(0, 0))
+    , m_cachedImage(0)
+{
+    updateAltText();
+}
+
+RenderImage::~RenderImage()
+{
+    if (m_cachedImage)
+        m_cachedImage->removeClient(this);
+    RenderImageScaleObserver::imageDestroyed(this);
+}
+
+void RenderImage::setCachedImage(CachedImage* newImage)
+{
+    if (m_cachedImage == newImage)
+        return;
+    if (m_cachedImage)
+        m_cachedImage->removeClient(this);
+    m_cachedImage = newImage;
+    if (m_cachedImage) {
+        m_cachedImage->addClient(this);
+        if (m_cachedImage->errorOccurred())
+            imageChanged(m_cachedImage.get());
+    }
+}
+
+// If we'll be displaying either alt text or an image, add some padding.
+static const unsigned short paddingWidth = 4;
+static const unsigned short paddingHeight = 4;
+
+// Alt text is restricted to this maximum size, in pixels.  These are
+// signed integers because they are compared with other signed values.
+static const int maxAltTextWidth = 1024;
+static const int maxAltTextHeight = 256;
+
+// Sets the image height and width to fit the alt text.  Returns true if the
+// image size changed.
+bool RenderImage::setImageSizeForAltText(CachedImage* newImage /* = 0 */)
+{
+    int imageWidth = 0;
+    int imageHeight = 0;
+  
+    // If we'll be displaying either text or an image, add a little padding.
+    if (!m_altText.isEmpty() || newImage) {
+        imageWidth = paddingWidth;
+        imageHeight = paddingHeight;
+    }
+  
+    if (newImage) {
+        // imageSize() returns 0 for the error image.  We need the true size of the
+        // error image, so we have to get it by grabbing image() directly.
+        imageWidth += newImage->image()->width() * style()->effectiveZoom();
+        imageHeight += newImage->image()->height() * style()->effectiveZoom();
+    }
+  
+    // we have an alt and the user meant it (its not a text we invented)
+    if (!m_altText.isEmpty()) {
+        const Font& font = style()->font();
+        imageWidth = max(imageWidth, min(font.width(TextRun(m_altText.characters(), m_altText.length())), maxAltTextWidth));
+        imageHeight = max(imageHeight, min(font.height(), maxAltTextHeight));
+    }
+  
+    IntSize imageSize = IntSize(imageWidth, imageHeight);
+    if (imageSize == intrinsicSize())
+        return false;
+
+    setIntrinsicSize(imageSize);
+    return true;
+}
+
+void RenderImage::imageChanged(WrappedImagePtr newImage)
+{
+    if (documentBeingDestroyed())
+        return;
+
+    if (hasBoxDecorations() || hasMask())
+        RenderReplaced::imageChanged(newImage);
+    
+    if (newImage != imagePtr() || !newImage)
+        return;
+
+    bool imageSizeChanged = false;
+
+    // Set image dimensions, taking into account the size of the alt text.
+    if (errorOccurred())
+        imageSizeChanged = setImageSizeForAltText(m_cachedImage.get());
+    
+    bool shouldRepaint = true;
+
+    // Image dimensions have been changed, see what needs to be done
+    if (imageSize(style()->effectiveZoom()) != intrinsicSize() || imageSizeChanged) {
+        if (!errorOccurred())
+            setIntrinsicSize(imageSize(style()->effectiveZoom()));
+
+        // In the case of generated image content using :before/:after, we might not be in the
+        // render tree yet.  In that case, we don't need to worry about check for layout, since we'll get a
+        // layout when we get added in to the render tree hierarchy later.
+        if (containingBlock()) {
+            // lets see if we need to relayout at all..
+            int oldwidth = m_width;
+            int oldheight = m_height;
+            if (!prefWidthsDirty())
+                setPrefWidthsDirty(true);
+            calcWidth();
+            calcHeight();
+
+            if (imageSizeChanged || m_width != oldwidth || m_height != oldheight) {
+                shouldRepaint = false;
+                if (!selfNeedsLayout())
+                    setNeedsLayout(true);
+            }
+
+            m_width = oldwidth;
+            m_height = oldheight;
+        }
+    }
+
+    if (shouldRepaint) {
+        // FIXME: We always just do a complete repaint, since we always pass in the full image
+        // rect at the moment anyway.
+        repaintRectangle(contentBox());
+    }
+}
+
+void RenderImage::resetAnimation()
+{
+    if (m_cachedImage) {
+        image()->resetAnimation();
+        if (!needsLayout())
+            repaint();
+    }
+}
+
+void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
+{
+    int cWidth = contentWidth();
+    int cHeight = contentHeight();
+    int leftBorder = borderLeft();
+    int topBorder = borderTop();
+    int leftPad = paddingLeft();
+    int topPad = paddingTop();
+
+    if (document()->printing() && !view()->printImages())
+        return;
+
+    GraphicsContext* context = paintInfo.context;
+
+    if (!hasImage() || errorOccurred()) {
+        if (paintInfo.phase == PaintPhaseSelection)
+            return;
+
+        if (cWidth > 2 && cHeight > 2) {
+            // Draw an outline rect where the image should be.
+            context->setStrokeStyle(SolidStroke);
+            context->setStrokeColor(Color::lightGray);
+            context->setFillColor(Color::transparent);
+            context->drawRect(IntRect(tx + leftBorder + leftPad, ty + topBorder + topPad, cWidth, cHeight));
+
+            bool errorPictureDrawn = false;
+            int imageX = 0;
+            int imageY = 0;
+            // When calculating the usable dimensions, exclude the pixels of
+            // the ouline rect so the error image/alt text doesn't draw on it.
+            int usableWidth = cWidth - 2;
+            int usableHeight = cHeight - 2;
+
+            if (errorOccurred() && !image()->isNull() && (usableWidth >= image()->width()) && (usableHeight >= image()->height())) {
+                // Center the error image, accounting for border and padding.
+                int centerX = (usableWidth - image()->width()) / 2;
+                if (centerX < 0)
+                    centerX = 0;
+                int centerY = (usableHeight - image()->height()) / 2;
+                if (centerY < 0)
+                    centerY = 0;
+                imageX = leftBorder + leftPad + centerX + 1;
+                imageY = topBorder + topPad + centerY + 1;
+                context->drawImage(image(), IntPoint(tx + imageX, ty + imageY));
+                errorPictureDrawn = true;
+            }
+
+            if (!m_altText.isEmpty()) {
+                String text = m_altText;
+                text.replace('\\', backslashAsCurrencySymbol());
+                context->setFont(style()->font());
+                context->setFillColor(style()->color());
+                int ax = tx + leftBorder + leftPad;
+                int ay = ty + topBorder + topPad;
+                const Font& font = style()->font();
+                int ascent = font.ascent();
+
+                // Only draw the alt text if it'll fit within the content box,
+                // and only if it fits above the error image.
+                TextRun textRun(text.characters(), text.length());
+                int textWidth = font.width(textRun);
+                if (errorPictureDrawn) {
+                    if (usableWidth >= textWidth && font.height() <= imageY)
+                        context->drawText(textRun, IntPoint(ax, ay + ascent));
+                } else if (usableWidth >= textWidth && cHeight >= font.height())
+                    context->drawText(textRun, IntPoint(ax, ay + ascent));
+            }
+        }
+    } else if (hasImage() && cWidth > 0 && cHeight > 0) {
+        Image* img = image(cWidth, cHeight);
+        if (!img || img->isNull())
+            return;
+
+#if PLATFORM(MAC)
+        if (style()->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
+            paintCustomHighlight(tx - m_x, ty - m_y, style()->highlight(), true);
+#endif
+
+        IntSize contentSize(cWidth, cHeight);
+        bool useLowQualityScaling = RenderImageScaleObserver::shouldImagePaintAtLowQuality(this, contentSize);
+        IntRect rect(IntPoint(tx + leftBorder + leftPad, ty + topBorder + topPad), contentSize);
+        HTMLImageElement* imageElt = (element() && element()->hasTagName(imgTag)) ? static_cast<HTMLImageElement*>(element()) : 0;
+        CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver;
+        context->drawImage(image(cWidth, cHeight), rect, compositeOperator, useLowQualityScaling);
+    }
+}
+
+int RenderImage::minimumReplacedHeight() const
+{
+    return errorOccurred() ? intrinsicSize().height() : 0;
+}
+
+HTMLMapElement* RenderImage::imageMap()
+{
+    HTMLImageElement* i = element() && element()->hasTagName(imgTag) ? static_cast<HTMLImageElement*>(element()) : 0;
+    return i ? i->document()->getImageMap(i->useMap()) : 0;
+}
+
+bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
+{
+    bool inside = RenderReplaced::nodeAtPoint(request, result, _x, _y, _tx, _ty, hitTestAction);
+
+    if (inside && element()) {
+        int tx = _tx + m_x;
+        int ty = _ty + m_y;
+        
+        HTMLMapElement* map = imageMap();
+        if (map) {
+            // we're a client side image map
+            inside = map->mapMouseEvent(_x - tx, _y - ty, IntSize(contentWidth(), contentHeight()), result);
+            result.setInnerNonSharedNode(element());
+        }
+    }
+
+    return inside;
+}
+
+void RenderImage::updateAltText()
+{
+    if (!element())
+        return;
+
+    if (element()->hasTagName(inputTag))
+        m_altText = static_cast<HTMLInputElement*>(element())->altText();
+    else if (element()->hasTagName(imgTag))
+        m_altText = static_cast<HTMLImageElement*>(element())->altText();
+}
+
+bool RenderImage::isWidthSpecified() const
+{
+    switch (style()->width().type()) {
+        case Fixed:
+        case Percent:
+            return true;
+        case Auto:
+        case Relative: // FIXME: Shouldn't this case return true?
+        case Static:
+        case Intrinsic:
+        case MinIntrinsic:
+            return false;
+    }
+    ASSERT(false);
+    return false;
+}
+
+bool RenderImage::isHeightSpecified() const
+{
+    switch (style()->height().type()) {
+        case Fixed:
+        case Percent:
+            return true;
+        case Auto:
+        case Relative: // FIXME: Shouldn't this case return true?
+        case Static:
+        case Intrinsic:
+        case MinIntrinsic:
+            return false;
+    }
+    ASSERT(false);
+    return false;
+}
+
+int RenderImage::calcReplacedWidth(bool includeMaxWidth) const
+{
+    if (imageHasRelativeWidth())
+        if (RenderObject* cb = isPositioned() ? container() : containingBlock())
+            setImageContainerSize(IntSize(cb->availableWidth(), cb->availableHeight()));
+
+    int width;
+    if (isWidthSpecified())
+        width = calcReplacedWidthUsing(style()->width());
+    else if (usesImageContainerSize())
+        width = imageSize(style()->effectiveZoom()).width();
+    else if (imageHasRelativeWidth())
+        width = 0; // If the image is relatively-sized, set the width to 0 until there is a set container size.
+    else
+        width = calcAspectRatioWidth();
+
+    int minW = calcReplacedWidthUsing(style()->minWidth());
+    int maxW = !includeMaxWidth || style()->maxWidth().isUndefined() ? width : calcReplacedWidthUsing(style()->maxWidth());
+
+#ifdef ANDROID_LAYOUT
+    width = max(minW, min(width, maxW));
+    // in SSR mode, we will fit the image to its container width
+    if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) {
+        int cw = containingBlockWidth();
+        if (cw && width>cw)
+            width = cw;
+    }
+    return width;
+#else
+     return max(minW, min(width, maxW));
+#endif
+}
+
+int RenderImage::calcReplacedHeight() const
+{
+    int height;
+    if (isHeightSpecified())
+        height = calcReplacedHeightUsing(style()->height());
+    else if (usesImageContainerSize())
+        height = imageSize(style()->effectiveZoom()).height();
+    else if (imageHasRelativeHeight())
+        height = 0; // If the image is relatively-sized, set the height to 0 until there is a set container size.
+    else
+        height = calcAspectRatioHeight();
+
+    int minH = calcReplacedHeightUsing(style()->minHeight());
+    int maxH = style()->maxHeight().isUndefined() ? height : calcReplacedHeightUsing(style()->maxHeight());
+
+#ifdef ANDROID_LAYOUT
+    height = max(minH, min(height, maxH));
+    // in SSR mode, we will fit the image to its container width
+    if (height && document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) {        
+        int width;
+        if (isWidthSpecified())
+            width = calcReplacedWidthUsing(style()->width());
+        else
+            width = calcAspectRatioWidth();
+        int minW = calcReplacedWidthUsing(style()->minWidth());
+        int maxW = style()->maxWidth().value() == undefinedLength ? width : 
+        	calcReplacedWidthUsing(style()->maxWidth());
+        width = max(minW, min(width, maxW));
+
+        int cw = containingBlockWidth();
+        if (cw && width && width>cw)
+            height = cw * height / width;   // preserve aspect ratio
+    }
+    return height;
+#else
+    return max(minH, min(height, maxH));
+#endif
+}
+
+int RenderImage::calcAspectRatioWidth() const
+{
+    IntSize size = intrinsicSize();
+    if (!size.height())
+        return 0;
+    if (!hasImage() || errorOccurred())
+        return size.width(); // Don't bother scaling.
+    return RenderReplaced::calcReplacedHeight() * size.width() / size.height();
+}
+
+int RenderImage::calcAspectRatioHeight() const
+{
+    IntSize size = intrinsicSize();
+    if (!size.width())
+        return 0;
+    if (!hasImage() || errorOccurred())
+        return size.height(); // Don't bother scaling.
+    return RenderReplaced::calcReplacedWidth() * size.height() / size.width();
+}
+
+void RenderImage::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+
+    int paddingAndBorders = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+    m_maxPrefWidth = calcReplacedWidth(false) + paddingAndBorders;
+
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength)
+        m_maxPrefWidth = min(m_maxPrefWidth, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? paddingAndBorders : 0));
+
+    if (style()->width().isPercent() || style()->height().isPercent() || 
+        style()->maxWidth().isPercent() || style()->maxHeight().isPercent() ||
+        style()->minWidth().isPercent() || style()->minHeight().isPercent())
+        m_minPrefWidth = 0;
+    else
+        m_minPrefWidth = m_maxPrefWidth;
+
+    setPrefWidthsDirty(false);
+}
+
+Image* RenderImage::nullImage()
+{
+    return Image::nullImage();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderImage.h b/WebCore/rendering/RenderImage.h
new file mode 100644
index 0000000..477fdeb
--- /dev/null
+++ b/WebCore/rendering/RenderImage.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ *           (C) 2006 Allan Sandfeld Jensen ([email protected]) 
+ *           (C) 2006 Samuel Weinig ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderImage_h
+#define RenderImage_h
+
+#include "CachedImage.h"
+#include "CachedResourceHandle.h"
+#include "RenderReplaced.h"
+
+namespace WebCore {
+
+class HTMLMapElement;
+
+class RenderImage : public RenderReplaced {
+public:
+    RenderImage(Node*);
+    virtual ~RenderImage();
+
+    virtual const char* renderName() const { return "RenderImage"; }
+
+    virtual bool isImage() const { return true; }
+    virtual bool isRenderImage() const { return true; }
+    
+    virtual void paintReplaced(PaintInfo& paintInfo, int tx, int ty);
+
+    virtual int minimumReplacedHeight() const;
+
+    virtual void imageChanged(WrappedImagePtr);
+    
+    bool setImageSizeForAltText(CachedImage* newImage = 0);
+
+    void updateAltText();
+
+    void setCachedImage(CachedImage*);
+    CachedImage* cachedImage() const { return m_cachedImage.get(); }
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+    virtual int calcReplacedWidth(bool includeMaxWidth = true) const;
+    virtual int calcReplacedHeight() const;
+
+    virtual void calcPrefWidths();
+
+    HTMLMapElement* imageMap();
+
+    void resetAnimation();
+
+    virtual bool hasImage() const { return m_cachedImage; }
+
+    void highQualityRepaintTimerFired(Timer<RenderImage>*);
+
+protected:
+    virtual Image* image(int w = 0, int h = 0) { return m_cachedImage ? m_cachedImage->image() : nullImage(); }
+    virtual bool errorOccurred() const { return m_cachedImage && m_cachedImage->errorOccurred(); }
+    virtual bool usesImageContainerSize() const { return m_cachedImage ? m_cachedImage->usesImageContainerSize() : false; }
+    virtual void setImageContainerSize(const IntSize& size) const { if (m_cachedImage) m_cachedImage->setImageContainerSize(size); }
+    virtual bool imageHasRelativeWidth() const { return m_cachedImage ? m_cachedImage->imageHasRelativeWidth() : false; }
+    virtual bool imageHasRelativeHeight() const { return m_cachedImage ? m_cachedImage->imageHasRelativeHeight() : false; }
+    virtual IntSize imageSize(float multiplier) const { return m_cachedImage ? m_cachedImage->imageSize(multiplier) : IntSize(); }
+    virtual WrappedImagePtr imagePtr() const { return m_cachedImage.get(); }
+
+    virtual void intrinsicSizeChanged() { imageChanged(imagePtr()); }
+
+private:
+    int calcAspectRatioWidth() const;
+    int calcAspectRatioHeight() const;
+
+    bool isWidthSpecified() const;
+    bool isHeightSpecified() const;
+
+protected:
+    // The image we are rendering.
+    CachedResourceHandle<CachedImage> m_cachedImage;
+
+    // Text to display as long as the image isn't available.
+    String m_altText;
+
+    static Image* nullImage();
+    
+    friend class RenderImageScaleObserver;
+};
+
+} // namespace WebCore
+
+#endif // RenderImage_h
diff --git a/WebCore/rendering/RenderImageGeneratedContent.cpp b/WebCore/rendering/RenderImageGeneratedContent.cpp
new file mode 100644
index 0000000..29d0508
--- /dev/null
+++ b/WebCore/rendering/RenderImageGeneratedContent.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "RenderImageGeneratedContent.h"
+
+#include "RenderBlock.h"
+#include "RenderStyle.h"
+#include "StyleCachedImage.h"
+
+namespace WebCore {
+
+RenderImageGeneratedContent::RenderImageGeneratedContent(Node* n)
+: RenderImage(n)
+{}
+
+RenderImageGeneratedContent::~RenderImageGeneratedContent()
+{
+    m_cachedImage = 0;
+    m_styleImage->removeClient(this);
+}
+
+void RenderImageGeneratedContent::setStyleImage(StyleImage* image)
+{
+    if (image->isCachedImage())
+        m_cachedImage = static_cast<StyleCachedImage*>(image)->cachedImage();
+    m_styleImage = image;
+    m_styleImage->addClient(this);
+}
+
+}
diff --git a/WebCore/rendering/RenderImageGeneratedContent.h b/WebCore/rendering/RenderImageGeneratedContent.h
new file mode 100644
index 0000000..cab0192
--- /dev/null
+++ b/WebCore/rendering/RenderImageGeneratedContent.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RenderImageGeneratedContent_h
+#define RenderImageGeneratedContent_h
+
+#include "RenderImage.h"
+#include <wtf/RefPtr.h>
+
+#include "RenderStyle.h"
+
+namespace WebCore {
+
+class StyleImage;
+
+class RenderImageGeneratedContent : public RenderImage
+{
+public:
+    RenderImageGeneratedContent(Node*);
+    virtual ~RenderImageGeneratedContent();
+    
+    void setStyleImage(StyleImage*);
+    
+    virtual bool hasImage() const { return true; }
+    
+protected:
+    virtual Image* image(int w = 0, int h = 0) { return m_styleImage->image(this, IntSize(w, h)); }
+    virtual bool errorOccurred() const { return m_styleImage->errorOccurred(); }
+    virtual bool usesImageContainerSize() const { return m_styleImage->usesImageContainerSize(); }
+    virtual void setImageContainerSize(const IntSize& size) const { m_styleImage->setImageContainerSize(size); }
+    virtual bool imageHasRelativeWidth() const { return m_styleImage->imageHasRelativeWidth(); }
+    virtual bool imageHasRelativeHeight() const { return m_styleImage->imageHasRelativeHeight(); }
+    virtual IntSize imageSize(float multiplier) const { return m_styleImage->imageSize(this, multiplier); }
+    virtual WrappedImagePtr imagePtr() const { return m_styleImage->data(); }
+
+private:
+    RefPtr<StyleImage> m_styleImage;
+};
+
+}
+
+#endif
diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp
new file mode 100644
index 0000000..79d914f
--- /dev/null
+++ b/WebCore/rendering/RenderInline.cpp
@@ -0,0 +1,383 @@
+/*
+ * This file is part of the render object implementation for KHTML.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderInline.h"
+
+#include "Document.h"
+#include "RenderArena.h"
+#include "RenderBlock.h"
+#include "VisiblePosition.h"
+
+namespace WebCore {
+
+RenderInline::RenderInline(Node* node)
+    : RenderFlow(node)
+{
+}
+
+RenderInline::~RenderInline()
+{
+}
+
+void RenderInline::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderFlow::styleDidChange(diff, oldStyle);
+
+    setInline(true);
+    setHasReflection(false);
+
+    // Ensure that all of the split inlines pick up the new style. We
+    // only do this if we're an inline, since we don't want to propagate
+    // a block's style to the other inlines.
+    // e.g., <font>foo <h4>goo</h4> moo</font>.  The <font> inlines before
+    // and after the block share the same style, but the block doesn't
+    // need to pass its style on to anyone else.
+    RenderFlow* currCont = continuation();
+    while (currCont) {
+        if (currCont->isInline()) {
+            RenderFlow* nextCont = currCont->continuation();
+            currCont->setContinuation(0);
+            currCont->setStyle(style());
+            currCont->setContinuation(nextCont);
+        }
+        currCont = currCont->continuation();
+    }
+
+    m_lineHeight = -1;
+
+    // Update pseudos for :before and :after now.
+    if (!isAnonymous()) {
+        updateBeforeAfterContent(RenderStyle::BEFORE);
+        updateBeforeAfterContent(RenderStyle::AFTER);
+    }
+}
+
+bool RenderInline::isInlineContinuation() const
+{
+    return m_isContinuation;
+}
+
+static inline bool isAfterContent(RenderObject* child)
+{
+    if (!child)
+        return false;
+    if (child->style()->styleType() != RenderStyle::AFTER)
+        return false;
+    // Text nodes don't have their own styles, so ignore the style on a text node.
+    if (child->isText() && !child->isBR())
+        return false;
+    return true;
+}
+
+void RenderInline::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild)
+{
+    // Make sure we don't append things after :after-generated content if we have it.
+    if (!beforeChild && isAfterContent(lastChild()))
+        beforeChild = lastChild();
+
+    if (!newChild->isInline() && !newChild->isFloatingOrPositioned()) {
+        // We are placing a block inside an inline. We have to perform a split of this
+        // inline into continuations.  This involves creating an anonymous block box to hold
+        // |newChild|.  We then make that block box a continuation of this inline.  We take all of
+        // the children after |beforeChild| and put them in a clone of this object.
+        RefPtr<RenderStyle> newStyle = RenderStyle::create();
+        newStyle->inheritFrom(style());
+        newStyle->setDisplay(BLOCK);
+
+        RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
+        newBox->setStyle(newStyle.release());
+        RenderFlow* oldContinuation = continuation();
+        setContinuation(newBox);
+
+        // Someone may have put a <p> inside a <q>, causing a split.  When this happens, the :after content
+        // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that our :after
+        // content gets properly destroyed.
+        bool isLastChild = (beforeChild == lastChild());
+        updateBeforeAfterContent(RenderStyle::AFTER);
+        if (isLastChild && beforeChild != lastChild())
+            beforeChild = 0; // We destroyed the last child, so now we need to update our insertion
+                             // point to be 0.  It's just a straight append now.
+
+        splitFlow(beforeChild, newBox, newChild, oldContinuation);
+        return;
+    }
+
+    RenderContainer::addChild(newChild, beforeChild);
+
+    newChild->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+RenderInline* RenderInline::cloneInline(RenderFlow* src)
+{
+    RenderInline* o = new (src->renderArena()) RenderInline(src->element());
+    o->m_isContinuation = true;
+    o->setStyle(src->style());
+    return o;
+}
+
+void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
+                                RenderBlock* middleBlock,
+                                RenderObject* beforeChild, RenderFlow* oldCont)
+{
+    // Create a clone of this inline.
+    RenderInline* clone = cloneInline(this);
+    clone->setContinuation(oldCont);
+
+    // Now take all of the children from beforeChild to the end and remove
+    // them from |this| and place them in the clone.
+    RenderObject* o = beforeChild;
+    while (o) {
+        RenderObject* tmp = o;
+        o = tmp->nextSibling();
+        clone->addChildToFlow(removeChildNode(tmp), 0);
+        tmp->setNeedsLayoutAndPrefWidthsRecalc();
+    }
+
+    // Hook |clone| up as the continuation of the middle block.
+    middleBlock->setContinuation(clone);
+
+    // We have been reparented and are now under the fromBlock.  We need
+    // to walk up our inline parent chain until we hit the containing block.
+    // Once we hit the containing block we're done.
+    RenderFlow* curr = static_cast<RenderFlow*>(parent());
+    RenderFlow* currChild = this;
+    
+    // FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone.
+    // There will eventually be a better approach to this problem that will let us nest to a much
+    // greater depth (see bugzilla bug 13430) but for now we have a limit.  This *will* result in
+    // incorrect rendering, but the alternative is to hang forever.
+    unsigned splitDepth = 1;
+    const unsigned cMaxSplitDepth = 200; 
+    while (curr && curr != fromBlock) {
+        if (splitDepth < cMaxSplitDepth) {
+            // Create a new clone.
+            RenderInline* cloneChild = clone;
+            clone = cloneInline(curr);
+
+            // Insert our child clone as the first child.
+            clone->addChildToFlow(cloneChild, 0);
+
+            // Hook the clone up as a continuation of |curr|.
+            RenderFlow* oldCont = curr->continuation();
+            curr->setContinuation(clone);
+            clone->setContinuation(oldCont);
+
+            // Someone may have indirectly caused a <q> to split.  When this happens, the :after content
+            // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that the inline's :after
+            // content gets properly destroyed.
+            curr->updateBeforeAfterContent(RenderStyle::AFTER);
+
+            // Now we need to take all of the children starting from the first child
+            // *after* currChild and append them all to the clone.
+            o = currChild->nextSibling();
+            while (o) {
+                RenderObject* tmp = o;
+                o = tmp->nextSibling();
+                clone->addChildToFlow(curr->removeChildNode(tmp), 0);
+                tmp->setNeedsLayoutAndPrefWidthsRecalc();
+            }
+        }
+        
+        // Keep walking up the chain.
+        currChild = curr;
+        curr = static_cast<RenderFlow*>(curr->parent());
+        splitDepth++;
+    }
+
+    // Now we are at the block level. We need to put the clone into the toBlock.
+    toBlock->appendChildNode(clone);
+
+    // Now take all the children after currChild and remove them from the fromBlock
+    // and put them in the toBlock.
+    o = currChild->nextSibling();
+    while (o) {
+        RenderObject* tmp = o;
+        o = tmp->nextSibling();
+        toBlock->appendChildNode(fromBlock->removeChildNode(tmp));
+    }
+}
+
+void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
+                             RenderObject* newChild, RenderFlow* oldCont)
+{
+    RenderBlock* pre = 0;
+    RenderBlock* block = containingBlock();
+    
+    // Delete our line boxes before we do the inline split into continuations.
+    block->deleteLineBoxTree();
+    
+    bool madeNewBeforeBlock = false;
+    if (block->isAnonymousBlock() && (!block->parent() || !block->parent()->createsAnonymousWrapper())) {
+        // We can reuse this block and make it the preBlock of the next continuation.
+        pre = block;
+        block = block->containingBlock();
+    } else {
+        // No anonymous block available for use.  Make one.
+        pre = block->createAnonymousBlock();
+        madeNewBeforeBlock = true;
+    }
+
+    RenderBlock* post = block->createAnonymousBlock();
+
+    RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
+    if (madeNewBeforeBlock)
+        block->insertChildNode(pre, boxFirst);
+    block->insertChildNode(newBlockBox, boxFirst);
+    block->insertChildNode(post, boxFirst);
+    block->setChildrenInline(false);
+    
+    if (madeNewBeforeBlock) {
+        RenderObject* o = boxFirst;
+        while (o) {
+            RenderObject* no = o;
+            o = no->nextSibling();
+            pre->appendChildNode(block->removeChildNode(no));
+            no->setNeedsLayoutAndPrefWidthsRecalc();
+        }
+    }
+
+    splitInlines(pre, post, newBlockBox, beforeChild, oldCont);
+
+    // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
+    // time in makeChildrenNonInline by just setting this explicitly up front.
+    newBlockBox->setChildrenInline(false);
+
+    // We don't just call addChild, since it would pass things off to the
+    // continuation, so we call addChildToFlow explicitly instead.  We delayed
+    // adding the newChild until now so that the |newBlockBox| would be fully
+    // connected, thus allowing newChild access to a renderArena should it need
+    // to wrap itself in additional boxes (e.g., table construction).
+    newBlockBox->addChildToFlow(newChild, 0);
+
+    // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
+    // get deleted properly.  Because objects moves from the pre block into the post block, we want to
+    // make new line boxes instead of leaving the old line boxes around.
+    pre->setNeedsLayoutAndPrefWidthsRecalc();
+    block->setNeedsLayoutAndPrefWidthsRecalc();
+    post->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+void RenderInline::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    paintLines(paintInfo, tx, ty);
+}
+
+void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel)
+{
+    for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+        rects.append(IntRect(tx + curr->xPos(), ty + curr->yPos(), curr->width(), curr->height()));
+
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+        if (!curr->isText())
+            curr->absoluteRects(rects, tx + curr->xPos(), ty + curr->yPos(), false);
+    }
+
+    if (continuation() && topLevel)
+        continuation()->absoluteRects(rects, 
+                                      tx - containingBlock()->xPos() + continuation()->xPos(),
+                                      ty - containingBlock()->yPos() + continuation()->yPos(),
+                                      topLevel);
+}
+
+bool RenderInline::requiresLayer()
+{
+    return isRelPositioned() || isTransparent() || hasMask();
+}
+
+int RenderInline::width() const
+{
+    // Return the width of the minimal left side and the maximal right side.
+    int leftSide = 0;
+    int rightSide = 0;
+    for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+        if (curr == firstLineBox() || curr->xPos() < leftSide)
+            leftSide = curr->xPos();
+        if (curr == firstLineBox() || curr->xPos() + curr->width() > rightSide)
+            rightSide = curr->xPos() + curr->width();
+    }
+
+    return rightSide - leftSide;
+}
+
+int RenderInline::height() const
+{
+    // See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero.  We have been
+    // unable to reproduce this at all (and consequently unable to figure ot why this is happening).  The assert will hopefully catch the problem in debug
+    // builds and help us someday figure out why.  We also put in a redundant check of lastLineBox() to avoid the crash for now.
+    ASSERT(!firstLineBox() == !lastLineBox());  // Either both are null or both exist.
+    if (firstLineBox() && lastLineBox())
+        return lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
+    return 0;
+}
+
+int RenderInline::offsetLeft() const
+{
+    int x = RenderFlow::offsetLeft();
+    if (firstLineBox())
+        x += firstLineBox()->xPos();
+    return x;
+}
+
+int RenderInline::offsetTop() const
+{
+    int y = RenderFlow::offsetTop();
+    if (firstLineBox())
+        y += firstLineBox()->yPos();
+    return y;
+}
+
+const char* RenderInline::renderName() const
+{
+    if (isRelPositioned())
+        return "RenderInline (relative positioned)";
+    if (isAnonymous())
+        return "RenderInline (generated)";
+    return "RenderInline";
+}
+
+bool RenderInline::nodeAtPoint(const HitTestRequest& request, HitTestResult& result,
+                                int x, int y, int tx, int ty, HitTestAction hitTestAction)
+{
+    return hitTestLines(request, result, x, y, tx, ty, hitTestAction);
+}
+
+VisiblePosition RenderInline::positionForCoordinates(int x, int y)
+{
+    // Translate the coords from the pre-anonymous block to the post-anonymous block.
+    RenderBlock* cb = containingBlock();
+    int parentBlockX = cb->xPos() + x;
+    int parentBlockY = cb->yPos() + y;
+    for (RenderObject* c = continuation(); c; c = c->continuation()) {
+        RenderObject* contBlock = c;
+        if (c->isInline())
+            contBlock = c->containingBlock();
+        if (c->isInline() || c->firstChild())
+            return c->positionForCoordinates(parentBlockX - contBlock->xPos(), parentBlockY - contBlock->yPos());
+    }
+
+    return RenderFlow::positionForCoordinates(x, y);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderInline.h b/WebCore/rendering/RenderInline.h
new file mode 100644
index 0000000..36cb864
--- /dev/null
+++ b/WebCore/rendering/RenderInline.h
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the render object implementation for KHTML.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderInline_h
+#define RenderInline_h
+
+#include "RenderFlow.h"
+
+namespace WebCore {
+
+class Position;
+
+class RenderInline : public RenderFlow {
+public:
+    RenderInline(Node*);
+    virtual ~RenderInline();
+
+    virtual const char* renderName() const;
+
+    virtual bool isRenderInline() const { return true; }
+    virtual bool isInlineFlow() const { return true; }
+    virtual bool childrenInline() const { return true; }
+
+    virtual bool isInlineContinuation() const;
+
+    virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild);
+    void splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
+                      RenderObject* beforeChild, RenderFlow* oldCont);
+    void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
+                   RenderObject* newChild, RenderFlow* oldCont);
+
+    virtual void layout() { } // Do nothing for layout()
+
+    virtual void paint(PaintInfo&, int tx, int ty);
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+    // overrides RenderObject
+    virtual bool requiresLayer();
+
+    virtual int width() const;
+    virtual int height() const;
+
+    // used to calculate offsetWidth/Height.  Overridden by inlines (RenderFlow) to return
+    // the remaining width on a given line (and the height of a single line).
+    virtual int offsetLeft() const;
+    virtual int offsetTop() const;
+
+    void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
+
+    virtual VisiblePosition positionForCoordinates(int x, int y);
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+    static RenderInline* cloneInline(RenderFlow* src);
+
+};
+
+} // namespace WebCore
+
+#endif // RenderInline_h
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp
new file mode 100644
index 0000000..93efde1
--- /dev/null
+++ b/WebCore/rendering/RenderLayer.cpp
@@ -0,0 +1,2572 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Robert O'Callahan <[email protected]>
+ *   David Baron <[email protected]>
+ *   Christian Biesinger <[email protected]>
+ *   Randall Jesup <[email protected]>
+ *   Roland Mainz <[email protected]>
+ *   Josh Soref <[email protected]>
+ *   Boris Zbarsky <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above.  If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "config.h"
+#include "RenderLayer.h"
+
+#include "CSSPropertyNames.h"
+#include "Document.h"
+#include "EventHandler.h"
+#include "EventNames.h"
+#include "FloatRect.h"
+#include "FocusController.h"
+#include "Frame.h"
+#include "FrameTree.h"
+#include "FrameView.h"
+#include "Gradient.h"
+#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "HitTestRequest.h"
+#include "HitTestResult.h"
+#include "OverflowEvent.h"
+#include "Page.h"
+#include "PlatformMouseEvent.h"
+#include "RenderArena.h"
+#include "RenderInline.h"
+#include "RenderMarquee.h"
+#include "RenderReplica.h"
+#include "RenderScrollbar.h"
+#include "RenderScrollbarPart.h"
+#include "RenderTheme.h"
+#include "RenderView.h"
+#include "ScaleTransformOperation.h"
+#include "Scrollbar.h"
+#include "ScrollbarTheme.h"
+#include "SelectionController.h"
+#include "TranslateTransformOperation.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#endif
+
+#define MIN_INTERSECT_FOR_REVEAL 32
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+const RenderLayer::ScrollAlignment RenderLayer::gAlignCenterIfNeeded = { RenderLayer::noScroll, RenderLayer::alignCenter, RenderLayer::alignToClosestEdge };
+const RenderLayer::ScrollAlignment RenderLayer::gAlignToEdgeIfNeeded = { RenderLayer::noScroll, RenderLayer::alignToClosestEdge, RenderLayer::alignToClosestEdge };
+const RenderLayer::ScrollAlignment RenderLayer::gAlignCenterAlways = { RenderLayer::alignCenter, RenderLayer::alignCenter, RenderLayer::alignCenter };
+const RenderLayer::ScrollAlignment RenderLayer::gAlignTopAlways = { RenderLayer::alignTop, RenderLayer::alignTop, RenderLayer::alignTop };
+const RenderLayer::ScrollAlignment RenderLayer::gAlignBottomAlways = { RenderLayer::alignBottom, RenderLayer::alignBottom, RenderLayer::alignBottom };
+
+const int MinimumWidthWhileResizing = 100;
+const int MinimumHeightWhileResizing = 40;
+
+void* ClipRects::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void ClipRects::operator delete(void* ptr, size_t sz)
+{
+    // Stash size where destroy can find it.
+    *(size_t *)ptr = sz;
+}
+
+void ClipRects::destroy(RenderArena* renderArena)
+{
+    delete this;
+    
+    // Recover the size left there for us by operator delete and free the memory.
+    renderArena->free(*(size_t *)this, this);
+}
+
+RenderLayer::RenderLayer(RenderObject* object)
+    : m_object(object)
+    , m_parent(0)
+    , m_previous(0)
+    , m_next(0)
+    , m_first(0)
+    , m_last(0)
+    , m_relX(0)
+    , m_relY(0)
+    , m_x(0)
+    , m_y(0)
+    , m_width(0)
+    , m_height(0)
+    , m_scrollX(0)
+    , m_scrollY(0)
+    , m_scrollOriginX(0)
+    , m_scrollLeftOverflow(0)
+    , m_scrollWidth(0)
+    , m_scrollHeight(0)
+    , m_inResizeMode(false)
+    , m_posZOrderList(0)
+    , m_negZOrderList(0)
+    , m_overflowList(0)
+    , m_clipRects(0) 
+    , m_scrollDimensionsDirty(true)
+    , m_zOrderListsDirty(true)
+    , m_overflowListDirty(true)
+    , m_isOverflowOnly(shouldBeOverflowOnly())
+    , m_usedTransparency(false)
+    , m_paintingInsideReflection(false)
+    , m_inOverflowRelayout(false)
+    , m_needsFullRepaint(false)
+    , m_overflowStatusDirty(true)
+    , m_visibleContentStatusDirty(true)
+    , m_hasVisibleContent(false)
+    , m_visibleDescendantStatusDirty(false)
+    , m_hasVisibleDescendant(false)
+    , m_marquee(0)
+    , m_staticX(0)
+    , m_staticY(0)
+    , m_transform(0)
+    , m_reflection(0)
+    , m_scrollCorner(0)
+    , m_resizer(0)
+{
+    if (!object->firstChild() && object->style()) {
+        m_visibleContentStatusDirty = false;
+        m_hasVisibleContent = object->style()->visibility() == VISIBLE;
+    }
+}
+
+RenderLayer::~RenderLayer()
+{
+    if (inResizeMode() && !renderer()->documentBeingDestroyed()) {
+        if (Frame* frame = renderer()->document()->frame())
+            frame->eventHandler()->resizeLayerDestroyed();
+    }
+
+    destroyScrollbar(HorizontalScrollbar);
+    destroyScrollbar(VerticalScrollbar);
+
+    // Child layers will be deleted by their corresponding render objects, so
+    // we don't need to delete them ourselves.
+
+    delete m_posZOrderList;
+    delete m_negZOrderList;
+    delete m_overflowList;
+    delete m_marquee;
+
+    // Make sure we have no lingering clip rects.
+    ASSERT(!m_clipRects);
+    
+    if (m_reflection) {
+        if (!m_reflection->documentBeingDestroyed())
+            m_reflection->removeLayers(this);
+        m_reflection->setParent(0);
+        m_reflection->destroy();
+    }
+    
+    if (m_scrollCorner)
+        m_scrollCorner->destroy();
+    if (m_resizer)
+        m_resizer->destroy();
+}
+
+void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
+{
+    if (doFullRepaint) {
+        m_object->repaint();
+        checkForRepaint = doFullRepaint = false;
+    }
+    
+    updateLayerPosition(); // For relpositioned layers or non-positioned layers,
+                           // we need to keep in sync, since we may have shifted relative
+                           // to our parent layer.
+
+    int x = 0;
+    int y = 0;
+    convertToLayerCoords(root(), x, y);
+    positionOverflowControls(x, y);
+
+    updateVisibilityStatus();
+
+    updateTransform();
+     
+    if (m_hasVisibleContent) {
+        RenderView* view = m_object->view();
+        ASSERT(view);
+        // FIXME: Optimize using LayoutState and remove the disableLayoutState() call
+        // from updateScrollInfoAfterLayout().
+        ASSERT(!view->layoutState());
+
+        IntRect newRect = m_object->absoluteClippedOverflowRect();
+        IntRect newOutlineBox = m_object->absoluteOutlineBox();
+        if (checkForRepaint) {
+            if (view && !view->printing()) {
+                if (m_needsFullRepaint) {
+                    view->repaintViewRectangle(m_repaintRect);
+                    if (newRect != m_repaintRect)
+                        view->repaintViewRectangle(newRect);
+                } else
+                    m_object->repaintAfterLayoutIfNeeded(m_repaintRect, m_outlineBox);
+            }
+        }
+        m_repaintRect = newRect;
+        m_outlineBox = newOutlineBox;
+    } else {
+        m_repaintRect = IntRect();
+        m_outlineBox = IntRect();
+    }
+
+    m_needsFullRepaint = false;
+
+    // Go ahead and update the reflection's position and size.
+    if (m_reflection)
+        m_reflection->layout();
+
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        child->updateLayerPositions(doFullRepaint, checkForRepaint);
+        
+    // With all our children positioned, now update our marquee if we need to.
+    if (m_marquee)
+        m_marquee->updateMarqueePosition();
+}
+
+void RenderLayer::updateTransform()
+{
+    bool hasTransform = renderer()->hasTransform();
+    bool hadTransform = m_transform;
+    if (hasTransform != hadTransform) {
+        if (hasTransform)
+            m_transform.set(new AffineTransform);
+        else
+            m_transform.clear();
+    }
+    
+    if (hasTransform) {
+        m_transform->reset();
+        renderer()->style()->applyTransform(*m_transform, renderer()->borderBox().size());
+    }
+}
+
+void RenderLayer::setHasVisibleContent(bool b)
+{ 
+    if (m_hasVisibleContent == b && !m_visibleContentStatusDirty)
+        return;
+    m_visibleContentStatusDirty = false; 
+    m_hasVisibleContent = b;
+    if (m_hasVisibleContent) {
+        m_repaintRect = renderer()->absoluteClippedOverflowRect();
+        m_outlineBox = renderer()->absoluteOutlineBox();
+        if (!isOverflowOnly())
+            dirtyStackingContextZOrderLists();
+    }
+    if (parent())
+        parent()->childVisibilityChanged(m_hasVisibleContent);
+}
+
+void RenderLayer::dirtyVisibleContentStatus() 
+{ 
+    m_visibleContentStatusDirty = true; 
+    if (parent())
+        parent()->dirtyVisibleDescendantStatus();
+}
+
+void RenderLayer::childVisibilityChanged(bool newVisibility) 
+{ 
+    if (m_hasVisibleDescendant == newVisibility || m_visibleDescendantStatusDirty)
+        return;
+    if (newVisibility) {
+        RenderLayer* l = this;
+        while (l && !l->m_visibleDescendantStatusDirty && !l->m_hasVisibleDescendant) {
+            l->m_hasVisibleDescendant = true;
+            l = l->parent();
+        }
+    } else 
+        dirtyVisibleDescendantStatus();
+}
+
+void RenderLayer::dirtyVisibleDescendantStatus()
+{
+    RenderLayer* l = this;
+    while (l && !l->m_visibleDescendantStatusDirty) {
+        l->m_visibleDescendantStatusDirty = true;
+        l = l->parent();
+    }
+}
+
+void RenderLayer::updateVisibilityStatus()
+{
+    if (m_visibleDescendantStatusDirty) {
+        m_hasVisibleDescendant = false;
+        for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+            child->updateVisibilityStatus();        
+            if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) {
+                m_hasVisibleDescendant = true;
+                break;
+            }
+        }
+        m_visibleDescendantStatusDirty = false;
+    }
+
+    if (m_visibleContentStatusDirty) {
+        if (m_object->style()->visibility() == VISIBLE)
+            m_hasVisibleContent = true;
+        else {
+            // layer may be hidden but still have some visible content, check for this
+            m_hasVisibleContent = false;
+            RenderObject* r = m_object->firstChild();
+            while (r) {
+                if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
+                    m_hasVisibleContent = true;
+                    break;
+                }
+                if (r->firstChild() && !r->hasLayer())
+                    r = r->firstChild();
+                else if (r->nextSibling())
+                    r = r->nextSibling();
+                else {
+                    do {
+                        r = r->parent();
+                        if (r==m_object)
+                            r = 0;
+                    } while (r && !r->nextSibling());
+                    if (r)
+                        r = r->nextSibling();
+                }
+            }
+        }    
+        m_visibleContentStatusDirty = false; 
+    }
+}
+
+void RenderLayer::updateLayerPosition()
+{
+    // Clear our cached clip rect information.
+    clearClipRect();
+
+    int x = m_object->xPos();
+    int y = m_object->yPos() - m_object->borderTopExtra();
+
+    if (!m_object->isPositioned() && m_object->parent()) {
+        // We must adjust our position by walking up the render tree looking for the
+        // nearest enclosing object with a layer.
+        RenderObject* curr = m_object->parent();
+        while (curr && !curr->hasLayer()) {
+            if (!curr->isTableRow()) {
+                // Rows and cells share the same coordinate space (that of the section).
+                // Omit them when computing our xpos/ypos.
+                x += curr->xPos();
+                y += curr->yPos();
+            }
+            curr = curr->parent();
+        }
+        y += curr->borderTopExtra();
+        if (curr->isTableRow()) {
+            // Put ourselves into the row coordinate space.
+            x -= curr->xPos();
+            y -= curr->yPos();
+        }
+    }
+
+    m_relX = m_relY = 0;
+    if (m_object->isRelPositioned()) {
+        m_relX = static_cast<RenderBox*>(m_object)->relativePositionOffsetX();
+        m_relY = static_cast<RenderBox*>(m_object)->relativePositionOffsetY();
+        x += m_relX; y += m_relY;
+    }
+    
+    // Subtract our parent's scroll offset.
+    if (m_object->isPositioned() && enclosingPositionedAncestor()) {
+        RenderLayer* positionedParent = enclosingPositionedAncestor();
+
+        // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
+        positionedParent->subtractScrollOffset(x, y);
+        
+        if (m_object->isPositioned()) {
+            IntSize offset = static_cast<RenderBox*>(m_object)->offsetForPositionedInContainer(positionedParent->renderer());
+            x += offset.width();
+            y += offset.height();
+        }
+    } else if (parent())
+        parent()->subtractScrollOffset(x, y);
+    
+    setPos(x,y);
+
+    setWidth(m_object->width());
+    setHeight(m_object->height() + m_object->borderTopExtra() + m_object->borderBottomExtra());
+
+    if (!m_object->hasOverflowClip()) {
+        if (m_object->overflowWidth() > m_object->width())
+            setWidth(m_object->overflowWidth());
+        if (m_object->overflowHeight() > m_object->height())
+            setHeight(m_object->overflowHeight());
+    }
+}
+
+RenderLayer *RenderLayer::stackingContext() const
+{
+    RenderLayer* curr = parent();
+    for ( ; curr && !curr->m_object->isRenderView() && !curr->m_object->isRoot() &&
+          curr->m_object->style()->hasAutoZIndex();
+          curr = curr->parent()) { }
+    return curr;
+}
+
+RenderLayer* RenderLayer::enclosingPositionedAncestor() const
+{
+    RenderLayer* curr = parent();
+    for ( ; curr && !curr->m_object->isRenderView() && !curr->m_object->isPositioned() && !curr->m_object->isRelPositioned() && !curr->hasTransform();
+         curr = curr->parent()) { }
+    return curr;
+}
+
+RenderLayer* RenderLayer::enclosingTransformedAncestor() const
+{
+    RenderLayer* curr = parent();
+    for ( ; curr && !curr->m_object->isRenderView() && !curr->transform(); curr = curr->parent())
+        { }
+    return curr;
+}
+
+bool RenderLayer::requiresSlowRepaints() const
+{
+    if (isTransparent() || hasReflection() || hasTransform())
+        return true;
+    if (!parent())
+        return false;
+    return parent()->requiresSlowRepaints();
+}
+
+bool RenderLayer::isTransparent() const
+{
+#if ENABLE(SVG)
+    if (m_object->node()->namespaceURI() == SVGNames::svgNamespaceURI)
+        return false;
+#endif
+    return m_object->isTransparent() || m_object->hasMask();
+}
+
+RenderLayer*
+RenderLayer::transparentAncestor()
+{
+    RenderLayer* curr = parent();
+    for ( ; curr && !curr->isTransparent(); curr = curr->parent()) { }
+    return curr;
+}
+
+static IntRect transparencyClipBox(const AffineTransform& enclosingTransform, const RenderLayer* l, const RenderLayer* rootLayer)
+{
+    // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
+    // paintDirtyRect, and that should cut down on the amount we have to paint.  Still it
+    // would be better to respect clips.
+    
+    AffineTransform* t = l->transform();
+    if (t && rootLayer != l) {
+        // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
+        // the transformed layer and all of its children.
+        int x = 0;
+        int y = 0;
+        l->convertToLayerCoords(rootLayer, x, y);
+        AffineTransform transform;
+        transform.translate(x, y);
+        transform = *t * transform;
+        transform = transform * enclosingTransform;
+
+        // We now have a transform that will produce a rectangle in our view's space.
+        IntRect clipRect = transform.mapRect(l->boundingBox(l));
+        
+        // Now shift the root layer to be us and pass down the new enclosing transform.
+        for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) {
+            if (!l->reflection() || l->reflectionLayer() != curr)
+                clipRect.unite(transparencyClipBox(transform, curr, l));
+        }
+            
+        return clipRect;
+    }
+    
+    // Note: we don't have to walk z-order lists since transparent elements always establish
+    // a stacking context.  This means we can just walk the layer tree directly.
+    IntRect clipRect = l->boundingBox(rootLayer);
+    
+    // If we have a mask, then the clip is limited to the border box area (and there is
+    // no need to examine child layers).
+    if (!l->renderer()->hasMask()) {
+        for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) {
+            if (!l->reflection() || l->reflectionLayer() != curr)
+                clipRect.unite(transparencyClipBox(enclosingTransform, curr, rootLayer));
+        }
+    }
+
+    // Now map the clipRect via the enclosing transform
+    return enclosingTransform.mapRect(clipRect);
+}
+
+void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer)
+{
+    if (p->paintingDisabled() || (isTransparent() && m_usedTransparency))
+        return;
+    
+    RenderLayer* ancestor = transparentAncestor();
+    if (ancestor)
+        ancestor->beginTransparencyLayers(p, rootLayer);
+    
+    if (isTransparent()) {
+        m_usedTransparency = true;
+        p->save();
+        p->clip(transparencyClipBox(AffineTransform(), this, rootLayer));
+        p->beginTransparencyLayer(renderer()->opacity());
+    }
+}
+
+void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void RenderLayer::operator delete(void* ptr, size_t sz)
+{
+    // Stash size where destroy can find it.
+    *(size_t *)ptr = sz;
+}
+
+void RenderLayer::destroy(RenderArena* renderArena)
+{    
+    delete this;
+
+    // Recover the size left there for us by operator delete and free the memory.
+    renderArena->free(*(size_t *)this, this);
+}
+
+void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
+{
+    RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
+    if (prevSibling) {
+        child->setPreviousSibling(prevSibling);
+        prevSibling->setNextSibling(child);
+    } else
+        setFirstChild(child);
+
+    if (beforeChild) {
+        beforeChild->setPreviousSibling(child);
+        child->setNextSibling(beforeChild);
+    } else
+        setLastChild(child);
+
+    child->setParent(this);
+
+    if (child->isOverflowOnly())
+        dirtyOverflowList();
+
+    if (!child->isOverflowOnly() || child->firstChild()) {
+        // Dirty the z-order list in which we are contained.  The stackingContext() can be null in the
+        // case where we're building up generated content layers.  This is ok, since the lists will start
+        // off dirty in that case anyway.
+        child->dirtyStackingContextZOrderLists();
+    }
+
+    child->updateVisibilityStatus();
+    if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
+        childVisibilityChanged(true);
+}
+
+RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
+{
+    // remove the child
+    if (oldChild->previousSibling())
+        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
+    if (oldChild->nextSibling())
+        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
+
+    if (m_first == oldChild)
+        m_first = oldChild->nextSibling();
+    if (m_last == oldChild)
+        m_last = oldChild->previousSibling();
+
+    if (oldChild->isOverflowOnly())
+        dirtyOverflowList();
+    if (!oldChild->isOverflowOnly() || oldChild->firstChild()) { 
+        // Dirty the z-order list in which we are contained.  When called via the
+        // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
+        // from the main layer tree, so we need to null-check the |stackingContext| value.
+        oldChild->dirtyStackingContextZOrderLists();
+    }
+
+    oldChild->setPreviousSibling(0);
+    oldChild->setNextSibling(0);
+    oldChild->setParent(0);
+    
+    oldChild->updateVisibilityStatus();
+    if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
+        childVisibilityChanged(false);
+    
+    return oldChild;
+}
+
+void RenderLayer::removeOnlyThisLayer()
+{
+    if (!m_parent)
+        return;
+    
+    // Dirty the clip rects.
+    clearClipRects();
+
+    // Remove us from the parent.
+    RenderLayer* parent = m_parent;
+    RenderLayer* nextSib = nextSibling();
+    parent->removeChild(this);
+    
+    if (reflection())
+        removeChild(reflectionLayer());
+
+    // Now walk our kids and reattach them to our parent.
+    RenderLayer* current = m_first;
+    while (current) {
+        RenderLayer* next = current->nextSibling();
+        removeChild(current);
+        parent->addChild(current, nextSib);
+        current->updateLayerPositions();
+        current = next;
+    }
+    
+    destroy(renderer()->renderArena());
+}
+
+void RenderLayer::insertOnlyThisLayer()
+{
+    if (!m_parent && renderer()->parent()) {
+        // We need to connect ourselves when our renderer() has a parent.
+        // Find our enclosingLayer and add ourselves.
+        RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
+        RenderLayer* beforeChild = parentLayer->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0;
+        if (parentLayer)
+            parentLayer->addChild(this, beforeChild);
+    }
+    
+    // Remove all descendant layers from the hierarchy and add them to the new position.
+    for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
+        curr->moveLayers(m_parent, this);
+        
+    // Clear out all the clip rects.
+    clearClipRects();
+}
+
+void 
+RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const
+{
+    if (ancestorLayer == this)
+        return;
+        
+    if (m_object->style()->position() == FixedPosition) {
+        // Add in the offset of the view.  We can obtain this by calling
+        // absolutePosition() on the RenderView.
+        int xOff, yOff;
+        m_object->absolutePosition(xOff, yOff, true);
+        x += xOff;
+        y += yOff;
+        return;
+    }
+ 
+    RenderLayer* parentLayer;
+    if (m_object->style()->position() == AbsolutePosition)
+        parentLayer = enclosingPositionedAncestor();
+    else
+        parentLayer = parent();
+    
+    if (!parentLayer) return;
+    
+    parentLayer->convertToLayerCoords(ancestorLayer, x, y);
+
+    x += xPos();
+    y += yPos();
+}
+
+void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint) 
+{
+    // We want to reduce the speed if we're close from the original point to improve the handleability of the scroll
+    const int shortDistanceLimit = 100;  // We delimit a 200 pixels long square enclosing the original point
+    const int speedReducer = 2;          // Within this square we divide the scrolling speed by 2
+    
+    const int iconRadius = 10;
+    Frame* frame = renderer()->document()->frame();
+    if (!frame)
+        return;
+    
+    IntPoint currentMousePosition = frame->eventHandler()->currentMousePosition();
+    
+    // We need to check if the current mouse position is out of the window. When the mouse is out of the window, the position is incoherent
+    static IntPoint previousMousePosition;
+    if (currentMousePosition.x() < 0 || currentMousePosition.y() < 0)
+        currentMousePosition = previousMousePosition;
+    else
+        previousMousePosition = currentMousePosition;
+
+    int xDelta = currentMousePosition.x() - sourcePoint.x();
+    int yDelta = currentMousePosition.y() - sourcePoint.y();
+
+    if (abs(xDelta) < iconRadius) // at the center we let the space for the icon
+        xDelta = 0;
+    if (abs(yDelta) < iconRadius)
+        yDelta = 0;
+
+    // Let's attenuate the speed for the short distances
+    if (abs(xDelta) < shortDistanceLimit)
+        xDelta /= speedReducer;
+    if (abs(yDelta) < shortDistanceLimit)
+        yDelta /= speedReducer;
+
+    scrollByRecursively(xDelta, yDelta);
+}
+
+void RenderLayer::scrollByRecursively(int xDelta, int yDelta)
+{
+    bool restrictedByLineClamp = false;
+    if (m_object->parent())
+        restrictedByLineClamp = m_object->parent()->style()->lineClamp() >= 0;
+
+    if (m_object->hasOverflowClip() && !restrictedByLineClamp) {
+        int newOffsetX = scrollXOffset() + xDelta;
+        int newOffsetY = scrollYOffset() + yDelta;
+        scrollToOffset(newOffsetX, newOffsetY);
+
+        // If this layer can't do the scroll we ask its parent
+        int leftToScrollX = newOffsetX - scrollXOffset();
+        int leftToScrollY = newOffsetY - scrollYOffset();
+        if ((leftToScrollX || leftToScrollY) && m_object->parent()) {
+            m_object->parent()->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY);
+            Frame* frame = renderer()->document()->frame();
+            if (frame)
+                frame->eventHandler()->updateAutoscrollRenderer();
+        }
+    } else if (m_object->view()->frameView())
+        m_object->view()->frameView()->scrollBy(IntSize(xDelta, yDelta));
+}
+
+
+void
+RenderLayer::scrollOffset(int& x, int& y)
+{
+    x += scrollXOffset() + m_scrollLeftOverflow;
+    y += scrollYOffset();
+}
+
+void
+RenderLayer::subtractScrollOffset(int& x, int& y)
+{
+    x -= scrollXOffset() + m_scrollLeftOverflow;
+    y -= scrollYOffset();
+}
+
+void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint)
+{
+    if (renderer()->style()->overflowX() != OMARQUEE) {
+        if (x < 0) x = 0;
+        if (y < 0) y = 0;
+    
+        // Call the scrollWidth/Height functions so that the dimensions will be computed if they need
+        // to be (for overflow:hidden blocks).
+        int maxX = scrollWidth() - m_object->clientWidth();
+        int maxY = scrollHeight() - m_object->clientHeight();
+        
+        if (x > maxX) x = maxX;
+        if (y > maxY) y = maxY;
+    }
+    
+    // FIXME: Eventually, we will want to perform a blit.  For now never
+    // blit, since the check for blitting is going to be very
+    // complicated (since it will involve testing whether our layer
+    // is either occluded by another layer or clipped by an enclosing
+    // layer or contains fixed backgrounds, etc.).
+    m_scrollX = x - m_scrollOriginX;
+    m_scrollY = y;
+
+    // Update the positions of our child layers.
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        child->updateLayerPositions(false, false);
+    
+    RenderView* view = renderer()->view();
+    
+    // We should have a RenderView if we're trying to scroll.
+    ASSERT(view);
+    if (view) {
+#if ENABLE(DASHBOARD_SUPPORT)
+        // Update dashboard regions, scrolling may change the clip of a
+        // particular region.
+        view->frameView()->updateDashboardRegions();
+#endif
+
+        view->updateWidgetPositions();
+    }
+
+    // Just schedule a full repaint of our object.
+    if (repaint)
+        m_object->repaint();
+    
+    if (updateScrollbars) {
+        if (m_hBar)
+            m_hBar->setValue(scrollXOffset());
+        if (m_vBar)
+            m_vBar->setValue(m_scrollY);
+    }
+
+    // Schedule the scroll DOM event.
+    if (view) {
+        if (FrameView* frameView = view->frameView())
+            frameView->scheduleEvent(Event::create(eventNames().scrollEvent, false, false), EventTargetNodeCast(renderer()->element()));
+    }
+}
+
+void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
+{
+    RenderLayer* parentLayer = 0;
+    IntRect newRect = rect;
+    int xOffset = 0, yOffset = 0;
+
+    // We may end up propagating a scroll event. It is important that we suspend events until 
+    // the end of the function since they could delete the layer or the layer's m_object.
+    FrameView* frameView = m_object->document()->view();
+    if (frameView)
+        frameView->pauseScheduledEvents();
+
+    bool restrictedByLineClamp = false;
+    if (m_object->parent()) {
+        parentLayer = m_object->parent()->enclosingLayer();
+        restrictedByLineClamp = m_object->parent()->style()->lineClamp() >= 0;
+    }
+
+    if (m_object->hasOverflowClip() && !restrictedByLineClamp) {
+        // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property.
+        // This will prevent us from revealing text hidden by the slider in Safari RSS.
+        int x, y;
+        m_object->absolutePosition(x, y);
+        x += m_object->borderLeft();
+        y += m_object->borderTop();
+
+        IntRect layerBounds = IntRect(x + scrollXOffset(), y + scrollYOffset(), m_object->clientWidth(), m_object->clientHeight());
+        IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());
+        IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);
+        
+        xOffset = r.x() - x;
+        yOffset = r.y() - y;
+        // Adjust offsets if they're outside of the allowable range.
+        xOffset = max(0, min(scrollWidth() - layerBounds.width(), xOffset));
+        yOffset = max(0, min(scrollHeight() - layerBounds.height(), yOffset));
+        
+        if (xOffset != scrollXOffset() || yOffset != scrollYOffset()) {
+            int diffX = scrollXOffset();
+            int diffY = scrollYOffset();
+            scrollToOffset(xOffset, yOffset);
+            diffX = scrollXOffset() - diffX;
+            diffY = scrollYOffset() - diffY;
+            newRect.setX(rect.x() - diffX);
+            newRect.setY(rect.y() - diffY);
+        }
+    } else if (!parentLayer && renderer()->canBeProgramaticallyScrolled(scrollToAnchor)) {
+        if (frameView) {
+            if (m_object->document() && m_object->document()->ownerElement() && m_object->document()->ownerElement()->renderer()) {
+                IntRect viewRect = frameView->visibleContentRect();
+                IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
+                
+                xOffset = r.x();
+                yOffset = r.y();
+                // Adjust offsets if they're outside of the allowable range.
+                xOffset = max(0, min(frameView->contentsWidth(), xOffset));
+                yOffset = max(0, min(frameView->contentsHeight(), yOffset));
+
+                frameView->setScrollPosition(IntPoint(xOffset, yOffset));
+                parentLayer = m_object->document()->ownerElement()->renderer()->enclosingLayer();
+                newRect.setX(rect.x() - frameView->scrollX() + frameView->x());
+                newRect.setY(rect.y() - frameView->scrollY() + frameView->y());
+            } else {
+                IntRect viewRect = frameView->visibleContentRect(true);
+                IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
+                
+                // If this is the outermost view that RenderLayer needs to scroll, then we should scroll the view recursively
+                // Other apps, like Mail, rely on this feature.
+                frameView->scrollRectIntoViewRecursively(r);
+            }
+        }
+    }
+    
+    if (parentLayer)
+        parentLayer->scrollRectToVisible(newRect, scrollToAnchor, alignX, alignY);
+
+    if (frameView)
+        frameView->resumeScheduledEvents();
+}
+
+IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
+{
+    // Determine the appropriate X behavior.
+    ScrollBehavior scrollX;
+    IntRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height());
+    int intersectWidth = intersection(visibleRect, exposeRectX).width();
+    if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL)
+        // If the rectangle is fully visible, use the specified visible behavior.
+        // If the rectangle is partially visible, but over a certain threshold,
+        // then treat it as fully visible to avoid unnecessary horizontal scrolling
+        scrollX = getVisibleBehavior(alignX);
+    else if (intersectWidth == visibleRect.width()) {
+        // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
+        scrollX = getVisibleBehavior(alignX);
+        if (scrollX == alignCenter)
+            scrollX = noScroll;
+    } else if (intersectWidth > 0)
+        // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior
+        scrollX = getPartialBehavior(alignX);
+    else
+        scrollX = getHiddenBehavior(alignX);
+    // If we're trying to align to the closest edge, and the exposeRect is further right
+    // than the visibleRect, and not bigger than the visible area, then align with the right.
+    if (scrollX == alignToClosestEdge && exposeRect.right() > visibleRect.right() && exposeRect.width() < visibleRect.width())
+        scrollX = alignRight;
+
+    // Given the X behavior, compute the X coordinate.
+    int x;
+    if (scrollX == noScroll) 
+        x = visibleRect.x();
+    else if (scrollX == alignRight)
+        x = exposeRect.right() - visibleRect.width();
+    else if (scrollX == alignCenter)
+        x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2;
+    else
+        x = exposeRect.x();
+
+    // Determine the appropriate Y behavior.
+    ScrollBehavior scrollY;
+    IntRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height());
+    int intersectHeight = intersection(visibleRect, exposeRectY).height();
+    if (intersectHeight == exposeRect.height())
+        // If the rectangle is fully visible, use the specified visible behavior.
+        scrollY = getVisibleBehavior(alignY);
+    else if (intersectHeight == visibleRect.height()) {
+        // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
+        scrollY = getVisibleBehavior(alignY);
+        if (scrollY == alignCenter)
+            scrollY = noScroll;
+    } else if (intersectHeight > 0)
+        // If the rectangle is partially visible, use the specified partial behavior
+        scrollY = getPartialBehavior(alignY);
+    else
+        scrollY = getHiddenBehavior(alignY);
+    // If we're trying to align to the closest edge, and the exposeRect is further down
+    // than the visibleRect, and not bigger than the visible area, then align with the bottom.
+    if (scrollY == alignToClosestEdge && exposeRect.bottom() > visibleRect.bottom() && exposeRect.height() < visibleRect.height())
+        scrollY = alignBottom;
+
+    // Given the Y behavior, compute the Y coordinate.
+    int y;
+    if (scrollY == noScroll) 
+        y = visibleRect.y();
+    else if (scrollY == alignBottom)
+        y = exposeRect.bottom() - visibleRect.height();
+    else if (scrollY == alignCenter)
+        y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2;
+    else
+        y = exposeRect.y();
+
+    return IntRect(IntPoint(x, y), visibleRect.size());
+}
+
+void RenderLayer::autoscroll()
+{
+    Frame* frame = renderer()->document()->frame();
+    if (!frame)
+        return;
+
+    FrameView* frameView = frame->view();
+    if (!frameView)
+        return;
+
+    frame->eventHandler()->updateSelectionForMouseDrag();
+
+    IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition());
+    scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, gAlignToEdgeIfNeeded, gAlignToEdgeIfNeeded);    
+}
+
+void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset)
+{
+    if (!inResizeMode() || !m_object->hasOverflowClip())
+        return;
+
+    // Set the width and height of the shadow ancestor node if there is one.
+    // This is necessary for textarea elements since the resizable layer is in the shadow content.
+    Element* element = static_cast<Element*>(m_object->node()->shadowAncestorNode());
+    RenderBox* renderer = static_cast<RenderBox*>(element->renderer());
+
+    EResize resize = renderer->style()->resize();
+    if (resize == RESIZE_NONE)
+        return;
+
+    Document* document = element->document();
+    if (!document->frame()->eventHandler()->mousePressed())
+        return;
+
+    float zoomFactor = renderer->style()->effectiveZoom();
+
+    IntSize newOffset = offsetFromResizeCorner(document->view()->windowToContents(evt.pos()));
+    newOffset.setWidth(newOffset.width() / zoomFactor);
+    newOffset.setHeight(newOffset.height() / zoomFactor);
+    
+    IntSize currentSize = IntSize(renderer->width() / zoomFactor, renderer->height() / zoomFactor);
+    IntSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize);
+    element->setMinimumSizeForResizing(minimumSize);
+    
+    IntSize adjustedOldOffset = IntSize(oldOffset.width() / zoomFactor, oldOffset.height() / zoomFactor);
+    
+    IntSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize;
+
+    CSSStyleDeclaration* style = element->style();
+    bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX;
+
+    ExceptionCode ec;
+
+    if (difference.width()) {
+        if (element && element->isControl()) {
+            // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
+            style->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false, ec);
+            style->setProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false, ec);
+        }
+        int baseWidth = renderer->width() - (isBoxSizingBorder ? 0
+            : renderer->borderLeft() + renderer->paddingLeft() + renderer->borderRight() + renderer->paddingRight());
+        baseWidth = baseWidth / zoomFactor;
+        style->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false, ec);
+    }
+
+    if (difference.height()) {
+        if (element && element->isControl()) {
+            // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
+            style->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false, ec);
+            style->setProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false, ec);
+        }
+        int baseHeight = renderer->height() - (isBoxSizingBorder ? 0
+            : renderer->borderTop() + renderer->paddingTop() + renderer->borderBottom() + renderer->paddingBottom());
+        baseHeight = baseHeight / zoomFactor;
+        style->setProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false, ec);
+    }
+
+    document->updateLayout();
+
+    // FIXME (Radar 4118564): We should also autoscroll the window as necessary to keep the point under the cursor in view.
+}
+
+void RenderLayer::valueChanged(Scrollbar*)
+{
+    // Update scroll position from scrollbars.
+
+    bool needUpdate = false;
+    int newX = scrollXOffset();
+    int newY = m_scrollY;
+    
+    if (m_hBar) {
+        newX = m_hBar->value();
+        if (newX != scrollXOffset())
+           needUpdate = true;
+    }
+
+    if (m_vBar) {
+        newY = m_vBar->value();
+        if (newY != m_scrollY)
+           needUpdate = true;
+    }
+
+    if (needUpdate)
+        scrollToOffset(newX, newY, false);
+}
+
+bool RenderLayer::isActive() const
+{
+    Page* page = renderer()->document()->frame()->page();
+    return page && page->focusController()->isActive();
+}
+
+
+static IntRect cornerRect(const RenderLayer* layer, const IntRect& bounds)
+{
+    int horizontalThickness;
+    int verticalThickness;
+    if (!layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
+        // FIXME: This isn't right.  We need to know the thickness of custom scrollbars
+        // even when they don't exist in order to set the resizer square size properly.
+        horizontalThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();
+        verticalThickness = horizontalThickness;
+    } else if (layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
+        horizontalThickness = layer->verticalScrollbar()->width();
+        verticalThickness = horizontalThickness;
+    } else if (layer->horizontalScrollbar() && !layer->verticalScrollbar()) {
+        verticalThickness = layer->horizontalScrollbar()->height();
+        horizontalThickness = verticalThickness;
+    } else {
+        horizontalThickness = layer->verticalScrollbar()->width();
+        verticalThickness = layer->horizontalScrollbar()->height();
+    }
+    return IntRect(bounds.right() - horizontalThickness - layer->renderer()->style()->borderRightWidth(), 
+                   bounds.bottom() - verticalThickness - layer->renderer()->style()->borderBottomWidth(),
+                   horizontalThickness, verticalThickness);
+}
+
+static IntRect scrollCornerRect(const RenderLayer* layer, const IntRect& bounds)
+{
+    // We have a scrollbar corner when a scrollbar is visible and not filling the entire length of the box.
+    // This happens when:
+    // (a) A resizer is present and at least one scrollbar is present
+    // (b) Both scrollbars are present.
+    bool hasHorizontalBar = layer->horizontalScrollbar();
+    bool hasVerticalBar = layer->verticalScrollbar();
+    bool hasResizer = layer->renderer()->style()->resize() != RESIZE_NONE;
+    if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar)))
+        return cornerRect(layer, bounds);
+    return IntRect();
+}
+
+static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds)
+{
+    if (layer->renderer()->style()->resize() == RESIZE_NONE)
+        return IntRect();
+    return cornerRect(layer, bounds);
+}
+
+bool RenderLayer::scrollbarCornerPresent() const
+{
+    return !scrollCornerRect(this, m_object->borderBox()).isEmpty();
+}
+
+void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
+{
+    IntRect scrollRect = rect;
+    if (scrollbar == m_vBar.get())
+        scrollRect.move(renderer()->width() - renderer()->borderRight() - scrollbar->width(), renderer()->borderTop());
+    else
+        scrollRect.move(renderer()->borderLeft(), renderer()->height() - renderer()->borderBottom() - scrollbar->height());
+    renderer()->repaintRectangle(scrollRect);
+}
+
+PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation)
+{
+    RefPtr<Scrollbar> widget;
+    bool hasCustomScrollbarStyle = m_object->node()->shadowAncestorNode()->renderer()->style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
+    if (hasCustomScrollbarStyle)
+        widget = RenderScrollbar::createCustomScrollbar(this, orientation, m_object->node()->shadowAncestorNode()->renderer());
+    else
+        widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
+    m_object->document()->view()->addChild(widget.get());        
+    return widget.release();
+}
+
+void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation)
+{
+    RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
+    if (scrollbar) {
+        scrollbar->removeFromParent();
+        scrollbar->setClient(0);
+        scrollbar = 0;
+    }
+}
+
+void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
+{
+    if (hasScrollbar == (m_hBar != 0))
+        return;
+
+    if (hasScrollbar)
+        m_hBar = createScrollbar(HorizontalScrollbar);
+    else
+        destroyScrollbar(HorizontalScrollbar);
+
+    // Destroying or creating one bar can cause our scrollbar corner to come and go.  We need to update the opposite scrollbar's style.
+    if (m_hBar)
+        m_hBar->styleChanged();
+    if (m_vBar)
+        m_vBar->styleChanged();
+
+#if ENABLE(DASHBOARD_SUPPORT)
+    // Force an update since we know the scrollbars have changed things.
+    if (m_object->document()->hasDashboardRegions())
+        m_object->document()->setDashboardRegionsDirty(true);
+#endif
+}
+
+void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
+{
+    if (hasScrollbar == (m_vBar != 0))
+        return;
+
+    if (hasScrollbar)
+        m_vBar = createScrollbar(VerticalScrollbar);
+    else
+        destroyScrollbar(VerticalScrollbar);
+
+     // Destroying or creating one bar can cause our scrollbar corner to come and go.  We need to update the opposite scrollbar's style.
+    if (m_hBar)
+        m_hBar->styleChanged();
+    if (m_vBar)
+        m_vBar->styleChanged();
+
+#if ENABLE(DASHBOARD_SUPPORT)
+    // Force an update since we know the scrollbars have changed things.
+    if (m_object->document()->hasDashboardRegions())
+        m_object->document()->setDashboardRegionsDirty(true);
+#endif
+}
+
+int RenderLayer::verticalScrollbarWidth() const
+{
+    if (!m_vBar)
+        return 0;
+    return m_vBar->width();
+}
+
+int RenderLayer::horizontalScrollbarHeight() const
+{
+    if (!m_hBar)
+        return 0;
+    return m_hBar->height();
+}
+
+IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& p) const
+{
+    // Currently the resize corner is always the bottom right corner
+    int x = width();
+    int y = height();
+    convertToLayerCoords(root(), x, y);
+    return p - IntPoint(x, y);
+}
+
+void RenderLayer::positionOverflowControls(int tx, int ty)
+{
+    if (!m_hBar && !m_vBar && (!m_object->hasOverflowClip() || m_object->style()->resize() == RESIZE_NONE))
+        return;
+    
+    IntRect borderBox = m_object->borderBox();
+    IntRect scrollCorner(scrollCornerRect(this, borderBox));
+    IntRect absBounds(borderBox.x() + tx, borderBox.y() + ty, borderBox.width(), borderBox.height());
+    if (m_vBar)
+        m_vBar->setFrameRect(IntRect(absBounds.right() - m_object->borderRight() - m_vBar->width(),
+                                     absBounds.y() + m_object->borderTop(),
+                                     m_vBar->width(),
+                                     absBounds.height() - (m_object->borderTop() + m_object->borderBottom()) - scrollCorner.height()));
+
+    if (m_hBar)
+        m_hBar->setFrameRect(IntRect(absBounds.x() + m_object->borderLeft(),
+                                     absBounds.bottom() - m_object->borderBottom() - m_hBar->height(),
+                                     absBounds.width() - (m_object->borderLeft() + m_object->borderRight()) - scrollCorner.width(),
+                                     m_hBar->height()));
+    
+    if (m_scrollCorner)
+        m_scrollCorner->setRect(scrollCorner);
+    if (m_resizer)
+        m_resizer->setRect(resizerCornerRect(this, borderBox));
+}
+
+int RenderLayer::scrollWidth()
+{
+    if (m_scrollDimensionsDirty)
+        computeScrollDimensions();
+    return m_scrollWidth;
+}
+
+int RenderLayer::scrollHeight()
+{
+    if (m_scrollDimensionsDirty)
+        computeScrollDimensions();
+    return m_scrollHeight;
+}
+
+void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
+{
+    m_scrollDimensionsDirty = false;
+    
+    bool ltr = m_object->style()->direction() == LTR;
+
+    int clientWidth = m_object->clientWidth();
+    int clientHeight = m_object->clientHeight();
+
+    m_scrollLeftOverflow = ltr ? 0 : min(0, m_object->leftmostPosition(true, false) - m_object->borderLeft());
+
+    int rightPos = ltr ?
+                    m_object->rightmostPosition(true, false) - m_object->borderLeft() :
+                    clientWidth - m_scrollLeftOverflow;
+    int bottomPos = m_object->lowestPosition(true, false) - m_object->borderTop();
+
+    m_scrollWidth = max(rightPos, clientWidth);
+    m_scrollHeight = max(bottomPos, clientHeight);
+    
+    m_scrollOriginX = ltr ? 0 : m_scrollWidth - clientWidth;
+
+    if (needHBar)
+        *needHBar = rightPos > clientWidth;
+    if (needVBar)
+        *needVBar = bottomPos > clientHeight;
+}
+
+void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
+{
+    if (m_overflowStatusDirty) {
+        m_horizontalOverflow = horizontalOverflow;
+        m_verticalOverflow = verticalOverflow;
+        m_overflowStatusDirty = false;
+        
+        return;
+    }
+    
+    bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
+    bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
+    
+    if (horizontalOverflowChanged || verticalOverflowChanged) {
+        m_horizontalOverflow = horizontalOverflow;
+        m_verticalOverflow = verticalOverflow;
+        
+        if (FrameView* frameView = m_object->document()->view()) {
+            frameView->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow),
+                EventTargetNodeCast(m_object->element()));
+        }
+    }
+}
+
+void
+RenderLayer::updateScrollInfoAfterLayout()
+{
+    m_scrollDimensionsDirty = true;
+
+    bool horizontalOverflow, verticalOverflow;
+    computeScrollDimensions(&horizontalOverflow, &verticalOverflow);
+
+    if (m_object->style()->overflowX() != OMARQUEE) {
+        // Layout may cause us to be in an invalid scroll position.  In this case we need
+        // to pull our scroll offsets back to the max (or push them up to the min).
+        int newX = max(0, min(scrollXOffset(), scrollWidth() - m_object->clientWidth()));
+        int newY = max(0, min(m_scrollY, scrollHeight() - m_object->clientHeight()));
+        if (newX != scrollXOffset() || newY != m_scrollY) {
+            RenderView* view = m_object->view();
+            ASSERT(view);
+            // scrollToOffset() may call updateLayerPositions(), which doesn't work
+            // with LayoutState.
+            // FIXME: Remove the disableLayoutState/enableLayoutState if the above changes.
+            if (view)
+                view->disableLayoutState();
+            scrollToOffset(newX, newY);
+            if (view)
+                view->enableLayoutState();
+        }
+    }
+
+    bool haveHorizontalBar = m_hBar;
+    bool haveVerticalBar = m_vBar;
+    
+    // overflow:scroll should just enable/disable.
+    if (m_object->style()->overflowX() == OSCROLL)
+        m_hBar->setEnabled(horizontalOverflow);
+    if (m_object->style()->overflowY() == OSCROLL)
+        m_vBar->setEnabled(verticalOverflow);
+
+    // A dynamic change from a scrolling overflow to overflow:hidden means we need to get rid of any
+    // scrollbars that may be present.
+    if (m_object->style()->overflowX() == OHIDDEN && haveHorizontalBar)
+        setHasHorizontalScrollbar(false);
+    if (m_object->style()->overflowY() == OHIDDEN && haveVerticalBar)
+        setHasVerticalScrollbar(false);
+    
+    // overflow:auto may need to lay out again if scrollbars got added/removed.
+    bool scrollbarsChanged = (m_object->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) || 
+                             (m_object->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);    
+    if (scrollbarsChanged) {
+        if (m_object->hasAutoHorizontalScrollbar())
+            setHasHorizontalScrollbar(horizontalOverflow);
+        if (m_object->hasAutoVerticalScrollbar())
+            setHasVerticalScrollbar(verticalOverflow);
+
+#if ENABLE(DASHBOARD_SUPPORT)
+        // Force an update since we know the scrollbars have changed things.
+        if (m_object->document()->hasDashboardRegions())
+            m_object->document()->setDashboardRegionsDirty(true);
+#endif
+
+        m_object->repaint();
+
+        if (m_object->style()->overflowX() == OAUTO || m_object->style()->overflowY() == OAUTO) {
+            if (!m_inOverflowRelayout) {
+                // Our proprietary overflow: overlay value doesn't trigger a layout.
+                m_inOverflowRelayout = true;
+                m_object->setNeedsLayout(true);
+                if (m_object->isRenderBlock())
+                    static_cast<RenderBlock*>(m_object)->layoutBlock(true);
+                else
+                    m_object->layout();
+                m_inOverflowRelayout = false;
+            }
+        }
+    }
+    
+    // If overflow:scroll is turned into overflow:auto a bar might still be disabled (Bug 11985).
+    if (m_hBar && m_object->hasAutoHorizontalScrollbar())
+        m_hBar->setEnabled(true);
+    if (m_vBar && m_object->hasAutoVerticalScrollbar())
+        m_vBar->setEnabled(true);
+
+    // Set up the range (and page step/line step).
+    if (m_hBar) {
+        int clientWidth = m_object->clientWidth();
+        int pageStep = (clientWidth - cAmountToKeepWhenPaging);
+        if (pageStep < 0) pageStep = clientWidth;
+        m_hBar->setSteps(cScrollbarPixelsPerLineStep, pageStep);
+        m_hBar->setProportion(clientWidth, m_scrollWidth);
+        m_hBar->setValue(scrollXOffset());
+    }
+    if (m_vBar) {
+        int clientHeight = m_object->clientHeight();
+        int pageStep = (clientHeight - cAmountToKeepWhenPaging);
+        if (pageStep < 0) pageStep = clientHeight;
+        m_vBar->setSteps(cScrollbarPixelsPerLineStep, pageStep);
+        m_vBar->setProportion(clientHeight, m_scrollHeight);
+    }
+ 
+    if (m_object->element() && m_object->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
+        updateOverflowStatus(horizontalOverflow, verticalOverflow);
+}
+
+void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
+{
+    // Don't do anything if we have no overflow.
+    if (!m_object->hasOverflowClip())
+        return;
+    
+    // Move the scrollbar widgets if necessary.  We normally move and resize widgets during layout, but sometimes
+    // widgets can move without layout occurring (most notably when you scroll a document that
+    // contains fixed positioned elements).
+    positionOverflowControls(tx, ty);
+
+    // Now that we're sure the scrollbars are in the right place, paint them.
+    if (m_hBar)
+        m_hBar->paint(context, damageRect);
+    if (m_vBar)
+        m_vBar->paint(context, damageRect);
+
+    // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the
+    // edge of the box.
+    paintScrollCorner(context, tx, ty, damageRect);
+    
+    // Paint our resizer last, since it sits on top of the scroll corner.
+    paintResizer(context, tx, ty, damageRect);
+}
+
+void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
+{
+    IntRect cornerRect = scrollCornerRect(this, m_object->borderBox());
+    IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
+    if (!absRect.intersects(damageRect))
+        return;
+
+    if (context->updatingControlTints()) {
+        updateScrollCornerStyle();
+        return;
+    }
+
+    if (m_scrollCorner) {
+        m_scrollCorner->paintIntoRect(context, tx, ty, absRect);
+        return;
+    }
+    
+    context->fillRect(absRect, Color::white);
+}
+
+void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
+{
+    if (m_object->style()->resize() == RESIZE_NONE)
+        return;
+
+    IntRect cornerRect = resizerCornerRect(this, m_object->borderBox());
+    IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
+    if (!absRect.intersects(damageRect))
+        return;
+
+    if (context->updatingControlTints()) {
+        updateResizerStyle();
+        return;
+    }
+    
+    if (m_resizer) {
+        m_resizer->paintIntoRect(context, tx, ty, absRect);
+        return;
+    }
+
+    // Paint the resizer control.
+    static RefPtr<Image> resizeCornerImage;
+    if (!resizeCornerImage)
+        resizeCornerImage = Image::loadPlatformResource("textAreaResizeCorner");
+    IntPoint imagePoint(absRect.right() - resizeCornerImage->width(), absRect.bottom() - resizeCornerImage->height());
+    context->drawImage(resizeCornerImage.get(), imagePoint);
+
+    // Draw a frame around the resizer (1px grey line) if there are any scrollbars present.
+    // Clipping will exclude the right and bottom edges of this frame.
+    if (m_hBar || m_vBar) {
+        context->save();
+        IntRect largerCorner = absRect;
+        largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1));
+        context->setStrokeColor(Color(makeRGB(217, 217, 217)));
+        context->setStrokeThickness(1.0f);
+        context->setFillColor(Color::transparent);
+        context->drawRect(largerCorner);
+        context->restore();
+    }
+}
+
+bool RenderLayer::isPointInResizeControl(const IntPoint& point)
+{
+    if (!m_object->hasOverflowClip() || m_object->style()->resize() == RESIZE_NONE)
+        return false;
+    
+    int x = 0;
+    int y = 0;
+    convertToLayerCoords(root(), x, y);
+    IntRect absBounds(x, y, m_object->width(), m_object->height());
+    return resizerCornerRect(this, absBounds).contains(point);
+}
+    
+bool RenderLayer::hitTestOverflowControls(HitTestResult& result)
+{
+    if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
+        return false;
+
+    int x = 0;
+    int y = 0;
+    convertToLayerCoords(root(), x, y);
+    IntRect absBounds(x, y, renderer()->width(), renderer()->height());
+    
+    IntRect resizeControlRect;
+    if (renderer()->style()->resize() != RESIZE_NONE) {
+        resizeControlRect = resizerCornerRect(this, absBounds);
+        if (resizeControlRect.contains(result.point()))
+            return true;
+    }
+
+    int resizeControlSize = max(resizeControlRect.height(), 0);
+
+    if (m_vBar) {
+        IntRect vBarRect(absBounds.right() - renderer()->borderRight() - m_vBar->width(), absBounds.y() + renderer()->borderTop(), m_vBar->width(), absBounds.height() - (renderer()->borderTop() + renderer()->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
+        if (vBarRect.contains(result.point())) {
+            result.setScrollbar(m_vBar.get());
+            return true;
+        }
+    }
+
+    resizeControlSize = max(resizeControlRect.width(), 0);
+    if (m_hBar) {
+        IntRect hBarRect(absBounds.x() + renderer()->borderLeft(), absBounds.bottom() - renderer()->borderBottom() - m_hBar->height(), absBounds.width() - (renderer()->borderLeft() + renderer()->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize), m_hBar->height());
+        if (hBarRect.contains(result.point())) {
+            result.setScrollbar(m_hBar.get());
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
+{
+    bool didHorizontalScroll = false;
+    bool didVerticalScroll = false;
+    
+    if (m_hBar) {
+        if (granularity == ScrollByDocument) {
+            // Special-case for the ScrollByDocument granularity. A document scroll can only be up 
+            // or down and in both cases the horizontal bar goes all the way to the left.
+            didHorizontalScroll = m_hBar->scroll(ScrollLeft, ScrollByDocument, multiplier);
+        } else
+            didHorizontalScroll = m_hBar->scroll(direction, granularity, multiplier);
+    }
+
+    if (m_vBar)
+        didVerticalScroll = m_vBar->scroll(direction, granularity, multiplier);
+
+    return (didHorizontalScroll || didVerticalScroll);
+}
+
+void
+RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintRestriction paintRestriction, RenderObject *paintingRoot)
+{
+    paintLayer(this, p, damageRect, false, paintRestriction, paintingRoot);
+}
+
+static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
+{
+    if (paintDirtyRect == clipRect)
+        return;
+    p->save();
+    p->clip(clipRect);
+}
+
+static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
+{
+    if (paintDirtyRect == clipRect)
+        return;
+    p->restore();
+}
+
+void
+RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
+                        const IntRect& paintDirtyRect, bool haveTransparency, PaintRestriction paintRestriction,
+                        RenderObject* paintingRoot, bool appliedTransform)
+{
+    // Avoid painting layers when stylesheets haven't loaded.  This eliminates FOUC.
+    // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
+    // will do a full repaint().
+    if (renderer()->document()->didLayoutWithPendingStylesheets() && !renderer()->isRenderView() && !renderer()->isRoot())
+        return;
+    
+    // If this layer is totally invisible then there is nothing to paint.
+    if (!m_object->opacity())
+        return;
+
+    if (isTransparent())
+        haveTransparency = true;
+
+    // Apply a transform if we have one.  A reflection is considered to be a transform, since it is a flip and a translate.
+    if (m_transform && !appliedTransform) {
+        // If the transform can't be inverted, then don't paint anything.
+        if (!m_transform->isInvertible())
+            return;
+
+        // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
+        // layer from the parent now.
+        if (haveTransparency)
+            parent()->beginTransparencyLayers(p, rootLayer);
+  
+        // Make sure the parent's clip rects have been calculated.
+        IntRect clipRect = paintDirtyRect;
+        if (parent()) {
+            parent()->calculateClipRects(rootLayer);
+            clipRect = parent()->clipRects()->overflowClipRect();
+            clipRect.intersect(paintDirtyRect);
+        }
+        
+        // Push the parent coordinate space's clip.
+        setClip(p, paintDirtyRect, clipRect);
+
+        // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
+        // This involves subtracting out the position of the layer in our current coordinate space.
+        int x = 0;
+        int y = 0;
+        convertToLayerCoords(rootLayer, x, y);
+        AffineTransform transform;
+        transform.translate(x, y);
+        transform = *m_transform * transform;
+        
+        // Apply the transform.
+        p->save();
+        p->concatCTM(transform);
+
+        // Now do a paint with the root layer shifted to be us.
+        paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), haveTransparency, paintRestriction, paintingRoot, true);
+        
+        p->restore();
+        
+        // Restore the clip.
+        restoreClip(p, paintDirtyRect, clipRect);
+        
+        return;
+    }
+
+    // Paint the reflection first if we have one.
+    if (m_reflection && !m_paintingInsideReflection && (!m_transform || appliedTransform)) {
+        // Mark that we are now inside replica painting.
+        m_paintingInsideReflection = true;
+        reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
+        m_paintingInsideReflection = false;
+    }
+
+    // Calculate the clip rects we should use.
+    IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
+    calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
+    int x = layerBounds.x();
+    int y = layerBounds.y();
+    int tx = x - renderer()->xPos();
+    int ty = y - renderer()->yPos() + renderer()->borderTopExtra();
+                             
+    // Ensure our lists are up-to-date.
+    updateZOrderLists();
+    updateOverflowList();
+
+    bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText;
+    bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
+    
+    // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
+    // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
+    // Else, our renderer tree may or may not contain the painting root, so we pass that root along
+    // so it will be tested against as we decend through the renderers.
+    RenderObject* paintingRootForRenderer = 0;
+    if (paintingRoot && !m_object->isDescendantOf(paintingRoot))
+        paintingRootForRenderer = paintingRoot;
+
+    // We want to paint our layer, but only if we intersect the damage rect.
+    bool shouldPaint = intersectsDamageRect(layerBounds, damageRect, rootLayer) && m_hasVisibleContent;
+    if (shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
+        // Begin transparency layers lazily now that we know we have to paint something.
+        if (haveTransparency)
+            beginTransparencyLayers(p, rootLayer);
+        
+        // Paint our background first, before painting any child layers.
+        // Establish the clip used to paint our background.
+        setClip(p, paintDirtyRect, damageRect);
+
+        // Paint the background.
+        RenderObject::PaintInfo paintInfo(p, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
+        renderer()->paint(paintInfo, tx, ty);
+
+        // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
+        // z-index.  We paint after we painted the background/border, so that the scrollbars will
+        // sit above the background/border.
+        paintOverflowControls(p, x, y, damageRect);
+        
+        // Restore the clip.
+        restoreClip(p, paintDirtyRect, damageRect);
+    }
+
+    // Now walk the sorted list of children with negative z-indices.
+    if (m_negZOrderList)
+        for (Vector<RenderLayer*>::iterator it = m_negZOrderList->begin(); it != m_negZOrderList->end(); ++it)
+            it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
+    
+    // Now establish the appropriate clip and paint our child RenderObjects.
+    if (shouldPaint && !clipRectToApply.isEmpty()) {
+        // Begin transparency layers lazily now that we know we have to paint something.
+        if (haveTransparency)
+            beginTransparencyLayers(p, rootLayer);
+
+        // Set up the clip used when painting our children.
+        setClip(p, paintDirtyRect, clipRectToApply);
+        RenderObject::PaintInfo paintInfo(p, clipRectToApply, 
+                                          selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
+                                          forceBlackText, paintingRootForRenderer, 0);
+        renderer()->paint(paintInfo, tx, ty);
+        if (!selectionOnly) {
+            paintInfo.phase = PaintPhaseFloat;
+            renderer()->paint(paintInfo, tx, ty);
+            paintInfo.phase = PaintPhaseForeground;
+            renderer()->paint(paintInfo, tx, ty);
+            paintInfo.phase = PaintPhaseChildOutlines;
+            renderer()->paint(paintInfo, tx, ty);
+        }
+
+        // Now restore our clip.
+        restoreClip(p, paintDirtyRect, clipRectToApply);
+    }
+    
+    if (!outlineRect.isEmpty()) {
+        // Paint our own outline
+        RenderObject::PaintInfo paintInfo(p, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
+        setClip(p, paintDirtyRect, outlineRect);
+        renderer()->paint(paintInfo, tx, ty);
+        restoreClip(p, paintDirtyRect, outlineRect);
+    }
+    
+    // Paint any child layers that have overflow.
+    if (m_overflowList)
+        for (Vector<RenderLayer*>::iterator it = m_overflowList->begin(); it != m_overflowList->end(); ++it)
+            it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
+    
+    // Now walk the sorted list of children with positive z-indices.
+    if (m_posZOrderList)
+        for (Vector<RenderLayer*>::iterator it = m_posZOrderList->begin(); it != m_posZOrderList->end(); ++it)
+            it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
+    
+    if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
+        setClip(p, paintDirtyRect, damageRect);
+
+        // Paint the mask.
+        RenderObject::PaintInfo paintInfo(p, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0);
+        renderer()->paint(paintInfo, tx, ty);
+        
+        // Restore the clip.
+        restoreClip(p, paintDirtyRect, damageRect);
+    }
+
+    // End our transparency layer
+    if (isTransparent() && m_usedTransparency) {
+        p->endTransparencyLayer();
+        p->restore();
+        m_usedTransparency = false;
+    }
+}
+
+static inline IntRect frameVisibleRect(RenderObject* renderer)
+{
+    FrameView* frameView = renderer->document()->view();
+    if (!frameView)
+        return IntRect();
+
+    return frameView->visibleContentRect();
+}
+
+bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
+{
+    renderer()->document()->updateLayout();
+    
+    IntRect boundsRect(m_x, m_y, width(), height());
+    boundsRect.intersect(frameVisibleRect(renderer()));
+
+    RenderLayer* insideLayer = hitTestLayer(this, request, result, boundsRect, result.point());
+
+    // Now determine if the result is inside an anchor; make sure an image map wins if
+    // it already set URLElement and only use the innermost.
+    Node* node = result.innerNode();
+    while (node) {
+        // for imagemaps, URLElement is the associated area element not the image itself
+        if (node->isLink() && !result.URLElement() && !node->hasTagName(imgTag))
+            result.setURLElement(static_cast<Element*>(node));
+        node = node->eventParentNode();
+    }
+
+    // Next set up the correct :hover/:active state along the new chain.
+    updateHoverActiveState(request, result);
+    
+    // Now return whether we were inside this layer (this will always be true for the root
+    // layer).
+    return insideLayer;
+}
+
+Node* RenderLayer::enclosingElement() const
+{
+    for (RenderObject* r = renderer(); r; r = r->parent()) {
+        if (Node* e = r->element())
+            return e;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
+                                       const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform)
+{
+    // Apply a transform if we have one.
+    if (m_transform && !appliedTransform) {
+        // If the transform can't be inverted, then don't hit test this layer at all.
+        if (!m_transform->isInvertible())
+            return 0;
+  
+        // Make sure the parent's clip rects have been calculated.
+        if (parent()) {
+            parent()->calculateClipRects(rootLayer);
+        
+            // Go ahead and test the enclosing clip now.
+            IntRect clipRect = parent()->clipRects()->overflowClipRect();
+            if (!clipRect.contains(hitTestPoint))
+                return 0;
+        }
+
+        // Adjust the transform such that the renderer's upper left corner is at (0,0) in user space.
+        // This involves subtracting out the position of the layer in our current coordinate space.
+        int x = 0;
+        int y = 0;
+        convertToLayerCoords(rootLayer, x, y);
+        AffineTransform transform;
+        transform.translate(x, y);
+        transform = *m_transform * transform;
+        
+        // Map the hit test point into the transformed space and then do a hit test with the root layer shifted to be us.
+        return hitTestLayer(this, request, result, transform.inverse().mapRect(hitTestRect), transform.inverse().mapPoint(hitTestPoint), true);
+    }
+
+    // Calculate the clip rects we should use.
+    IntRect layerBounds;
+    IntRect bgRect;
+    IntRect fgRect;
+    IntRect outlineRect;
+    calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect);
+    
+    // Ensure our lists are up-to-date.
+    updateZOrderLists();
+    updateOverflowList();
+
+    // This variable tracks which layer the mouse ends up being inside.  The minute we find an insideLayer,
+    // we are done and can return it.
+    RenderLayer* insideLayer = 0;
+    
+    // Begin by walking our list of positive layers from highest z-index down to the lowest
+    // z-index.
+    if (m_posZOrderList) {
+        for (int i = m_posZOrderList->size() - 1; i >= 0; --i) {
+            insideLayer = m_posZOrderList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
+            if (insideLayer)
+                return insideLayer;
+        }
+    }
+
+    // Now check our overflow objects.
+    if (m_overflowList) {
+        for (int i = m_overflowList->size() - 1; i >= 0; --i) {
+            insideLayer = m_overflowList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
+            if (insideLayer)
+                return insideLayer;
+        }
+    }
+
+    // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
+    if (fgRect.contains(hitTestPoint) && 
+        renderer()->hitTest(request, result, hitTestPoint,
+                            layerBounds.x() - renderer()->xPos(),
+                            layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(), 
+                            HitTestDescendants)) {
+        // For positioned generated content, we might still not have a
+        // node by the time we get to the layer level, since none of
+        // the content in the layer has an element. So just walk up
+        // the tree.
+        if (!result.innerNode() || !result.innerNonSharedNode()) {
+            Node* e = enclosingElement();
+            if (!result.innerNode())
+                result.setInnerNode(e);
+            if (!result.innerNonSharedNode())
+                result.setInnerNonSharedNode(e);
+        }
+
+        return this;
+    }
+        
+    // Now check our negative z-index children.
+    if (m_negZOrderList) {
+        for (int i = m_negZOrderList->size() - 1; i >= 0; --i) {
+            insideLayer = m_negZOrderList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
+            if (insideLayer)
+                return insideLayer;
+        }
+    }
+
+    // Next we want to see if the mouse is inside this layer but not any of its children.
+    if (bgRect.contains(hitTestPoint) &&
+        renderer()->hitTest(request, result, hitTestPoint,
+                            layerBounds.x() - renderer()->xPos(),
+                            layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(),
+                            HitTestSelf)) {
+        if (!result.innerNode() || !result.innerNonSharedNode()) {
+            Node* e = enclosingElement();
+            if (!result.innerNode())
+                result.setInnerNode(e);
+            if (!result.innerNonSharedNode())
+                result.setInnerNonSharedNode(e);
+        }
+
+        return this;
+    }
+
+    // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down, 
+    // return ourselves. We do this so mouse events continue getting delivered after a drag has 
+    // exited the WebView, and so hit testing over a scrollbar hits the content document.
+    if ((request.active || request.mouseUp) && renderer()->isRenderView()) {
+        renderer()->updateHitTestResult(result, hitTestPoint);
+        return this;
+    }
+
+    return 0;
+}
+
+void RenderLayer::calculateClipRects(const RenderLayer* rootLayer)
+{
+    if (m_clipRects)
+        return; // We have the correct cached value.
+
+    IntRect infiniteRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX);
+    if (!parent()) {
+        // The root layer's clip rect is always infinite.
+        m_clipRects = new (m_object->renderArena()) ClipRects(infiniteRect);
+        m_clipRects->ref();
+        return;
+    }
+
+    // For transformed layers, the root layer was shifted to be us, so there is no need to
+    // examine the parent.  We want to cache clip rects with us as the root.
+    RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
+    
+    // Ensure that our parent's clip has been calculated so that we can examine the values.
+    if (parentLayer)
+        parentLayer->calculateClipRects(rootLayer);
+
+    // Set up our three rects to initially match the parent rects.
+    IntRect posClipRect(parentLayer ? parentLayer->clipRects()->posClipRect() : infiniteRect);
+    IntRect overflowClipRect(parentLayer ? parentLayer->clipRects()->overflowClipRect() : infiniteRect);
+    IntRect fixedClipRect(parentLayer ? parentLayer->clipRects()->fixedClipRect() : infiniteRect);
+    bool fixed = parentLayer ? parentLayer->clipRects()->fixed() : false;
+
+    // A fixed object is essentially the root of its containing block hierarchy, so when
+    // we encounter such an object, we reset our clip rects to the fixedClipRect.
+    if (m_object->style()->position() == FixedPosition) {
+        posClipRect = fixedClipRect;
+        overflowClipRect = fixedClipRect;
+        fixed = true;
+    }
+    else if (m_object->style()->position() == RelativePosition)
+        posClipRect = overflowClipRect;
+    else if (m_object->style()->position() == AbsolutePosition)
+        overflowClipRect = posClipRect;
+    
+    // Update the clip rects that will be passed to child layers.
+    if (m_object->hasOverflowClip() || m_object->hasClip()) {
+        // This layer establishes a clip of some kind.
+        int x = 0;
+        int y = 0;
+        convertToLayerCoords(rootLayer, x, y);
+        RenderView* view = renderer()->view();
+        ASSERT(view);
+        if (view && fixed && rootLayer->renderer() == view) {
+            x -= view->frameView()->scrollX();
+            y -= view->frameView()->scrollY();
+        }
+        
+        if (m_object->hasOverflowClip()) {
+            IntRect newOverflowClip = m_object->getOverflowClipRect(x,y);
+            overflowClipRect.intersect(newOverflowClip);
+            if (m_object->isPositioned() || m_object->isRelPositioned())
+                posClipRect.intersect(newOverflowClip);
+        }
+        if (m_object->hasClip()) {
+            IntRect newPosClip = m_object->getClipRect(x,y);
+            posClipRect.intersect(newPosClip);
+            overflowClipRect.intersect(newPosClip);
+            fixedClipRect.intersect(newPosClip);
+        }
+    }
+    
+    // If our clip rects match our parent's clip, then we can just share its data structure and
+    // ref count.
+    if (parent()->clipRects() &&
+        fixed == parent()->clipRects()->fixed() &&
+        posClipRect == parent()->clipRects()->posClipRect() &&
+        overflowClipRect == parent()->clipRects()->overflowClipRect() &&
+        fixedClipRect == parent()->clipRects()->fixedClipRect())
+        m_clipRects = parent()->clipRects();
+    else
+        m_clipRects = new (m_object->renderArena()) ClipRects(overflowClipRect, fixedClipRect, posClipRect, fixed);
+    m_clipRects->ref();
+}
+
+void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
+                                 IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect) const
+{
+    if (rootLayer != this && parent()) {
+        parent()->calculateClipRects(rootLayer);
+
+        backgroundRect = m_object->style()->position() == FixedPosition ? parent()->clipRects()->fixedClipRect() :
+                         (m_object->isPositioned() ? parent()->clipRects()->posClipRect() : 
+                                                     parent()->clipRects()->overflowClipRect());
+        RenderView* view = renderer()->view();
+        ASSERT(view);
+        if (view && parent()->clipRects()->fixed() && rootLayer->renderer() == view)
+            backgroundRect.move(view->frameView()->scrollX(), view->frameView()->scrollY());
+
+        backgroundRect.intersect(paintDirtyRect);
+    } else
+        backgroundRect = paintDirtyRect;
+    foregroundRect = backgroundRect;
+    outlineRect = backgroundRect;
+    
+    int x = 0;
+    int y = 0;
+    convertToLayerCoords(rootLayer, x, y);
+    layerBounds = IntRect(x,y,width(),height());
+    
+    // Update the clip rects that will be passed to child layers.
+    if (m_object->hasOverflowClip() || m_object->hasClip()) {
+        // This layer establishes a clip of some kind.
+        if (m_object->hasOverflowClip())
+            foregroundRect.intersect(m_object->getOverflowClipRect(x,y));
+        if (m_object->hasClip()) {
+            // Clip applies to *us* as well, so go ahead and update the damageRect.
+            IntRect newPosClip = m_object->getClipRect(x,y);
+            backgroundRect.intersect(newPosClip);
+            foregroundRect.intersect(newPosClip);
+            outlineRect.intersect(newPosClip);
+        }
+
+        // If we establish a clip at all, then go ahead and make sure our background
+        // rect is intersected with our layer's bounds.
+        if (ShadowData* boxShadow = renderer()->style()->boxShadow()) {
+            IntRect overflow = layerBounds;
+            do {
+                IntRect shadowRect = layerBounds;
+                shadowRect.move(boxShadow->x, boxShadow->y);
+                shadowRect.inflate(boxShadow->blur);
+                overflow.unite(shadowRect);
+                boxShadow = boxShadow->next;
+            } while (boxShadow);
+            backgroundRect.intersect(overflow);
+        } else
+            backgroundRect.intersect(layerBounds);
+    }
+}
+
+IntRect RenderLayer::childrenClipRect() const
+{
+    RenderLayer* rootLayer = renderer()->document()->renderer()->layer();
+    IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
+    calculateRects(rootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect);
+    return foregroundRect;
+}
+
+IntRect RenderLayer::selfClipRect() const
+{
+    RenderLayer* rootLayer = renderer()->document()->renderer()->layer();
+    IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
+    calculateRects(rootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect);
+    return backgroundRect;
+}
+
+bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const
+{
+    // Always examine the canvas and the root.
+    // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
+    // paints the root's background.
+    if (renderer()->isRenderView() || renderer()->isRoot())
+        return true;
+
+    // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we 
+    // can go ahead and return true.
+    RenderView* view = renderer()->view();
+    ASSERT(view);
+    if (view && !renderer()->isInlineFlow()) {
+        IntRect b = layerBounds;
+        b.inflate(view->maximalOutlineSize());
+        if (b.intersects(damageRect))
+            return true;
+    }
+        
+    // Otherwise we need to compute the bounding box of this single layer and see if it intersects
+    // the damage rect.
+    return boundingBox(rootLayer).intersects(damageRect);
+}
+
+IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
+{
+    // There are three special cases we need to consider.
+    // (1) Inline Flows.  For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
+    // inline.  In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the root
+    // line boxes of all three lines (including overflow on those lines).
+    // (2) Left/Top Overflow.  The width/height of layers already includes right/bottom overflow.  However, in the case of left/top
+    // overflow, we have to create a bounding box that will extend to include this overflow.
+    // (3) Floats.  When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats
+    // as part of our bounding box.  We do this because we are the responsible layer for both hit testing and painting those
+    // floats.
+    IntRect result;
+    if (renderer()->isInlineFlow()) {
+        // Go from our first line box to our last line box.
+        RenderInline* inlineFlow = static_cast<RenderInline*>(renderer());
+        InlineFlowBox* firstBox = inlineFlow->firstLineBox();
+        if (!firstBox)
+            return result;
+        int top = firstBox->root()->topOverflow();
+        int bottom = inlineFlow->lastLineBox()->root()->bottomOverflow();
+        int left = firstBox->xPos();
+        for (InlineRunBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox())
+            left = min(left, curr->xPos());
+        result = IntRect(m_x + left, m_y + (top - renderer()->yPos()), width(), bottom - top);
+    } else if (renderer()->isTableRow()) {
+        // Our bounding box is just the union of all of our cells' border/overflow rects.
+        for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
+            if (child->isTableCell()) {
+                IntRect bbox = child->borderBox();
+                bbox.move(0, child->borderTopExtra());
+                result.unite(bbox);
+                IntRect overflowRect = renderer()->overflowRect(false);
+                overflowRect.move(0, child->borderTopExtra());
+                if (bbox != overflowRect)
+                    result.unite(overflowRect);
+            }
+        }
+        result.move(m_x, m_y);
+    } else {
+        if (renderer()->hasMask())
+            result = renderer()->maskClipRect();
+        else {
+            IntRect bbox = renderer()->borderBox();
+            result = bbox;
+            IntRect overflowRect = renderer()->overflowRect(false);
+            if (bbox != overflowRect)
+                result.unite(overflowRect);
+        }
+
+        // We have to adjust the x/y of this result so that it is in the coordinate space of the layer.
+        // We also have to add in borderTopExtra here, since borderBox(), in order to play well with methods like
+        // floatRect that deal with child content, uses an origin of (0,0) that is at the child content box (so
+        // border box returns a y coord of -borderTopExtra().  The layer, however, uses the outer box.  This is all
+        // really confusing.
+        result.move(m_x, m_y + renderer()->borderTopExtra());
+    }
+    
+    // Convert the bounding box to an absolute position.  We can do this easily by looking at the delta
+    // between the bounding box's xpos and our layer's xpos and then applying that to the absolute layerBounds
+    // passed in.
+    int absX = 0, absY = 0;
+    convertToLayerCoords(rootLayer, absX, absY);
+    result.move(absX - m_x, absY - m_y);
+    RenderView* view = renderer()->view();
+    ASSERT(view);
+    if (view)
+        result.inflate(view->maximalOutlineSize());
+    return result;
+}
+
+void RenderLayer::clearClipRects()
+{
+    if (!m_clipRects)
+        return;
+
+    clearClipRect();
+    
+    for (RenderLayer* l = firstChild(); l; l = l->nextSibling())
+        l->clearClipRects();
+}
+
+void RenderLayer::clearClipRect()
+{
+    if (m_clipRects) {
+        m_clipRects->deref(m_object->renderArena());
+        m_clipRects = 0;
+    }
+}
+
+static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
+{
+    if (!obj1 || !obj2)
+        return 0;
+
+    for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor())
+        for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor())
+            if (currObj1 == currObj2)
+                return currObj1;
+
+    return 0;
+}
+
+void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestResult& result)
+{
+    // We don't update :hover/:active state when the result is marked as readonly.
+    if (request.readonly)
+        return;
+
+    Document* doc = renderer()->document();
+
+    Node* activeNode = doc->activeNode();
+    if (activeNode && !request.active) {
+        // We are clearing the :active chain because the mouse has been released.
+        for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) {
+            if (curr->element() && !curr->isText())
+                curr->element()->setInActiveChain(false);
+        }
+        doc->setActiveNode(0);
+    } else {
+        Node* newActiveNode = result.innerNode();
+        if (!activeNode && newActiveNode && request.active) {
+            // We are setting the :active chain and freezing it. If future moves happen, they
+            // will need to reference this chain.
+            for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) {
+                if (curr->element() && !curr->isText()) {
+                    curr->element()->setInActiveChain(true);
+                }
+            }
+            doc->setActiveNode(newActiveNode);
+        }
+    }
+
+    // If the mouse is down and if this is a mouse move event, we want to restrict changes in 
+    // :hover/:active to only apply to elements that are in the :active chain that we froze
+    // at the time the mouse went down.
+    bool mustBeInActiveChain = request.active && request.mouseMove;
+
+    // Check to see if the hovered node has changed.  If not, then we don't need to
+    // do anything.  
+    RefPtr<Node> oldHoverNode = doc->hoverNode();
+    Node* newHoverNode = result.innerNode();
+
+    // Update our current hover node.
+    doc->setHoverNode(newHoverNode);
+
+    // We have two different objects.  Fetch their renderers.
+    RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
+    RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;
+    
+    // Locate the common ancestor render object for the two renderers.
+    RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
+
+    if (oldHoverObj != newHoverObj) {
+        // The old hover path only needs to be cleared up to (and not including) the common ancestor;
+        for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) {
+            if (curr->element() && !curr->isText() && (!mustBeInActiveChain || curr->element()->inActiveChain())) {
+                curr->element()->setActive(false);
+                curr->element()->setHovered(false);
+            }
+        }
+    }
+
+    // Now set the hover state for our new object up to the root.
+    for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
+        if (curr->element() && !curr->isText() && (!mustBeInActiveChain || curr->element()->inActiveChain())) {
+            curr->element()->setActive(request.active);
+            curr->element()->setHovered(true);
+        }
+    }
+}
+
+// Helper for the sorting of layers by z-index.
+static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
+{
+    return first->zIndex() < second->zIndex();
+}
+
+void RenderLayer::dirtyZOrderLists()
+{
+    if (m_posZOrderList)
+        m_posZOrderList->clear();
+    if (m_negZOrderList)
+        m_negZOrderList->clear();
+    m_zOrderListsDirty = true;
+}
+
+void RenderLayer::dirtyStackingContextZOrderLists()
+{
+    RenderLayer* sc = stackingContext();
+    if (sc)
+        sc->dirtyZOrderLists();
+}
+
+void RenderLayer::dirtyOverflowList()
+{
+    if (m_overflowList)
+        m_overflowList->clear();
+    m_overflowListDirty = true;
+}
+
+void RenderLayer::updateZOrderLists()
+{
+    if (!isStackingContext() || !m_zOrderListsDirty)
+        return;
+        
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        if (!m_reflection || reflectionLayer() != child)
+            child->collectLayers(m_posZOrderList, m_negZOrderList);
+
+    // Sort the two lists.
+    if (m_posZOrderList)
+        std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex);
+    if (m_negZOrderList)
+        std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
+
+    m_zOrderListsDirty = false;
+}
+
+void RenderLayer::updateOverflowList()
+{
+    if (!m_overflowListDirty)
+        return;
+        
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+        // Ignore non-overflow layers and reflections.
+        if (child->isOverflowOnly() && (!m_reflection || reflectionLayer() != child)) {
+            if (!m_overflowList)
+                m_overflowList = new Vector<RenderLayer*>;
+            m_overflowList->append(child);
+        }
+    }
+    
+    m_overflowListDirty = false;
+}
+
+void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer)
+{
+    updateVisibilityStatus();
+
+    // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
+    if ((m_hasVisibleContent || (m_hasVisibleDescendant && isStackingContext())) && !isOverflowOnly()) {
+        // Determine which buffer the child should be in.
+        Vector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
+
+        // Create the buffer if it doesn't exist yet.
+        if (!buffer)
+            buffer = new Vector<RenderLayer*>;
+        
+        // Append ourselves at the end of the appropriate buffer.
+        buffer->append(this);
+    }
+
+    // Recur into our children to collect more layers, but only if we don't establish
+    // a stacking context.
+    if (m_hasVisibleDescendant && !isStackingContext()) {
+        for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+            // Ignore reflections.
+            if (!m_reflection || reflectionLayer() != child)
+                child->collectLayers(posBuffer, negBuffer);
+        }
+    }
+}
+
+void RenderLayer::repaintIncludingDescendants()
+{
+    m_object->repaint();
+    for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
+        curr->repaintIncludingDescendants();
+}
+
+bool RenderLayer::shouldBeOverflowOnly() const
+{
+    return (renderer()->hasOverflowClip() || renderer()->hasReflection()) && 
+           !renderer()->isPositioned() &&
+           !renderer()->isRelPositioned() &&
+           !renderer()->hasTransform() &&
+           !isTransparent();
+}
+
+void RenderLayer::styleChanged(RenderStyle::Diff, const RenderStyle* oldStyle)
+{
+    bool isOverflowOnly = shouldBeOverflowOnly();
+    if (isOverflowOnly != m_isOverflowOnly) {
+        m_isOverflowOnly = isOverflowOnly;
+        RenderLayer* p = parent();
+        if (p)
+            p->dirtyOverflowList();
+        dirtyStackingContextZOrderLists();
+    }
+
+    if (m_object->style()->overflowX() == OMARQUEE && m_object->style()->marqueeBehavior() != MNONE) {
+        if (!m_marquee)
+            m_marquee = new RenderMarquee(this);
+        m_marquee->updateMarqueeStyle();
+    }
+    else if (m_marquee) {
+        delete m_marquee;
+        m_marquee = 0;
+    }
+    
+    if (!hasReflection() && m_reflection) {
+        m_reflection->destroy();
+        m_reflection = 0;
+    } else if (hasReflection()) {
+        if (!m_reflection)
+            createReflection();
+        updateReflectionStyle();
+    }
+    
+    // FIXME: Need to detect a swap from custom to native scrollbars (and vice versa).
+    if (m_hBar)
+        m_hBar->styleChanged();
+    if (m_vBar)
+        m_vBar->styleChanged();
+    
+    updateScrollCornerStyle();
+    updateResizerStyle();
+}
+
+void RenderLayer::updateScrollCornerStyle()
+{
+    RenderObject* actualRenderer = m_object->node()->isElementNode() ? m_object->node()->shadowAncestorNode()->renderer() : m_object;
+    RefPtr<RenderStyle> corner = m_object->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RenderStyle::SCROLLBAR_CORNER, actualRenderer->style()) : 0;
+    if (corner) {
+        if (!m_scrollCorner) {
+            m_scrollCorner = new (m_object->renderArena()) RenderScrollbarPart(m_object->document());
+            m_scrollCorner->setParent(m_object);
+        }
+        m_scrollCorner->setStyle(corner.release());
+    } else if (m_scrollCorner) {
+        m_scrollCorner->destroy();
+        m_scrollCorner = 0;
+    }
+}
+
+void RenderLayer::updateResizerStyle()
+{
+    RenderObject* actualRenderer = m_object->node()->isElementNode() ? m_object->node()->shadowAncestorNode()->renderer() : m_object;
+    RefPtr<RenderStyle> resizer = m_object->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RenderStyle::RESIZER, actualRenderer->style()) : 0;
+    if (resizer) {
+        if (!m_resizer) {
+            m_resizer = new (m_object->renderArena()) RenderScrollbarPart(m_object->document());
+            m_resizer->setParent(m_object);
+        }
+        m_resizer->setStyle(resizer.release());
+    } else if (m_resizer) {
+        m_resizer->destroy();
+        m_resizer = 0;
+    }
+}
+
+RenderLayer* RenderLayer::reflectionLayer() const
+{
+    return m_reflection ? m_reflection->layer() : 0;
+}
+
+void RenderLayer::createReflection()
+{
+    ASSERT(!m_reflection);
+    m_reflection = new (renderer()->renderArena()) RenderReplica(renderer()->document());
+    m_reflection->setParent(renderer()); // We create a 1-way connection.
+}
+
+void RenderLayer::updateReflectionStyle()
+{
+    RefPtr<RenderStyle> newStyle = RenderStyle::create();
+    newStyle->inheritFrom(renderer()->style());
+    
+    // Map in our transform.
+    TransformOperations transform;
+    switch (renderer()->style()->boxReflect()->direction()) {
+        case ReflectionBelow:
+            transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
+            transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
+            transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
+            break;
+        case ReflectionAbove:
+            transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
+            transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
+            transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
+            break;
+        case ReflectionRight:
+            transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
+            transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
+            transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
+            break;
+        case ReflectionLeft:
+            transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
+            transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
+            transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
+            break;
+    }
+    newStyle->setTransform(transform);
+
+    // Map in our mask.
+    newStyle->setMaskBoxImage(renderer()->style()->boxReflect()->mask());
+    
+    m_reflection->setStyle(newStyle.release());
+}
+
+void RenderLayer::suspendMarquees()
+{
+    if (m_marquee)
+        m_marquee->suspend();
+    
+    for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
+        curr->suspendMarquees();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h
new file mode 100644
index 0000000..f946b5f
--- /dev/null
+++ b/WebCore/rendering/RenderLayer.h
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Robert O'Callahan <[email protected]>
+ *   David Baron <[email protected]>
+ *   Christian Biesinger <[email protected]>
+ *   Randall Jesup <[email protected]>
+ *   Roland Mainz <[email protected]>
+ *   Josh Soref <[email protected]>
+ *   Boris Zbarsky <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above.  If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#ifndef RenderLayer_h
+#define RenderLayer_h
+
+#include "ScrollbarClient.h"
+#include "RenderObject.h"
+#include "Timer.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class AffineTransform;
+class CachedResource;
+class HitTestResult;
+class RenderFrameSet;
+class RenderMarquee;
+class RenderObject;
+class RenderReplica;
+class RenderScrollbarPart;
+class RenderStyle;
+class RenderTable;
+class RenderText;
+class RenderView;
+class Scrollbar;
+
+struct HitTestRequest;
+
+class ClipRects {
+public:
+    ClipRects(const IntRect& r)
+        : m_overflowClipRect(r)
+        , m_fixedClipRect(r)
+        , m_posClipRect(r)
+        , m_refCnt(0)
+        , m_fixed(false)
+    {
+    }
+
+    ClipRects(const IntRect& overflowRect, const IntRect& fixedRect, const IntRect& posRect, bool fixed)
+        : m_overflowClipRect(overflowRect)
+        , m_fixedClipRect(fixedRect)
+        , m_posClipRect(posRect)
+        , m_refCnt(0)
+        , m_fixed(fixed)
+    {
+    }
+
+    const IntRect& overflowClipRect() { return m_overflowClipRect; }
+    const IntRect& fixedClipRect() { return m_fixedClipRect; }
+    const IntRect& posClipRect() { return m_posClipRect; }
+    bool fixed() const { return m_fixed; }
+
+    void ref() { m_refCnt++; }
+    void deref(RenderArena* renderArena) { if (--m_refCnt == 0) destroy(renderArena); }
+
+    void destroy(RenderArena*);
+
+    // Overloaded new operator.
+    void* operator new(size_t, RenderArena*) throw();
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void*, size_t);
+        
+private:
+    // The normal operator new is disallowed on all render objects.
+    void* operator new(size_t) throw();
+
+private:
+    IntRect m_overflowClipRect;
+    IntRect m_fixedClipRect;
+    IntRect m_posClipRect;
+    unsigned m_refCnt : 31;
+    bool m_fixed : 1;
+};
+
+class RenderLayer : public ScrollbarClient {
+public:
+    enum ScrollBehavior {
+        noScroll,
+        alignCenter,
+        alignTop,
+        alignBottom, 
+        alignLeft,
+        alignRight,
+        alignToClosestEdge
+    };
+
+    struct ScrollAlignment {
+        ScrollBehavior m_rectVisible;
+        ScrollBehavior m_rectHidden;
+        ScrollBehavior m_rectPartial;
+    };
+
+    friend class RenderReplica;
+
+    static const ScrollAlignment gAlignCenterIfNeeded;
+    static const ScrollAlignment gAlignToEdgeIfNeeded;
+    static const ScrollAlignment gAlignCenterAlways;
+    static const ScrollAlignment gAlignTopAlways;
+    static const ScrollAlignment gAlignBottomAlways;
+
+    static ScrollBehavior getVisibleBehavior(const ScrollAlignment& s) { return s.m_rectVisible; }
+    static ScrollBehavior getPartialBehavior(const ScrollAlignment& s) { return s.m_rectPartial; }
+    static ScrollBehavior getHiddenBehavior(const ScrollAlignment& s) { return s.m_rectHidden; }
+
+    RenderLayer(RenderObject*);
+    ~RenderLayer();
+
+    RenderObject* renderer() const { return m_object; }
+    RenderLayer* parent() const { return m_parent; }
+    RenderLayer* previousSibling() const { return m_previous; }
+    RenderLayer* nextSibling() const { return m_next; }
+    RenderLayer* firstChild() const { return m_first; }
+    RenderLayer* lastChild() const { return m_last; }
+
+    void addChild(RenderLayer* newChild, RenderLayer* beforeChild = 0);
+    RenderLayer* removeChild(RenderLayer*);
+
+    void removeOnlyThisLayer();
+    void insertOnlyThisLayer();
+
+    void repaintIncludingDescendants();
+
+    void styleChanged(RenderStyle::Diff, const RenderStyle*);
+
+    RenderMarquee* marquee() const { return m_marquee; }
+    void suspendMarquees();
+
+    bool isOverflowOnly() const { return m_isOverflowOnly; }
+
+    bool requiresSlowRepaints() const;
+
+    bool isTransparent() const;
+    RenderLayer* transparentAncestor();
+    void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer);
+
+    bool hasReflection() const { return m_object->hasReflection(); }
+    RenderReplica* reflection() const { return m_reflection; }
+    RenderLayer* reflectionLayer() const;
+
+    const RenderLayer* root() const
+    {
+        const RenderLayer* curr = this;
+        while (curr->parent())
+            curr = curr->parent();
+        return curr;
+    }
+    
+    int xPos() const { return m_x; }
+    int yPos() const { return m_y; }
+    void setPos(int xPos, int yPos)
+    {
+        m_x = xPos;
+        m_y = yPos;
+    }
+
+    int width() const { return m_width; }
+    int height() const { return m_height; }
+    void setWidth(int w) { m_width = w; }
+    void setHeight(int h) { m_height = h; }
+
+    int scrollWidth();
+    int scrollHeight();
+
+    void panScrollFromPoint(const IntPoint&);
+
+    // Scrolling methods for layers that can scroll their overflow.
+    void scrollByRecursively(int xDelta, int yDelta);
+    void scrollOffset(int& x, int& y);
+    void subtractScrollOffset(int& x, int& y);
+    int scrollXOffset() const { return m_scrollX + m_scrollOriginX; }
+    int scrollYOffset() const { return m_scrollY; }
+    void scrollToOffset(int x, int y, bool updateScrollbars = true, bool repaint = true);
+    void scrollToXOffset(int x) { scrollToOffset(x, m_scrollY); }
+    void scrollToYOffset(int y) { scrollToOffset(m_scrollX + m_scrollOriginX, y); }
+    void scrollRectToVisible(const IntRect&, bool scrollToAnchor = false, const ScrollAlignment& alignX = gAlignCenterIfNeeded, const ScrollAlignment& alignY = gAlignCenterIfNeeded);
+
+    IntRect getRectToExpose(const IntRect& visibleRect, const IntRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY);    
+
+    void setHasHorizontalScrollbar(bool);
+    void setHasVerticalScrollbar(bool);
+
+    PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation);
+    void destroyScrollbar(ScrollbarOrientation);
+
+    Scrollbar* horizontalScrollbar() const { return m_hBar.get(); }
+    Scrollbar* verticalScrollbar() const { return m_vBar.get(); }
+
+    int verticalScrollbarWidth() const;
+    int horizontalScrollbarHeight() const;
+
+    void positionOverflowControls(int tx, int ty);
+    bool isPointInResizeControl(const IntPoint&);
+    bool hitTestOverflowControls(HitTestResult&);
+    IntSize offsetFromResizeCorner(const IntPoint&) const;
+
+    void paintOverflowControls(GraphicsContext*, int tx, int ty, const IntRect& damageRect);
+    void paintScrollCorner(GraphicsContext*, int tx, int ty, const IntRect& damageRect);
+    void paintResizer(GraphicsContext*, int tx, int ty, const IntRect& damageRect);
+
+    void updateScrollInfoAfterLayout();
+
+    bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f);
+    void autoscroll();
+
+    void resize(const PlatformMouseEvent&, const IntSize&);
+    bool inResizeMode() const { return m_inResizeMode; }
+    void setInResizeMode(bool b) { m_inResizeMode = b; }
+    
+    void updateLayerPosition();
+    void updateLayerPositions(bool doFullRepaint = false, bool checkForRepaint = true);
+
+    void updateTransform();
+
+    void relativePositionOffset(int& relX, int& relY) { relX += m_relX; relY += m_relY; }
+
+    void clearClipRects();
+    void clearClipRect();
+
+    // Get the enclosing stacking context for this layer.  A stacking context is a layer
+    // that has a non-auto z-index.
+    RenderLayer* stackingContext() const;
+    bool isStackingContext() const { return !hasAutoZIndex() || renderer()->isRenderView(); }
+
+    void dirtyZOrderLists();
+    void dirtyStackingContextZOrderLists();
+    void updateZOrderLists();
+    Vector<RenderLayer*>* posZOrderList() const { return m_posZOrderList; }
+    Vector<RenderLayer*>* negZOrderList() const { return m_negZOrderList; }
+
+    void dirtyOverflowList();
+    void updateOverflowList();
+    Vector<RenderLayer*>* overflowList() const { return m_overflowList; }
+
+    bool hasVisibleContent() const { return m_hasVisibleContent; }
+    void setHasVisibleContent(bool);
+    void dirtyVisibleContentStatus();
+
+    // Gets the nearest enclosing positioned ancestor layer (also includes
+    // the <html> layer and the root layer).
+    RenderLayer* enclosingPositionedAncestor() const;
+
+    void convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const;
+
+    bool hasAutoZIndex() const { return renderer()->style()->hasAutoZIndex(); }
+    int zIndex() const { return renderer()->style()->zIndex(); }
+
+    // The two main functions that use the layer system.  The paint method
+    // paints the layers that intersect the damage rect from back to
+    // front.  The hitTest method looks for mouse events by walking
+    // layers that intersect the point from front to back.
+    void paint(GraphicsContext*, const IntRect& damageRect, PaintRestriction = PaintRestrictionNone, RenderObject* paintingRoot = 0);
+    bool hitTest(const HitTestRequest&, HitTestResult&);
+
+    // This method figures out our layerBounds in coordinates relative to
+    // |rootLayer}.  It also computes our background and foreground clip rects
+    // for painting/event handling.
+    void calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
+                        IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect) const;
+    void calculateClipRects(const RenderLayer* rootLayer);
+    ClipRects* clipRects() const { return m_clipRects; }
+    IntRect childrenClipRect() const; // Returns the foreground clip rect of the layer in the document's coordinate space.
+    IntRect selfClipRect() const; // Returns the background clip rect of the layer in the document's coordinate space.
+
+    bool intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const;
+
+    // Returns a bounding box for this layer only.
+    IntRect boundingBox(const RenderLayer* rootLayer) const;
+
+    void updateHoverActiveState(const HitTestRequest&, HitTestResult&);
+
+    IntRect repaintRect() const { return m_repaintRect; }
+    void setNeedsFullRepaint(bool f = true) { m_needsFullRepaint = f; }
+    
+    int staticX() const { return m_staticX; }
+    int staticY() const { return m_staticY; }
+    void setStaticX(int staticX) { m_staticX = staticX; }
+    void setStaticY(int staticY) { m_staticY = staticY; }
+
+    bool hasTransform() const { return m_object->hasTransform(); }
+    AffineTransform* transform() const { return m_transform.get(); }
+
+    void destroy(RenderArena*);
+
+     // Overloaded new operator.  Derived classes must override operator new
+    // in order to allocate out of the RenderArena.
+    void* operator new(size_t, RenderArena*) throw();
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void*, size_t);
+
+private:
+    // The normal operator new is disallowed on all render objects.
+    void* operator new(size_t) throw();
+
+private:
+    void setNextSibling(RenderLayer* next) { m_next = next; }
+    void setPreviousSibling(RenderLayer* prev) { m_previous = prev; }
+    void setParent(RenderLayer* parent) { m_parent = parent; }
+    void setFirstChild(RenderLayer* first) { m_first = first; }
+    void setLastChild(RenderLayer* last) { m_last = last; }
+
+    void collectLayers(Vector<RenderLayer*>*&, Vector<RenderLayer*>*&);
+
+    void paintLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect,
+                    bool haveTransparency, PaintRestriction, RenderObject* paintingRoot, bool appliedTransform = false);
+    RenderLayer* hitTestLayer(RenderLayer* rootLayer, const HitTestRequest&, HitTestResult&, const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform = false);
+    void computeScrollDimensions(bool* needHBar = 0, bool* needVBar = 0);
+
+    bool shouldBeOverflowOnly() const;
+
+    virtual void valueChanged(Scrollbar*);
+    virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
+    virtual bool isActive() const;
+    virtual bool scrollbarCornerPresent() const;
+
+    void updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow);
+
+    void childVisibilityChanged(bool newVisibility);
+    void dirtyVisibleDescendantStatus();
+    void updateVisibilityStatus();
+
+    Node* enclosingElement() const;
+
+    void createReflection();
+    void updateReflectionStyle();
+    bool paintingInsideReflection() const { return m_paintingInsideReflection; }
+
+    RenderLayer* enclosingTransformedAncestor() const;
+
+    void updateScrollCornerStyle();
+    void updateResizerStyle();
+
+protected:   
+    RenderObject* m_object;
+
+    RenderLayer* m_parent;
+    RenderLayer* m_previous;
+    RenderLayer* m_next;
+    RenderLayer* m_first;
+    RenderLayer* m_last;
+
+    IntRect m_repaintRect; // Cached repaint rects. Used by layout.
+    IntRect m_outlineBox;
+
+    // Our current relative position offset.
+    int m_relX;
+    int m_relY;
+
+    // Our (x,y) coordinates are in our parent layer's coordinate space.
+    int m_x;
+    int m_y;
+
+    // The layer's width/height
+    int m_width;
+    int m_height;
+
+    // Our scroll offsets if the view is scrolled.
+    int m_scrollX;
+    int m_scrollY;
+    int m_scrollOriginX;
+    int m_scrollLeftOverflow;
+
+    // The width/height of our scrolled area.
+    int m_scrollWidth;
+    int m_scrollHeight;
+
+    // For layers with overflow, we have a pair of scrollbars.
+    RefPtr<Scrollbar> m_hBar;
+    RefPtr<Scrollbar> m_vBar;
+
+    // Keeps track of whether the layer is currently resizing, so events can cause resizing to start and stop.
+    bool m_inResizeMode;
+
+    // For layers that establish stacking contexts, m_posZOrderList holds a sorted list of all the
+    // descendant layers within the stacking context that have z-indices of 0 or greater
+    // (auto will count as 0).  m_negZOrderList holds descendants within our stacking context with negative
+    // z-indices.
+    Vector<RenderLayer*>* m_posZOrderList;
+    Vector<RenderLayer*>* m_negZOrderList;
+
+    // This list contains child layers that cannot create stacking contexts.  For now it is just
+    // overflow layers, but that may change in the future.
+    Vector<RenderLayer*>* m_overflowList;
+
+    ClipRects* m_clipRects;      // Cached clip rects used when painting and hit testing.
+
+    bool m_scrollDimensionsDirty : 1;
+    bool m_zOrderListsDirty : 1;
+    bool m_overflowListDirty: 1;
+    bool m_isOverflowOnly : 1;
+
+    bool m_usedTransparency : 1; // Tracks whether we need to close a transparent layer, i.e., whether
+                                 // we ended up painting this layer or any descendants (and therefore need to
+                                 // blend).
+    bool m_paintingInsideReflection : 1;  // A state bit tracking if we are painting inside a replica.
+    bool m_inOverflowRelayout : 1;
+    bool m_needsFullRepaint : 1;
+
+    bool m_overflowStatusDirty : 1;
+    bool m_horizontalOverflow : 1;
+    bool m_verticalOverflow : 1;
+    bool m_visibleContentStatusDirty : 1;
+    bool m_hasVisibleContent : 1;
+    bool m_visibleDescendantStatusDirty : 1;
+    bool m_hasVisibleDescendant : 1;
+
+    RenderMarquee* m_marquee; // Used by layers with overflow:marquee
+    
+    // Cached normal flow values for absolute positioned elements with static left/top values.
+    int m_staticX;
+    int m_staticY;
+    
+    OwnPtr<AffineTransform> m_transform;
+    
+    // May ultimately be extended to many replicas (with their own paint order).
+    RenderReplica* m_reflection;
+    
+    // Renderers to hold our custom scroll corner and resizer.
+    RenderScrollbarPart* m_scrollCorner;
+    RenderScrollbarPart* m_resizer;
+};
+
+} // namespace WebCore
+
+#endif // RenderLayer_h
diff --git a/WebCore/rendering/RenderLegend.cpp b/WebCore/rendering/RenderLegend.cpp
new file mode 100644
index 0000000..b4cf291
--- /dev/null
+++ b/WebCore/rendering/RenderLegend.cpp
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderLegend.h"
+
+#include "HTMLFormControlElement.h"
+
+namespace WebCore {
+
+RenderLegend::RenderLegend(HTMLFormControlElement* element)
+    : RenderBlock(element)
+{
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderLegend.h b/WebCore/rendering/RenderLegend.h
new file mode 100644
index 0000000..fa8b249
--- /dev/null
+++ b/WebCore/rendering/RenderLegend.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderLegend_h
+#define RenderLegend_h
+
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+    class HTMLFormControlElement;
+
+    class RenderLegend : public RenderBlock {
+    public:
+        RenderLegend(HTMLFormControlElement*);
+
+        virtual const char* renderName() const { return "RenderLegend"; }
+    };
+
+} // namespace WebCore
+
+#endif // RenderLegend_h
diff --git a/WebCore/rendering/RenderListBox.cpp b/WebCore/rendering/RenderListBox.cpp
new file mode 100644
index 0000000..c435ff4
--- /dev/null
+++ b/WebCore/rendering/RenderListBox.cpp
@@ -0,0 +1,651 @@
+/*
+ * This file is part of the select element renderer in WebCore.
+ *
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderListBox.h"
+
+#include "AXObjectCache.h"
+#include "CSSStyleSelector.h"
+#include "Document.h"
+#include "EventHandler.h"
+#include "EventNames.h"
+#include "FocusController.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "HTMLOptGroupElement.h"
+#include "HTMLOptionElement.h"
+#include "HTMLSelectElement.h"
+#include "HitTestResult.h"
+#include "Page.h"
+#include "RenderScrollbar.h"
+#include "RenderTheme.h"
+#include "RenderView.h"
+#include "Scrollbar.h"
+#include "SelectionController.h"
+#include "NodeRenderStyle.h"
+#include <math.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+ 
+const int rowSpacing = 1;
+
+const int optionsSpacingHorizontal = 2;
+
+const int minSize = 4;
+const int maxDefaultSize = 10;
+
+// FIXME: This hardcoded baselineAdjustment is what we used to do for the old
+// widget, but I'm not sure this is right for the new control.
+const int baselineAdjustment = 7;
+
+RenderListBox::RenderListBox(HTMLSelectElement* element)
+    : RenderBlock(element)
+    , m_optionsChanged(true)
+    , m_scrollToRevealSelectionAfterLayout(false)
+    , m_inAutoscroll(false)
+    , m_optionsWidth(0)
+    , m_indexOffset(0)
+{
+}
+
+RenderListBox::~RenderListBox()
+{
+    setHasVerticalScrollbar(false);
+}
+
+void RenderListBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    setReplaced(isInline());
+}
+
+void RenderListBox::updateFromElement()
+{
+    if (m_optionsChanged) {
+        const Vector<HTMLElement*>& listItems = static_cast<HTMLSelectElement*>(node())->listItems();
+        int size = numItems();
+        
+        float width = 0;
+        for (int i = 0; i < size; ++i) {
+            HTMLElement* element = listItems[i];
+            String text;
+            Font itemFont = style()->font();
+            if (element->hasTagName(optionTag))
+                text = static_cast<HTMLOptionElement*>(element)->optionText();
+            else if (element->hasTagName(optgroupTag)) {
+                text = static_cast<HTMLOptGroupElement*>(element)->groupLabelText();
+                FontDescription d = itemFont.fontDescription();
+                d.setWeight(d.bolderWeight());
+                itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
+                itemFont.update(document()->styleSelector()->fontSelector());
+            }
+                
+            if (!text.isEmpty()) {
+                float textWidth = itemFont.floatWidth(TextRun(text.impl(), 0, 0, 0, false, false, false, false));
+                width = max(width, textWidth);
+            }
+        }
+        m_optionsWidth = static_cast<int>(ceilf(width));
+        m_optionsChanged = false;
+        
+        setHasVerticalScrollbar(true);
+
+        setNeedsLayoutAndPrefWidthsRecalc();
+    }
+}
+
+void RenderListBox::selectionChanged()
+{
+    repaint();
+    if (!m_inAutoscroll) {
+        if (m_optionsChanged || needsLayout())
+            m_scrollToRevealSelectionAfterLayout = true;
+        else
+            scrollToRevealSelection();
+    }
+    
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->selectedChildrenChanged(this);
+}
+
+void RenderListBox::layout()
+{
+    RenderBlock::layout();
+    if (m_scrollToRevealSelectionAfterLayout)
+        scrollToRevealSelection();
+}
+
+void RenderListBox::scrollToRevealSelection()
+{    
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+
+    m_scrollToRevealSelectionAfterLayout = false;
+
+    int firstIndex = select->activeSelectionStartListIndex();
+    if (firstIndex >= 0 && !listIndexIsVisible(select->activeSelectionEndListIndex()))
+        scrollToRevealElementAtListIndex(firstIndex);
+}
+
+void RenderListBox::calcPrefWidths()
+{
+    ASSERT(!m_optionsChanged);
+
+    m_minPrefWidth = 0;
+    m_maxPrefWidth = 0;
+
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
+    else {
+        m_maxPrefWidth = m_optionsWidth + 2 * optionsSpacingHorizontal;
+        if (m_vBar)
+            m_maxPrefWidth += m_vBar->width();
+    }
+
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+        m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+    } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
+        m_minPrefWidth = 0;
+    else
+        m_minPrefWidth = m_maxPrefWidth;
+
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
+        m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+        m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+    }
+
+    int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+    m_minPrefWidth += toAdd;
+    m_maxPrefWidth += toAdd;
+                                
+    setPrefWidthsDirty(false);
+}
+
+int RenderListBox::size() const
+{
+    int specifiedSize = static_cast<HTMLSelectElement*>(node())->size();
+    if (specifiedSize > 1)
+        return max(minSize, specifiedSize);
+    return min(max(minSize, numItems()), maxDefaultSize);
+}
+
+int RenderListBox::numVisibleItems() const
+{
+    // Only count fully visible rows. But don't return 0 even if only part of a row shows.
+    return max(1, (contentHeight() + rowSpacing) / itemHeight());
+}
+
+int RenderListBox::numItems() const
+{
+    return static_cast<HTMLSelectElement*>(node())->listItems().size();
+}
+
+int RenderListBox::listHeight() const
+{
+    return itemHeight() * numItems() - rowSpacing;
+}
+
+void RenderListBox::calcHeight()
+{
+    int toAdd = paddingTop() + paddingBottom() + borderTop() + borderBottom();
+ 
+    int itemHeight = RenderListBox::itemHeight();
+    m_height = itemHeight * size() - rowSpacing + toAdd;
+    
+    RenderBlock::calcHeight();
+    
+    if (m_vBar) {
+        bool enabled = numVisibleItems() < numItems();
+        m_vBar->setEnabled(enabled);
+        m_vBar->setSteps(1, min(1, numVisibleItems() - 1), itemHeight);
+        m_vBar->setProportion(numVisibleItems(), numItems());
+        if (!enabled)
+            m_indexOffset = 0;
+    }
+}
+
+int RenderListBox::baselinePosition(bool b, bool isRootLineBox) const
+{
+    return height() + marginTop() + marginBottom() - baselineAdjustment;
+}
+
+IntRect RenderListBox::itemBoundingBoxRect(int tx, int ty, int index)
+{
+    return IntRect(tx + borderLeft() + paddingLeft(),
+                   ty + borderTop() + paddingTop() + itemHeight() * (index - m_indexOffset),
+                   contentWidth(), itemHeight());
+}
+    
+void RenderListBox::paintObject(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (style()->visibility() != VISIBLE)
+        return;
+    
+    int listItemsSize = numItems();
+
+    if (paintInfo.phase == PaintPhaseForeground) {
+        int index = m_indexOffset;
+        while (index < listItemsSize && index <= m_indexOffset + numVisibleItems()) {
+            paintItemForeground(paintInfo, tx, ty, index);
+            index++;
+        }
+    }
+
+    // Paint the children.
+    RenderBlock::paintObject(paintInfo, tx, ty);
+
+    if (paintInfo.phase == PaintPhaseBlockBackground)
+        paintScrollbar(paintInfo, tx, ty);
+    else if (paintInfo.phase == PaintPhaseChildBlockBackground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) {
+        int index = m_indexOffset;
+        while (index < listItemsSize && index <= m_indexOffset + numVisibleItems()) {
+            paintItemBackground(paintInfo, tx, ty, index);
+            index++;
+        }
+    }
+}
+
+void RenderListBox::paintScrollbar(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (m_vBar) {
+        IntRect scrollRect(tx + width() - borderRight() - m_vBar->width(),
+                           ty + borderTop(),
+                           m_vBar->width(),
+                           height() - (borderTop() + borderBottom()));
+        m_vBar->setFrameRect(scrollRect);
+        m_vBar->paint(paintInfo.context, paintInfo.rect);
+    }
+}
+
+void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, int listIndex)
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    const Vector<HTMLElement*>& listItems = select->listItems();
+    HTMLElement* element = listItems[listIndex];
+
+    String itemText;
+    if (element->hasTagName(optionTag))
+        itemText = static_cast<HTMLOptionElement*>(element)->optionText();
+    else if (element->hasTagName(optgroupTag))
+        itemText = static_cast<HTMLOptGroupElement*>(element)->groupLabelText();
+       
+    // Determine where the item text should be placed
+    IntRect r = itemBoundingBoxRect(tx, ty, listIndex);
+    r.move(optionsSpacingHorizontal, style()->font().ascent());
+
+    RenderStyle* itemStyle = element->renderStyle();
+    if (!itemStyle)
+        itemStyle = style();
+    
+    Color textColor = element->renderStyle() ? element->renderStyle()->color() : style()->color();
+    if (element->hasTagName(optionTag) && static_cast<HTMLOptionElement*>(element)->selected()) {
+        if (document()->frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node())
+            textColor = theme()->activeListBoxSelectionForegroundColor();
+        // Honor the foreground color for disabled items
+        else if (!element->disabled())
+            textColor = theme()->inactiveListBoxSelectionForegroundColor();
+    }
+
+    paintInfo.context->setFillColor(textColor);
+
+    Font itemFont = style()->font();
+    if (element->hasTagName(optgroupTag)) {
+        FontDescription d = itemFont.fontDescription();
+        d.setWeight(d.bolderWeight());
+        itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
+        itemFont.update(document()->styleSelector()->fontSelector());
+    }
+    paintInfo.context->setFont(itemFont);
+    
+    unsigned length = itemText.length();
+    const UChar* string = itemText.characters();
+    TextRun textRun(string, length, 0, 0, 0, itemStyle->direction() == RTL, itemStyle->unicodeBidi() == Override, false, false);
+
+    // Draw the item text
+    if (itemStyle->visibility() != HIDDEN)
+        paintInfo.context->drawBidiText(textRun, r.location());
+}
+
+void RenderListBox::paintItemBackground(PaintInfo& paintInfo, int tx, int ty, int listIndex)
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    const Vector<HTMLElement*>& listItems = select->listItems();
+    HTMLElement* element = listItems[listIndex];
+
+    Color backColor;
+    if (element->hasTagName(optionTag) && static_cast<HTMLOptionElement*>(element)->selected()) {
+        if (document()->frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node())
+            backColor = theme()->activeListBoxSelectionBackgroundColor();
+        else
+            backColor = theme()->inactiveListBoxSelectionBackgroundColor();
+    } else
+        backColor = element->renderStyle() ? element->renderStyle()->backgroundColor() : style()->backgroundColor();
+
+    // Draw the background for this list box item
+    if (!element->renderStyle() || element->renderStyle()->visibility() != HIDDEN) {
+        IntRect itemRect = itemBoundingBoxRect(tx, ty, listIndex);
+        itemRect.intersect(controlClipRect(tx, ty));
+        paintInfo.context->fillRect(itemRect, backColor);
+    }
+}
+
+bool RenderListBox::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty)
+{
+    if (!m_vBar)
+        return false;
+
+    IntRect vertRect(_tx + width() - borderRight() - m_vBar->width(),
+                   _ty + borderTop() - borderTopExtra(),
+                   m_vBar->width(),
+                   height() + borderTopExtra() + borderBottomExtra() - borderTop() - borderBottom());
+
+    if (vertRect.contains(_x, _y)) {
+        result.setScrollbar(m_vBar.get());
+        return true;
+    }
+    return false;
+}
+
+int RenderListBox::listIndexAtOffset(int offsetX, int offsetY)
+{
+    if (!numItems())
+        return -1;
+
+    if (offsetY < borderTop() + paddingTop() || offsetY > height() - paddingBottom() - borderBottom())
+        return -1;
+
+    int scrollbarWidth = m_vBar ? m_vBar->width() : 0;
+    if (offsetX < borderLeft() + paddingLeft() || offsetX > width() - borderRight() - paddingRight() - scrollbarWidth)
+        return -1;
+
+    int newOffset = (offsetY - borderTop() - paddingTop()) / itemHeight() + m_indexOffset;
+    return newOffset < numItems() ? newOffset : -1;
+}
+
+void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
+{
+    const int maxSpeed = 20;
+    const int iconRadius = 7;
+    const int speedReducer = 4;
+
+    int offsetX;
+    int offsetY;
+    absolutePosition(offsetX, offsetY);
+
+    IntPoint currentMousePosition = document()->frame()->eventHandler()->currentMousePosition();
+    // We need to check if the current mouse position is out of the window. When the mouse is out of the window, the position is incoherent
+    static IntPoint previousMousePosition;
+    if (currentMousePosition.y() < 0)
+        currentMousePosition = previousMousePosition;
+    else
+        previousMousePosition = currentMousePosition;
+
+    int yDelta = currentMousePosition.y() - panStartMousePosition.y();
+
+   // If the point is too far from the center we limit the speed
+    yDelta = max(min(yDelta, maxSpeed), -maxSpeed);
+    
+    if(abs(yDelta) < iconRadius) // at the center we let the space for the icon
+        return;
+
+    if (yDelta > 0)
+        //offsetY = view()->viewHeight();
+        offsetY += listHeight();
+   else if (yDelta < 0)
+       yDelta--;
+
+    // Let's attenuate the speed
+    yDelta /= speedReducer;
+
+    IntPoint scrollPoint(0,0);
+    scrollPoint.setY(offsetY + yDelta);
+    int newOffset = scrollToward(scrollPoint);
+    if (newOffset < 0) 
+        return;
+
+    m_inAutoscroll = true;
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    select->updateListBoxSelection(!select->multiple());
+    m_inAutoscroll = false;
+}
+
+int RenderListBox::scrollToward(const IntPoint& destination)
+{
+    int rx = 0;
+    int ry = 0;
+    absolutePosition(rx, ry);
+    int offsetX = destination.x() - rx;
+    int offsetY = destination.y() - ry;
+
+    int rows = numVisibleItems();
+    int offset = m_indexOffset;
+    
+    if (offsetY < borderTop() + paddingTop() && scrollToRevealElementAtListIndex(offset - 1))
+        return offset - 1;
+    
+    if (offsetY > height() - paddingBottom() - borderBottom() && scrollToRevealElementAtListIndex(offset + rows))
+        return offset + rows - 1;
+    
+    return listIndexAtOffset(offsetX, offsetY);
+}
+
+void RenderListBox::autoscroll()
+{
+    IntPoint pos = document()->frame()->view()->windowToContents(document()->frame()->eventHandler()->currentMousePosition());
+
+    int endIndex = scrollToward(pos);
+    if (endIndex >= 0) {
+        HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+        m_inAutoscroll = true;
+
+        if (!select->multiple())
+            select->setActiveSelectionAnchorIndex(endIndex);
+
+        select->setActiveSelectionEndIndex(endIndex);
+        select->updateListBoxSelection(!select->multiple());
+        m_inAutoscroll = false;
+    }
+}
+
+void RenderListBox::stopAutoscroll()
+{
+    static_cast<HTMLSelectElement*>(node())->listBoxOnChange();
+}
+
+bool RenderListBox::scrollToRevealElementAtListIndex(int index)
+{
+    if (index < 0 || index >= numItems() || listIndexIsVisible(index))
+        return false;
+
+    int newOffset;
+    if (index < m_indexOffset)
+        newOffset = index;
+    else
+        newOffset = index - numVisibleItems() + 1;
+
+    m_indexOffset = newOffset;
+    if (m_vBar)
+        m_vBar->setValue(m_indexOffset);
+
+    return true;
+}
+
+bool RenderListBox::listIndexIsVisible(int index)
+{    
+    return index >= m_indexOffset && index < m_indexOffset + numVisibleItems();
+}
+
+bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
+{
+    return m_vBar && m_vBar->scroll(direction, granularity, multiplier);
+}
+
+void RenderListBox::valueChanged(unsigned listIndex)
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    select->setSelectedIndex(select->listToOptionIndex(listIndex));
+    select->onChange();
+}
+
+void RenderListBox::valueChanged(Scrollbar*)
+{
+    int newOffset = m_vBar->value();
+    if (newOffset != m_indexOffset) {
+        m_indexOffset = newOffset;
+        repaint();
+        // Fire the scroll DOM event.
+        EventTargetNodeCast(node())->dispatchEventForType(eventNames().scrollEvent, false, false);
+    }
+}
+
+int RenderListBox::itemHeight() const
+{
+    return style()->font().height() + rowSpacing;
+}
+
+int RenderListBox::verticalScrollbarWidth() const
+{
+    return m_vBar ? m_vBar->width() : 0;
+}
+
+// FIXME: We ignore padding in the vertical direction as far as these values are concerned, since that's
+// how the control currently paints.
+int RenderListBox::scrollWidth() const
+{
+    // There is no horizontal scrolling allowed.
+    return clientWidth();
+}
+
+int RenderListBox::scrollHeight() const
+{
+    return max(clientHeight(), listHeight());
+}
+
+int RenderListBox::scrollLeft() const
+{
+    return 0;
+}
+
+void RenderListBox::setScrollLeft(int)
+{
+}
+
+int RenderListBox::scrollTop() const
+{
+    return m_indexOffset * itemHeight();
+}
+
+void RenderListBox::setScrollTop(int newTop)
+{
+    // Determine an index and scroll to it.    
+    int index = newTop / itemHeight();
+    if (index < 0 || index >= numItems() || index == m_indexOffset)
+        return;
+    m_indexOffset = index;
+    if (m_vBar)
+        m_vBar->setValue(index);
+}
+
+IntRect RenderListBox::controlClipRect(int tx, int ty) const
+{
+    IntRect clipRect = contentBox();
+    clipRect.move(tx, ty);
+    return clipRect;
+}
+
+bool RenderListBox::isActive() const
+{
+    Page* page = document()->frame()->page();
+    return page && page->focusController()->isActive();
+}
+
+void RenderListBox::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
+{
+    IntRect scrollRect = rect;
+    scrollRect.move(width() - borderRight() - scrollbar->width(), borderTop());
+    repaintRectangle(scrollRect);
+}
+
+bool RenderListBox::isScrollable() const
+{
+    if (numVisibleItems() < numItems())
+        return true;
+    return RenderObject::isScrollable();
+}
+
+PassRefPtr<Scrollbar> RenderListBox::createScrollbar()
+{
+    RefPtr<Scrollbar> widget;
+    bool hasCustomScrollbarStyle = style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
+    if (hasCustomScrollbarStyle)
+        widget = RenderScrollbar::createCustomScrollbar(this, VerticalScrollbar, this);
+    else
+        widget = Scrollbar::createNativeScrollbar(this, VerticalScrollbar, SmallScrollbar);
+    document()->view()->addChild(widget.get());        
+    return widget.release();
+}
+
+void RenderListBox::destroyScrollbar()
+{
+    if (!m_vBar)
+        return;
+    
+    m_vBar->removeFromParent();
+    m_vBar->setClient(0);
+    m_vBar = 0;
+}
+
+void RenderListBox::setHasVerticalScrollbar(bool hasScrollbar)
+{
+    if (hasScrollbar == (m_vBar != 0))
+        return;
+
+    if (hasScrollbar)
+        m_vBar = createScrollbar();
+    else
+        destroyScrollbar();
+
+    if (m_vBar)
+        m_vBar->styleChanged();
+
+#if ENABLE(DASHBOARD_SUPPORT)
+    // Force an update since we know the scrollbars have changed things.
+    if (document()->hasDashboardRegions())
+        document()->setDashboardRegionsDirty(true);
+#endif
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderListBox.h b/WebCore/rendering/RenderListBox.h
new file mode 100644
index 0000000..ccc6847
--- /dev/null
+++ b/WebCore/rendering/RenderListBox.h
@@ -0,0 +1,132 @@
+/*
+ * This file is part of the select element renderer in WebCore.
+ *
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RenderListBox_h
+#define RenderListBox_h
+
+#include "RenderBlock.h"
+#include "ScrollbarClient.h"
+
+namespace WebCore {
+
+class HTMLSelectElement;
+
+class RenderListBox : public RenderBlock, private ScrollbarClient {
+public:
+    RenderListBox(HTMLSelectElement*);
+    ~RenderListBox();
+
+    virtual const char* renderName() const { return "RenderListBox"; }
+
+    virtual bool isListBox() const { return true; }
+
+    virtual void updateFromElement();
+
+    virtual bool canHaveChildren() const { return false; }
+
+    virtual bool hasControlClip() const { return true; }
+    virtual void paintObject(PaintInfo&, int tx, int ty);
+    virtual IntRect controlClipRect(int tx, int ty) const;
+
+    virtual bool isPointInOverflowControl(HitTestResult&, int x, int y, int tx, int ty);
+
+    virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f);
+    virtual bool isScrollable() const;
+
+    virtual void calcPrefWidths();
+    virtual int baselinePosition(bool firstLine, bool isRootLineBox) const;
+    virtual void calcHeight();
+
+    virtual void layout();
+
+    void selectionChanged();
+
+    void setOptionsChanged(bool changed) { m_optionsChanged = changed; }
+
+    int listIndexAtOffset(int x, int y);
+    IntRect itemBoundingBoxRect(int tx, int ty, int index);
+
+    bool scrollToRevealElementAtListIndex(int index);
+    bool listIndexIsVisible(int index);
+
+    virtual bool canBeProgramaticallyScrolled(bool) const { return true; }
+    virtual void autoscroll();
+    virtual void stopAutoscroll();
+
+    virtual bool shouldPanScroll() const { return true; }
+    virtual void panScroll(const IntPoint&);
+
+    int scrollToward(const IntPoint&); // Returns the new index or -1 if no scroll occurred
+
+    virtual int verticalScrollbarWidth() const;
+    virtual int scrollLeft() const;
+    virtual int scrollTop() const;
+    virtual int scrollWidth() const;
+    virtual int scrollHeight() const;
+    virtual void setScrollLeft(int);
+    virtual void setScrollTop(int);
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+private:
+    // ScrollbarClient interface.
+    virtual void valueChanged(Scrollbar*);
+    virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
+    virtual bool isActive() const;
+    virtual bool scrollbarCornerPresent() const { return false; } // We don't support resize on list boxes yet.  If we did this would have to change.
+
+    void setHasVerticalScrollbar(bool hasScrollbar);
+    PassRefPtr<Scrollbar> createScrollbar();
+    void destroyScrollbar();
+    
+    int itemHeight() const;
+    void valueChanged(unsigned listIndex);
+    int size() const;
+    int numVisibleItems() const;
+    int numItems() const;
+    int listHeight() const;
+    void paintScrollbar(PaintInfo&, int tx, int ty);
+    void paintItemForeground(PaintInfo&, int tx, int ty, int listIndex);
+    void paintItemBackground(PaintInfo&, int tx, int ty, int listIndex);
+    void scrollToRevealSelection();
+
+    bool m_optionsChanged;
+    bool m_scrollToRevealSelectionAfterLayout;
+    bool m_inAutoscroll;
+    int m_optionsWidth;
+    int m_indexOffset;
+
+    RefPtr<Scrollbar> m_vBar;
+};
+
+} // namepace WebCore
+
+#endif // RenderListBox_h
diff --git a/WebCore/rendering/RenderListItem.cpp b/WebCore/rendering/RenderListItem.cpp
new file mode 100644
index 0000000..b69612e
--- /dev/null
+++ b/WebCore/rendering/RenderListItem.cpp
@@ -0,0 +1,334 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Andrew Wellington ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderListItem.h"
+
+#include "CachedImage.h"
+#include "HTMLNames.h"
+#include "HTMLOListElement.h"
+#include "RenderListMarker.h"
+#include "RenderView.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderListItem::RenderListItem(Node* node)
+    : RenderBlock(node)
+    , m_marker(0)
+    , m_hasExplicitValue(false)
+    , m_isValueUpToDate(false)
+    , m_notInList(false)
+{
+    setInline(false);
+}
+
+void RenderListItem::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+
+    if (style()->listStyleType() != LNONE ||
+        (style()->listStyleImage() && !style()->listStyleImage()->errorOccurred())) {
+        RefPtr<RenderStyle> newStyle = RenderStyle::create();
+        // The marker always inherits from the list item, regardless of where it might end
+        // up (e.g., in some deeply nested line box). See CSS3 spec.
+        newStyle->inheritFrom(style()); 
+        if (!m_marker)
+            m_marker = new (renderArena()) RenderListMarker(this);
+        m_marker->setStyle(newStyle.release());
+    } else if (m_marker) {
+        m_marker->destroy();
+        m_marker = 0;
+    }
+}
+
+void RenderListItem::destroy()
+{    
+    if (m_marker) {
+        m_marker->destroy();
+        m_marker = 0;
+    }
+    RenderBlock::destroy();
+}
+
+static Node* enclosingList(Node* node)
+{
+    Node* parent = node->parentNode();
+    for (Node* n = parent; n; n = n->parentNode())
+        if (n->hasTagName(ulTag) || n->hasTagName(olTag))
+            return n;
+    // If there's no actual <ul> or <ol> list element, then our parent acts as
+    // our list for purposes of determining what other list items should be
+    // numbered as part of the same list.
+    return parent;
+}
+
+static RenderListItem* previousListItem(Node* list, const RenderListItem* item)
+{
+    for (Node* n = item->node()->traversePreviousNode(); n != list; n = n->traversePreviousNode()) {
+        RenderObject* o = n->renderer();
+        if (o && o->isListItem()) {
+            Node* otherList = enclosingList(n);
+            // This item is part of our current list, so it's what we're looking for.
+            if (list == otherList)
+                return static_cast<RenderListItem*>(o);
+            // We found ourself inside another list; lets skip the rest of it.
+            // Use traverseNextNode() here because the other list itself may actually
+            // be a list item itself. We need to examine it, so we do this to counteract
+            // the traversePreviousNode() that will be done by the loop.
+            if (otherList)
+                n = otherList->traverseNextNode();
+        }
+    }
+    return 0;
+}
+
+inline int RenderListItem::calcValue() const
+{
+    if (m_hasExplicitValue)
+        return m_explicitValue;
+    Node* list = enclosingList(node());
+    // FIXME: This recurses to a possible depth of the length of the list.
+    // That's not good -- we need to change this to an iterative algorithm.
+    if (RenderListItem* previousItem = previousListItem(list, this))
+        return previousItem->value() + 1;
+    if (list && list->hasTagName(olTag))
+        return static_cast<HTMLOListElement*>(list)->start();
+    return 1;
+}
+
+void RenderListItem::updateValueNow() const
+{
+    m_value = calcValue();
+    m_isValueUpToDate = true;
+}
+
+bool RenderListItem::isEmpty() const
+{
+    return lastChild() == m_marker;
+}
+
+static RenderObject* getParentOfFirstLineBox(RenderBlock* curr, RenderObject* marker)
+{
+    RenderObject* firstChild = curr->firstChild();
+    if (!firstChild)
+        return 0;
+
+    for (RenderObject* currChild = firstChild; currChild; currChild = currChild->nextSibling()) {
+        if (currChild == marker)
+            continue;
+
+        if (currChild->isInline() && (!currChild->isInlineFlow() || curr->generatesLineBoxesForInlineChild(currChild)))
+            return curr;
+
+        if (currChild->isFloating() || currChild->isPositioned())
+            continue;
+
+        if (currChild->isTable() || !currChild->isRenderBlock())
+            break;
+
+        if (curr->isListItem() && currChild->style()->htmlHacks() && currChild->element() &&
+            (currChild->element()->hasTagName(ulTag)|| currChild->element()->hasTagName(olTag)))
+            break;
+
+        RenderObject* lineBox = getParentOfFirstLineBox(static_cast<RenderBlock*>(currChild), marker);
+        if (lineBox)
+            return lineBox;
+    }
+
+    return 0;
+}
+
+void RenderListItem::updateValue()
+{
+    if (!m_hasExplicitValue) {
+        m_isValueUpToDate = false;
+        if (m_marker)
+            m_marker->setNeedsLayoutAndPrefWidthsRecalc();
+    }
+}
+
+static RenderObject* firstNonMarkerChild(RenderObject* parent)
+{
+    RenderObject* result = parent->firstChild();
+    while (result && result->isListMarker())
+        result = result->nextSibling();
+    return result;
+}
+
+void RenderListItem::updateMarkerLocation()
+{
+    // Sanity check the location of our marker.
+    if (m_marker) {
+        RenderObject* markerPar = m_marker->parent();
+        RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
+        if (!lineBoxParent) {
+            // If the marker is currently contained inside an anonymous box,
+            // then we are the only item in that anonymous box (since no line box
+            // parent was found).  It's ok to just leave the marker where it is
+            // in this case.
+            if (markerPar && markerPar->isAnonymousBlock())
+                lineBoxParent = markerPar;
+            else
+                lineBoxParent = this;
+        }
+
+        if (markerPar != lineBoxParent || m_marker->prefWidthsDirty()) {
+            // Removing and adding the marker can trigger repainting in
+            // containers other than ourselves, so we need to disable LayoutState.
+            view()->disableLayoutState();
+            updateFirstLetter();
+            m_marker->remove();
+            if (!lineBoxParent)
+                lineBoxParent = this;
+            lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
+            if (m_marker->prefWidthsDirty())
+                m_marker->calcPrefWidths();
+            view()->enableLayoutState();
+        }
+    }
+}
+
+void RenderListItem::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+    
+    updateMarkerLocation();
+
+    RenderBlock::calcPrefWidths();
+}
+
+void RenderListItem::layout()
+{
+    ASSERT(needsLayout()); 
+
+    updateMarkerLocation();    
+    RenderBlock::layout();
+}
+
+void RenderListItem::positionListMarker()
+{
+    if (m_marker && !m_marker->isInside() && m_marker->inlineBoxWrapper()) {
+        int markerOldX = m_marker->xPos();
+        int yOffset = 0;
+        int xOffset = 0;
+        for (RenderObject* o = m_marker->parent(); o != this; o = o->parent()) {
+            yOffset += o->yPos();
+            xOffset += o->xPos();
+        }
+
+        bool adjustOverflow = false;
+        int markerXPos;
+        RootInlineBox* root = m_marker->inlineBoxWrapper()->root();
+
+        if (style()->direction() == LTR) {
+            int leftLineOffset = leftRelOffset(yOffset, leftOffset(yOffset));
+            markerXPos = leftLineOffset - xOffset - paddingLeft() - borderLeft() + m_marker->marginLeft();
+            m_marker->inlineBoxWrapper()->adjustPosition(markerXPos - markerOldX, 0);
+            if (markerXPos < root->leftOverflow()) {
+                root->setHorizontalOverflowPositions(markerXPos, root->rightOverflow());
+                adjustOverflow = true;
+            }
+        } else {
+            int rightLineOffset = rightRelOffset(yOffset, rightOffset(yOffset));
+            markerXPos = rightLineOffset - xOffset + paddingRight() + borderRight() + m_marker->marginLeft();
+            m_marker->inlineBoxWrapper()->adjustPosition(markerXPos - markerOldX, 0);
+            if (markerXPos + m_marker->width() > root->rightOverflow()) {
+                root->setHorizontalOverflowPositions(root->leftOverflow(), markerXPos + m_marker->width());
+                adjustOverflow = true;
+            }
+        }
+
+        if (adjustOverflow) {
+            IntRect markerRect(markerXPos + xOffset, yOffset, m_marker->width(), m_marker->height());
+            RenderObject* o = m_marker;
+            do {
+                o = o->parent();
+                if (o->isRenderBlock())
+                    static_cast<RenderBlock*>(o)->addVisualOverflow(markerRect);
+                markerRect.move(-o->xPos(), -o->yPos());
+            } while (o != this);
+        }
+    }
+}
+
+void RenderListItem::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (!m_height)
+        return;
+
+    RenderBlock::paint(paintInfo, tx, ty);
+}
+
+const String& RenderListItem::markerText() const
+{
+    if (m_marker)
+        return m_marker->text();
+    static String staticNullString;
+    return staticNullString;
+}
+
+void RenderListItem::explicitValueChanged()
+{
+    if (m_marker)
+        m_marker->setNeedsLayoutAndPrefWidthsRecalc();
+    Node* listNode = enclosingList(node());
+    RenderObject* listRenderer = 0;
+    if (listNode)
+        listRenderer = listNode->renderer();
+    for (RenderObject* r = this; r; r = r->nextInPreOrder(listRenderer))
+        if (r->isListItem()) {
+            RenderListItem* item = static_cast<RenderListItem*>(r);
+            if (!item->m_hasExplicitValue) {
+                item->m_isValueUpToDate = false;
+                if (RenderListMarker* marker = item->m_marker)
+                    marker->setNeedsLayoutAndPrefWidthsRecalc();
+            }
+        }
+}
+
+void RenderListItem::setExplicitValue(int value)
+{
+    if (m_hasExplicitValue && m_explicitValue == value)
+        return;
+    m_explicitValue = value;
+    m_value = value;
+    m_hasExplicitValue = true;
+    explicitValueChanged();
+}
+
+void RenderListItem::clearExplicitValue()
+{
+    if (!m_hasExplicitValue)
+        return;
+    m_hasExplicitValue = false;
+    m_isValueUpToDate = false;
+    explicitValueChanged();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderListItem.h b/WebCore/rendering/RenderListItem.h
new file mode 100644
index 0000000..d4dd675
--- /dev/null
+++ b/WebCore/rendering/RenderListItem.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderListItem_h
+#define RenderListItem_h
+
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+class RenderListMarker;
+
+class RenderListItem : public RenderBlock {
+public:
+    RenderListItem(Node*);
+
+    virtual const char* renderName() const { return "RenderListItem"; }
+
+    virtual bool isListItem() const { return true; }
+    
+    virtual void destroy();
+
+    int value() const { if (!m_isValueUpToDate) updateValueNow(); return m_value; }
+    void updateValue();
+
+    bool hasExplicitValue() const { return m_hasExplicitValue; }
+    int explicitValue() const { return m_explicitValue; }
+    void setExplicitValue(int value);
+    void clearExplicitValue();
+
+    virtual bool isEmpty() const;
+    virtual void paint(PaintInfo&, int tx, int ty);
+
+    virtual void layout();
+    virtual void calcPrefWidths();
+
+    virtual void positionListMarker();
+
+    void setNotInList(bool notInList) { m_notInList = notInList; }
+    bool notInList() const { return m_notInList; }
+
+    const String& markerText() const;
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+private:
+    void updateMarkerLocation();
+    inline int calcValue() const;
+    void updateValueNow() const;
+    void explicitValueChanged();
+
+    RenderListMarker* m_marker;
+    int m_explicitValue;
+    mutable int m_value;
+
+    bool m_hasExplicitValue : 1;
+    mutable bool m_isValueUpToDate : 1;
+    bool m_notInList : 1;
+};
+
+} // namespace WebCore
+
+#endif // RenderListItem_h
diff --git a/WebCore/rendering/RenderListMarker.cpp b/WebCore/rendering/RenderListMarker.cpp
new file mode 100644
index 0000000..b2937b9
--- /dev/null
+++ b/WebCore/rendering/RenderListMarker.cpp
@@ -0,0 +1,906 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Andrew Wellington ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderListMarker.h"
+
+#include "CachedImage.h"
+#include "CharacterNames.h"
+#include "Document.h"
+#include "GraphicsContext.h"
+#include "ListMarkerBox.h"
+#include "RenderLayer.h"
+#include "RenderListItem.h"
+#include "RenderView.h"
+
+using namespace std;
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+const int cMarkerPadding = 7;
+
+static String toRoman(int number, bool upper)
+{
+    // FIXME: CSS3 describes how to make this work for much larger numbers,
+    // using overbars and special characters. It also specifies the characters
+    // in the range U+2160 to U+217F instead of standard ASCII ones.
+    if (number < 1 || number > 3999)
+        return String::number(number);
+
+    const int lettersSize = 12; // big enough for three each of I, X, C, and M
+    UChar letters[lettersSize];
+
+    int length = 0;
+    const UChar ldigits[] = { 'i', 'v', 'x', 'l', 'c', 'd', 'm' };
+    const UChar udigits[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
+    const UChar* digits = upper ? udigits : ldigits;
+    int d = 0;
+    do {
+        int num = number % 10;
+        if (num % 5 < 4)
+            for (int i = num % 5; i > 0; i--)
+                letters[lettersSize - ++length] = digits[d];
+        if (num >= 4 && num <= 8)
+            letters[lettersSize - ++length] = digits[d + 1];
+        if (num == 9)
+            letters[lettersSize - ++length] = digits[d + 2];
+        if (num % 5 == 4)
+            letters[lettersSize - ++length] = digits[d];
+        number /= 10;
+        d += 2;
+    } while (number);
+
+    ASSERT(length <= lettersSize);
+    return String(&letters[lettersSize - length], length);
+}
+
+static String toAlphabetic(int number, const UChar* alphabet, int alphabetSize)
+{
+    ASSERT(alphabetSize >= 10);
+
+    if (number < 1)
+        return String::number(number);
+
+    const int lettersSize = 10; // big enough for a 32-bit int, with a 10-letter alphabet
+    UChar letters[lettersSize];
+
+    --number;
+    letters[lettersSize - 1] = alphabet[number % alphabetSize];
+    int length = 1;
+    while ((number /= alphabetSize) > 0)
+        letters[lettersSize - ++length] = alphabet[number % alphabetSize - 1];
+
+    ASSERT(length <= lettersSize);
+    return String(&letters[lettersSize - length], length);
+}
+
+static int toHebrewUnder1000(int number, UChar letters[5])
+{
+    // FIXME: CSS3 mentions various refinements not implemented here.
+    // FIXME: Should take a look at Mozilla's HebrewToText function (in nsBulletFrame).
+    ASSERT(number >= 0 && number < 1000);
+    int length = 0;
+    int fourHundreds = number / 400;
+    for (int i = 0; i < fourHundreds; i++)
+        letters[length++] = 1511 + 3;
+    number %= 400;
+    if (number / 100)
+        letters[length++] = 1511 + (number / 100) - 1;
+    number %= 100;
+    if (number == 15 || number == 16) {
+        letters[length++] = 1487 + 9;
+        letters[length++] = 1487 + number - 9;
+    } else {
+        if (int tens = number / 10) {
+            static const UChar hebrewTens[9] = { 1497, 1499, 1500, 1502, 1504, 1505, 1506, 1508, 1510 };
+            letters[length++] = hebrewTens[tens - 1];
+        }
+        if (int ones = number % 10)
+            letters[length++] = 1487 + ones;
+    }
+    ASSERT(length <= 5);
+    return length;
+}
+
+static String toHebrew(int number)
+{
+    // FIXME: CSS3 mentions ways to make this work for much larger numbers.
+    if (number < 0 || number > 999999)
+        return String::number(number);
+
+    if (number == 0) {
+        static const UChar hebrewZero[3] = { 0x05D0, 0x05E4, 0x05E1 };
+        return String(hebrewZero, 3);
+    }
+
+    const int lettersSize = 11; // big enough for two 5-digit sequences plus a quote mark between
+    UChar letters[lettersSize];
+
+    int length;
+    if (number < 1000)
+        length = 0;
+    else {
+        length = toHebrewUnder1000(number / 1000, letters);
+        letters[length++] = '\'';
+        number = number % 1000;
+    }
+    length += toHebrewUnder1000(number, letters + length);
+
+    ASSERT(length <= lettersSize);
+    return String(letters, length);
+}
+
+static int toArmenianUnder10000(int number, bool upper, bool addCircumflex, UChar letters[9])
+{
+    ASSERT(number >= 0 && number < 10000);
+    int length = 0;
+
+    int lowerOffset = upper ? 0 : 0x0030;
+
+    if (int thousands = number / 1000)
+        if (thousands == 7) {
+            letters[length++] = 0x0548 + lowerOffset;
+            letters[length++] = 0x0552 + lowerOffset;
+            if (addCircumflex)
+                letters[length++] = 0x0302;
+        } else {
+            letters[length++] = (0x054C - 1 + lowerOffset) + thousands;
+            if (addCircumflex)
+                letters[length++] = 0x0302;
+        }
+
+    if (int hundreds = (number / 100) % 10) {
+        letters[length++] = (0x0543 - 1 + lowerOffset) + hundreds;
+        if (addCircumflex)
+            letters[length++] = 0x0302;
+    }
+
+    if (int tens = (number / 10) % 10) {
+        letters[length++] = (0x053A - 1 + lowerOffset) + tens;
+        if (addCircumflex)
+            letters[length++] = 0x0302;
+    }
+
+    if (int ones = number % 10) {
+        letters[length++] = (0x531 - 1 + lowerOffset) + ones;
+        if (addCircumflex)
+            letters[length++] = 0x0302;
+    }
+
+    return length;
+}
+
+static String toArmenian(int number, bool upper)
+{
+    if (number < 1 || number > 99999999)
+        return String::number(number);
+
+    const int lettersSize = 18; // twice what toArmenianUnder10000 needs
+    UChar letters[lettersSize];
+
+    int length = toArmenianUnder10000(number / 10000, upper, true, letters);
+    length += toArmenianUnder10000(number % 10000, upper, false, letters + length);
+
+    ASSERT(length <= lettersSize);
+    return String(letters, length);
+}
+
+static String toGeorgian(int number)
+{
+    if (number < 1 || number > 19999)
+        return String::number(number);
+
+    const int lettersSize = 5;
+    UChar letters[lettersSize];
+
+    int length = 0;
+
+    if (number > 9999)
+        letters[length++] = 0x10F5;
+
+    if (int thousands = (number / 1000) % 10) {
+        static const UChar georgianThousands[9] = {
+            0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10F4, 0x10EF, 0x10F0
+        };
+        letters[length++] = georgianThousands[thousands - 1];
+    }
+
+    if (int hundreds = (number / 100) % 10) {
+        static const UChar georgianHundreds[9] = {
+            0x10E0, 0x10E1, 0x10E2, 0x10F3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8
+        };
+        letters[length++] = georgianHundreds[hundreds - 1];
+    }
+
+    if (int tens = (number / 10) % 10) {
+        static const UChar georgianTens[9] = {
+            0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10F2, 0x10DD, 0x10DE, 0x10DF
+        };
+        letters[length++] = georgianTens[tens - 1];
+    }
+
+    if (int ones = number % 10) {
+        static const UChar georgianOnes[9] = {
+            0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10F1, 0x10D7
+        };
+        letters[length++] = georgianOnes[ones - 1];
+    }
+
+    ASSERT(length <= lettersSize);
+    return String(letters, length);
+}
+
+// The table uses the order from the CSS3 specification:
+// first 3 group markers, then 3 digit markers, then ten digits.
+static String toCJKIdeographic(int number, const UChar table[16])
+{
+    if (number < 0)
+        return String::number(number);
+
+    enum AbstractCJKChar {
+        noChar,
+        secondGroupMarker, thirdGroupMarker, fourthGroupMarker,
+        secondDigitMarker, thirdDigitMarker, fourthDigitMarker,
+        digit0, digit1, digit2, digit3, digit4,
+        digit5, digit6, digit7, digit8, digit9
+    };
+
+    if (number == 0)
+        return String(&table[digit0 - 1], 1);
+
+    const int groupLength = 8; // 4 digits, 3 digit markers, and a group marker
+    const int bufferLength = 4 * groupLength;
+    AbstractCJKChar buffer[bufferLength] = { noChar };
+
+    for (int i = 0; i < 4; ++i) {
+        int groupValue = number % 10000;
+        number /= 10000;
+
+        // Process least-significant group first, but put it in the buffer last.
+        AbstractCJKChar* group = &buffer[(3 - i) * groupLength];
+
+        if (groupValue && i)
+            group[7] = static_cast<AbstractCJKChar>(secondGroupMarker - 1 + i);
+
+        // Put in the four digits and digit markers for any non-zero digits.
+        group[6] = static_cast<AbstractCJKChar>(digit0 + (groupValue % 10));
+        if (number != 0 || groupValue > 9) {
+            int digitValue = ((groupValue / 10) % 10);
+            group[4] = static_cast<AbstractCJKChar>(digit0 + digitValue);
+            if (digitValue)
+                group[5] = secondDigitMarker;
+        }
+        if (number != 0 || groupValue > 99) {
+            int digitValue = ((groupValue / 100) % 10);
+            group[2] = static_cast<AbstractCJKChar>(digit0 + digitValue);
+            if (digitValue)
+                group[3] = thirdDigitMarker;
+        }
+        if (number != 0 || groupValue > 999) {
+            int digitValue = groupValue / 1000;
+            group[0] = static_cast<AbstractCJKChar>(digit0 + digitValue);
+            if (digitValue)
+                group[1] = fourthDigitMarker;
+        }
+
+        // Remove the tens digit, but leave the marker, for any group that has
+        // a value of less than 20.
+        if (groupValue < 20) {
+            ASSERT(group[4] == noChar || group[4] == digit0 || group[4] == digit1);
+            group[4] = noChar;
+        }
+
+        if (number == 0)
+            break;
+    }
+
+    // Convert into characters, omitting consecutive runs of digit0 and
+    // any trailing digit0.
+    int length = 0;
+    UChar characters[bufferLength];
+    AbstractCJKChar last = noChar;
+    for (int i = 0; i < bufferLength; ++i) {
+        AbstractCJKChar a = buffer[i];
+        if (a != noChar) {
+            if (a != digit0 || last != digit0)
+                characters[length++] = table[a - 1];
+            last = a;
+        }
+    }
+    if (last == digit0)
+        --length;
+
+    return String(characters, length);
+}
+
+String listMarkerText(EListStyleType type, int value)
+{
+    switch (type) {
+        case LNONE:
+            return "";
+
+        // We use the same characters for text security.
+        // See RenderText::setInternalString.
+        case CIRCLE:
+            return String(&whiteBullet, 1);
+        case DISC:
+            return String(&bullet, 1);
+        case SQUARE:
+            // The CSS 2.1 test suite uses U+25EE BLACK MEDIUM SMALL SQUARE
+            // instead, but I think this looks better.
+            return String(&blackSquare, 1);
+
+        case LDECIMAL:
+            return String::number(value);
+        case DECIMAL_LEADING_ZERO:
+            if (value < -9 || value > 9)
+                return String::number(value);
+            if (value < 0)
+                return "-0" + String::number(-value); // -01 to -09
+            return "0" + String::number(value); // 00 to 09
+
+        case LOWER_ALPHA:
+        case LOWER_LATIN: {
+            static const UChar lowerLatinAlphabet[26] = {
+                'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+                'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
+            };
+            return toAlphabetic(value, lowerLatinAlphabet, 26);
+        }
+        case UPPER_ALPHA:
+        case UPPER_LATIN: {
+            static const UChar upperLatinAlphabet[26] = {
+                'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+                'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
+            };
+            return toAlphabetic(value, upperLatinAlphabet, 26);
+        }
+        case LOWER_GREEK: {
+            static const UChar lowerGreekAlphabet[24] = {
+                0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
+                0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0,
+                0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9
+            };
+            return toAlphabetic(value, lowerGreekAlphabet, 24);
+        }
+
+        case HIRAGANA: {
+            // FIXME: This table comes from the CSS3 draft, and is probably
+            // incorrect, given the comments in that draft.
+            static const UChar hiraganaAlphabet[48] = {
+                0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D, 0x304F,
+                0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D, 0x305F,
+                0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B, 0x306C, 0x306D,
+                0x306E, 0x306F, 0x3072, 0x3075, 0x3078, 0x307B, 0x307E, 0x307F,
+                0x3080, 0x3081, 0x3082, 0x3084, 0x3086, 0x3088, 0x3089, 0x308A,
+                0x308B, 0x308C, 0x308D, 0x308F, 0x3090, 0x3091, 0x3092, 0x3093
+            };
+            return toAlphabetic(value, hiraganaAlphabet, 48);
+        }
+        case HIRAGANA_IROHA: {
+            // FIXME: This table comes from the CSS3 draft, and is probably
+            // incorrect, given the comments in that draft.
+            static const UChar hiraganaIrohaAlphabet[47] = {
+                0x3044, 0x308D, 0x306F, 0x306B, 0x307B, 0x3078, 0x3068, 0x3061,
+                0x308A, 0x306C, 0x308B, 0x3092, 0x308F, 0x304B, 0x3088, 0x305F,
+                0x308C, 0x305D, 0x3064, 0x306D, 0x306A, 0x3089, 0x3080, 0x3046,
+                0x3090, 0x306E, 0x304A, 0x304F, 0x3084, 0x307E, 0x3051, 0x3075,
+                0x3053, 0x3048, 0x3066, 0x3042, 0x3055, 0x304D, 0x3086, 0x3081,
+                0x307F, 0x3057, 0x3091, 0x3072, 0x3082, 0x305B, 0x3059
+            };
+            return toAlphabetic(value, hiraganaIrohaAlphabet, 47);
+        }
+        case KATAKANA: {
+            // FIXME: This table comes from the CSS3 draft, and is probably
+            // incorrect, given the comments in that draft.
+            static const UChar katakanaAlphabet[48] = {
+                0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, 0x30AF,
+                0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, 0x30BF,
+                0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, 0x30CD,
+                0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, 0x30DF,
+                0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA,
+                0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F0, 0x30F1, 0x30F2, 0x30F3
+            };
+            return toAlphabetic(value, katakanaAlphabet, 48);
+        }
+        case KATAKANA_IROHA: {
+            // FIXME: This table comes from the CSS3 draft, and is probably
+            // incorrect, given the comments in that draft.
+            static const UChar katakanaIrohaAlphabet[47] = {
+                0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, 0x30D8, 0x30C8, 0x30C1,
+                0x30EA, 0x30CC, 0x30EB, 0x30F2, 0x30EF, 0x30AB, 0x30E8, 0x30BF,
+                0x30EC, 0x30BD, 0x30C4, 0x30CD, 0x30CA, 0x30E9, 0x30E0, 0x30A6,
+                0x30F0, 0x30CE, 0x30AA, 0x30AF, 0x30E4, 0x30DE, 0x30B1, 0x30D5,
+                0x30B3, 0x30A8, 0x30C6, 0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1,
+                0x30DF, 0x30B7, 0x30F1, 0x30D2, 0x30E2, 0x30BB, 0x30B9
+            };
+            return toAlphabetic(value, katakanaIrohaAlphabet, 47);
+        }
+
+        case CJK_IDEOGRAPHIC: {
+            static const UChar traditionalChineseInformalTable[16] = {
+                0x842C, 0x5104, 0x5146,
+                0x5341, 0x767E, 0x5343,
+                0x96F6, 0x4E00, 0x4E8C, 0x4E09, 0x56DB,
+                0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D
+            };
+            return toCJKIdeographic(value, traditionalChineseInformalTable);
+        }
+
+        case LOWER_ROMAN:
+            return toRoman(value, false);
+        case UPPER_ROMAN:
+            return toRoman(value, true);
+
+        case ARMENIAN:
+            // CSS3 says "armenian" means "lower-armenian".
+            // But the CSS2.1 test suite contains uppercase test results for "armenian",
+            // so we'll match the test suite.
+            return toArmenian(value, true);
+        case GEORGIAN:
+            return toGeorgian(value);
+        case HEBREW:
+            return toHebrew(value);
+    }
+
+    ASSERT_NOT_REACHED();
+    return "";
+}
+
+RenderListMarker::RenderListMarker(RenderListItem* item)
+    : RenderBox(item->document())
+    , m_listItem(item)
+    , m_selectionState(SelectionNone)
+{
+    // init RenderObject attributes
+    setInline(true);   // our object is Inline
+    setReplaced(true); // pretend to be replaced
+}
+
+RenderListMarker::~RenderListMarker()
+{
+    if (m_image)
+        m_image->removeClient(this);
+}
+
+void RenderListMarker::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+{
+    if (style() && (newStyle->listStylePosition() != style()->listStylePosition() || newStyle->listStyleType() != style()->listStyleType()))
+        setNeedsLayoutAndPrefWidthsRecalc();
+    
+    RenderBox::styleWillChange(diff, newStyle);
+}
+
+void RenderListMarker::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBox::styleDidChange(diff, oldStyle);
+
+    if (m_image != style()->listStyleImage()) {
+        if (m_image)
+            m_image->removeClient(this);
+        m_image = style()->listStyleImage();
+        if (m_image)
+            m_image->addClient(this);
+    }
+}
+
+InlineBox* RenderListMarker::createInlineBox(bool, bool isRootLineBox, bool)
+{
+    ASSERT(!isRootLineBox);
+    ListMarkerBox* box = new (renderArena()) ListMarkerBox(this);
+    m_inlineBoxWrapper = box;
+    return box;
+}
+
+bool RenderListMarker::isImage() const
+{
+    return m_image && !m_image->errorOccurred();
+}
+
+void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (paintInfo.phase != PaintPhaseForeground)
+        return;
+    
+    if (style()->visibility() != VISIBLE)
+        return;
+
+    IntRect marker = getRelativeMarkerRect();
+    marker.move(tx, ty);
+
+    IntRect box(tx + m_x, ty + m_y, m_width, m_height);
+
+    if (box.y() > paintInfo.rect.bottom() || box.y() + box.height() < paintInfo.rect.y())
+        return;
+
+    if (hasBoxDecorations()) 
+        paintBoxDecorations(paintInfo, box.x(), box.y());
+
+    GraphicsContext* context = paintInfo.context;
+    context->setFont(style()->font());
+
+    if (isImage()) {
+#if PLATFORM(MAC)
+        if (style()->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
+            paintCustomHighlight(tx, ty, style()->highlight(), true);
+#endif
+        context->drawImage(m_image->image(this, marker.size()), marker.location());
+        if (selectionState() != SelectionNone)
+            context->fillRect(selectionRect(), selectionBackgroundColor());
+        return;
+    }
+
+#if PLATFORM(MAC)
+    // FIXME: paint gap between marker and list item proper
+    if (style()->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
+        paintCustomHighlight(tx, ty, style()->highlight(), true);
+#endif
+
+    if (selectionState() != SelectionNone)
+        context->fillRect(selectionRect(), selectionBackgroundColor());
+
+    const Color color(style()->color());
+    context->setStrokeColor(color);
+    context->setStrokeStyle(SolidStroke);
+    context->setStrokeThickness(1.0f);
+    context->setFillColor(color);
+
+    switch (style()->listStyleType()) {
+        case DISC:
+            context->drawEllipse(marker);
+            return;
+        case CIRCLE:
+            context->setFillColor(Color::transparent);
+            context->drawEllipse(marker);
+            return;
+        case SQUARE:
+            context->drawRect(marker);
+            return;
+        case LNONE:
+            return;
+        case ARMENIAN:
+        case CJK_IDEOGRAPHIC:
+        case DECIMAL_LEADING_ZERO:
+        case GEORGIAN:
+        case HEBREW:
+        case HIRAGANA:
+        case HIRAGANA_IROHA:
+        case KATAKANA:
+        case KATAKANA_IROHA:
+        case LDECIMAL:
+        case LOWER_ALPHA:
+        case LOWER_GREEK:
+        case LOWER_LATIN:
+        case LOWER_ROMAN:
+        case UPPER_ALPHA:
+        case UPPER_LATIN:
+        case UPPER_ROMAN:
+            break;
+    }
+    if (m_text.isEmpty())
+        return;
+
+    TextRun textRun(m_text);
+
+    // Text is not arbitrary. We can judge whether it's RTL from the first character,
+    // and we only need to handle the direction RightToLeft for now.
+    bool textNeedsReversing = direction(m_text[0]) == RightToLeft;
+    Vector<UChar> reversedText;
+    if (textNeedsReversing) {
+        int length = m_text.length();
+        reversedText.grow(length);
+        for (int i = 0; i < length; ++i)
+            reversedText[length - i - 1] = m_text[i];
+        textRun = TextRun(reversedText.data(), length);
+    }
+
+    const Font& font = style()->font();
+    if (style()->direction() == LTR) {
+        int width = font.width(textRun);
+        context->drawText(textRun, marker.location());
+        const UChar periodSpace[2] = { '.', ' ' };
+        context->drawText(TextRun(periodSpace, 2), marker.location() + IntSize(width, 0));
+    } else {
+        const UChar spacePeriod[2] = { ' ', '.' };
+        TextRun spacePeriodRun(spacePeriod, 2);
+        int width = font.width(spacePeriodRun);
+        context->drawText(spacePeriodRun, marker.location());
+        context->drawText(textRun, marker.location() + IntSize(width, 0));
+    }
+}
+
+void RenderListMarker::layout()
+{
+    ASSERT(needsLayout());
+    ASSERT(!prefWidthsDirty());
+
+    if (isImage()) {
+        m_width = m_image->imageSize(this, style()->effectiveZoom()).width();
+        m_height = m_image->imageSize(this, style()->effectiveZoom()).height();
+    } else {
+        m_width = minPrefWidth();
+        m_height = style()->font().height();
+    }
+
+    m_marginLeft = m_marginRight = 0;
+
+    Length leftMargin = style()->marginLeft();
+    Length rightMargin = style()->marginRight();
+    if (leftMargin.isFixed())
+        m_marginLeft = leftMargin.value();
+    if (rightMargin.isFixed())
+        m_marginRight = rightMargin.value();
+
+    setNeedsLayout(false);
+}
+
+void RenderListMarker::imageChanged(WrappedImagePtr o)
+{
+    // A list marker can't have a background or border image, so no need to call the base class method.
+    if (o != m_image->data())
+        return;
+
+    if (m_width != m_image->imageSize(this, style()->effectiveZoom()).width() || m_height != m_image->imageSize(this, style()->effectiveZoom()).height() || m_image->errorOccurred())
+        setNeedsLayoutAndPrefWidthsRecalc();
+    else
+        repaint();
+}
+
+void RenderListMarker::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+
+    m_text = "";
+
+    const Font& font = style()->font();
+
+    if (isImage()) {
+        // FIXME: This is a somewhat arbitrary width.  Generated images for markers really won't become particularly useful
+        // until we support the CSS3 marker pseudoclass to allow control over the width and height of the marker box.
+        int bulletWidth = font.ascent() / 2;
+        m_image->setImageContainerSize(IntSize(bulletWidth, bulletWidth));
+        m_minPrefWidth = m_maxPrefWidth = m_image->imageSize(this, style()->effectiveZoom()).width();
+        setPrefWidthsDirty(false);
+        updateMargins();
+        return;
+    }
+
+    int width = 0;
+    EListStyleType type = style()->listStyleType();
+    switch (type) {
+        case LNONE:
+            break;
+        case CIRCLE:
+        case DISC:
+        case SQUARE:
+            m_text = listMarkerText(type, 0); // value is ignored for these types
+            width = (font.ascent() * 2 / 3 + 1) / 2 + 2;
+            break;
+        case ARMENIAN:
+        case CJK_IDEOGRAPHIC:
+        case DECIMAL_LEADING_ZERO:
+        case GEORGIAN:
+        case HEBREW:
+        case HIRAGANA:
+        case HIRAGANA_IROHA:
+        case KATAKANA:
+        case KATAKANA_IROHA:
+        case LDECIMAL:
+        case LOWER_ALPHA:
+        case LOWER_GREEK:
+        case LOWER_LATIN:
+        case LOWER_ROMAN:
+        case UPPER_ALPHA:
+        case UPPER_LATIN:
+        case UPPER_ROMAN:
+            m_text = listMarkerText(type, m_listItem->value());
+            if (m_text.isEmpty())
+                width = 0;
+            else {
+                int itemWidth = font.width(m_text);
+                const UChar periodSpace[2] = { '.', ' ' };
+                int periodSpaceWidth = font.width(TextRun(periodSpace, 2));
+                width = itemWidth + periodSpaceWidth;
+            }
+            break;
+    }
+
+    m_minPrefWidth = width;
+    m_maxPrefWidth = width;
+
+    setPrefWidthsDirty(false);
+    
+    updateMargins();
+}
+
+void RenderListMarker::updateMargins()
+{
+    const Font& font = style()->font();
+
+    int marginLeft = 0;
+    int marginRight = 0;
+
+    if (isInside()) {
+        if (isImage()) {
+            if (style()->direction() == LTR)
+                marginRight = cMarkerPadding;
+            else
+                marginLeft = cMarkerPadding;
+        } else switch (style()->listStyleType()) {
+            case DISC:
+            case CIRCLE:
+            case SQUARE:
+                if (style()->direction() == LTR) {
+                    marginLeft = -1;
+                    marginRight = font.ascent() - minPrefWidth() + 1;
+                } else {
+                    marginLeft = font.ascent() - minPrefWidth() + 1;
+                    marginRight = -1;
+                }
+                break;
+            default:
+                break;
+        }
+    } else {
+        if (style()->direction() == LTR) {
+            if (isImage())
+                marginLeft = -minPrefWidth() - cMarkerPadding;
+            else {
+                int offset = font.ascent() * 2 / 3;
+                switch (style()->listStyleType()) {
+                    case DISC:
+                    case CIRCLE:
+                    case SQUARE:
+                        marginLeft = -offset - cMarkerPadding - 1;
+                        break;
+                    case LNONE:
+                        break;
+                    default:
+                        marginLeft = m_text.isEmpty() ? 0 : -minPrefWidth() - offset / 2;
+                }
+            }
+        } else {
+            if (isImage())
+                marginLeft = cMarkerPadding;
+            else {
+                int offset = font.ascent() * 2 / 3;
+                switch (style()->listStyleType()) {
+                    case DISC:
+                    case CIRCLE:
+                    case SQUARE:
+                        marginLeft = offset + cMarkerPadding + 1 - minPrefWidth();
+                        break;
+                    case LNONE:
+                        break;
+                    default:
+                        marginLeft = m_text.isEmpty() ? 0 : offset / 2;
+                }
+            }
+        }
+        marginRight = -marginLeft - minPrefWidth();
+    }
+
+    style()->setMarginLeft(Length(marginLeft, Fixed));
+    style()->setMarginRight(Length(marginRight, Fixed));
+}
+
+int RenderListMarker::lineHeight(bool, bool) const
+{
+    if (!isImage())
+        return m_listItem->lineHeight(false, true);
+    return height();
+}
+
+int RenderListMarker::baselinePosition(bool, bool) const
+{
+    if (!isImage()) {
+        const Font& font = style()->font();
+        return font.ascent() + (lineHeight(false) - font.height())/2;
+    }
+    return height();
+}
+
+bool RenderListMarker::isInside() const
+{
+    return m_listItem->notInList() || style()->listStylePosition() == INSIDE;
+}
+
+IntRect RenderListMarker::getRelativeMarkerRect()
+{
+    if (isImage())
+        return IntRect(m_x, m_y, m_image->imageSize(this, style()->effectiveZoom()).width(), m_image->imageSize(this, style()->effectiveZoom()).height());
+
+    switch (style()->listStyleType()) {
+        case DISC:
+        case CIRCLE:
+        case SQUARE: {
+            // FIXME: Are these particular rounding rules necessary?
+            const Font& font = style()->font();
+            int ascent = font.ascent();
+            int bulletWidth = (ascent * 2 / 3 + 1) / 2;
+            return IntRect(m_x + 1, m_y + 3 * (ascent - ascent * 2 / 3) / 2, bulletWidth, bulletWidth);
+        }
+        case LNONE:
+            return IntRect();
+        case ARMENIAN:
+        case CJK_IDEOGRAPHIC:
+        case DECIMAL_LEADING_ZERO:
+        case GEORGIAN:
+        case HEBREW:
+        case HIRAGANA:
+        case HIRAGANA_IROHA:
+        case KATAKANA:
+        case KATAKANA_IROHA:
+        case LDECIMAL:
+        case LOWER_ALPHA:
+        case LOWER_GREEK:
+        case LOWER_LATIN:
+        case LOWER_ROMAN:
+        case UPPER_ALPHA:
+        case UPPER_LATIN:
+        case UPPER_ROMAN:
+            if (m_text.isEmpty())
+                return IntRect();
+            const Font& font = style()->font();
+            int itemWidth = font.width(m_text);
+            const UChar periodSpace[2] = { '.', ' ' };
+            int periodSpaceWidth = font.width(TextRun(periodSpace, 2));
+            return IntRect(m_x, m_y + font.ascent(), itemWidth + periodSpaceWidth, font.height());
+    }
+
+    return IntRect();
+}
+
+void RenderListMarker::setSelectionState(SelectionState state)
+{
+    m_selectionState = state;
+    if (InlineBox* box = inlineBoxWrapper())
+        if (RootInlineBox* root = box->root())
+            root->setHasSelectedChildren(state != SelectionNone);
+    containingBlock()->setSelectionState(state);
+}
+
+IntRect RenderListMarker::selectionRect(bool clipToVisibleContent)
+{
+    ASSERT(!needsLayout());
+
+    if (selectionState() == SelectionNone || !inlineBoxWrapper())
+        return IntRect();
+
+    RootInlineBox* root = inlineBoxWrapper()->root();
+    IntRect rect(0, root->selectionTop() - yPos(), width(), root->selectionHeight());
+            
+    if (clipToVisibleContent)
+        computeAbsoluteRepaintRect(rect);
+    else {
+        int absx, absy;
+        absolutePosition(absx, absy);
+        rect.move(absx, absy);
+    }
+    
+    return rect;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderListMarker.h b/WebCore/rendering/RenderListMarker.h
new file mode 100644
index 0000000..3c5224c
--- /dev/null
+++ b/WebCore/rendering/RenderListMarker.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderListMarker_h
+#define RenderListMarker_h
+
+#include "RenderBox.h"
+
+namespace WebCore {
+
+class RenderListItem;
+
+String listMarkerText(EListStyleType, int value);
+
+// Used to render the list item's marker.
+// The RenderListMarker always has to be a child of a RenderListItem.
+class RenderListMarker : public RenderBox {
+public:
+    RenderListMarker(RenderListItem*);
+    ~RenderListMarker();
+
+    virtual const char* renderName() const { return "RenderListMarker"; }
+
+    virtual bool isListMarker() const { return true; }
+
+    virtual void paint(PaintInfo&, int tx, int ty);
+
+    virtual void layout();
+    virtual void calcPrefWidths();
+
+    virtual void imageChanged(WrappedImagePtr);
+
+    virtual InlineBox* createInlineBox(bool, bool, bool);
+
+    virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
+    virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
+
+    bool isImage() const;
+    bool isText() const { return !isImage(); }
+    const String& text() const { return m_text; }
+
+    bool isInside() const;
+
+    virtual SelectionState selectionState() const { return m_selectionState; }
+    virtual void setSelectionState(SelectionState);
+    virtual IntRect selectionRect(bool clipToVisibleContent = true);
+    virtual bool canBeSelectionLeaf() const { return true; }
+
+    void updateMargins();
+
+protected:
+    virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+private:
+    IntRect getRelativeMarkerRect();
+
+    String m_text;
+    RefPtr<StyleImage> m_image;
+    RenderListItem* m_listItem;
+    SelectionState m_selectionState;
+};
+
+} // namespace WebCore
+
+#endif // RenderListMarker_h
diff --git a/WebCore/rendering/RenderMarquee.cpp b/WebCore/rendering/RenderMarquee.cpp
new file mode 100644
index 0000000..96d26ea
--- /dev/null
+++ b/WebCore/rendering/RenderMarquee.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Robert O'Callahan <[email protected]>
+ *   David Baron <[email protected]>
+ *   Christian Biesinger <[email protected]>
+ *   Randall Jesup <[email protected]>
+ *   Roland Mainz <[email protected]>
+ *   Josh Soref <[email protected]>
+ *   Boris Zbarsky <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above.  If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "config.h"
+
+#include "RenderMarquee.h"
+
+#include "FrameView.h"
+#include "HTMLMarqueeElement.h"
+#include "HTMLNames.h"
+#include "RenderLayer.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderMarquee::RenderMarquee(RenderLayer* l)
+    : m_layer(l), m_currentLoop(0)
+    , m_totalLoops(0)
+    , m_timer(this, &RenderMarquee::timerFired)
+    , m_start(0), m_end(0), m_speed(0), m_reset(false)
+    , m_suspended(false), m_stopped(false), m_direction(MAUTO)
+{
+}
+
+int RenderMarquee::marqueeSpeed() const
+{
+    int result = m_layer->renderer()->style()->marqueeSpeed();
+    Node* elt = m_layer->renderer()->element();
+    if (elt && elt->hasTagName(marqueeTag)) {
+        HTMLMarqueeElement* marqueeElt = static_cast<HTMLMarqueeElement*>(elt);
+        result = max(result, marqueeElt->minimumDelay());
+    }
+    return result;
+}
+
+EMarqueeDirection RenderMarquee::direction() const
+{
+    // FIXME: Support the CSS3 "auto" value for determining the direction of the marquee.
+    // For now just map MAUTO to MBACKWARD
+    EMarqueeDirection result = m_layer->renderer()->style()->marqueeDirection();
+    TextDirection dir = m_layer->renderer()->style()->direction();
+    if (result == MAUTO)
+        result = MBACKWARD;
+    if (result == MFORWARD)
+        result = (dir == LTR) ? MRIGHT : MLEFT;
+    if (result == MBACKWARD)
+        result = (dir == LTR) ? MLEFT : MRIGHT;
+    
+    // Now we have the real direction.  Next we check to see if the increment is negative.
+    // If so, then we reverse the direction.
+    Length increment = m_layer->renderer()->style()->marqueeIncrement();
+    if (increment.isNegative())
+        result = static_cast<EMarqueeDirection>(-result);
+    
+    return result;
+}
+
+bool RenderMarquee::isHorizontal() const
+{
+    return direction() == MLEFT || direction() == MRIGHT;
+}
+
+int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge)
+{
+    RenderObject* o = m_layer->renderer();
+    RenderStyle* s = o->style();
+    if (isHorizontal()) {
+        bool ltr = s->direction() == LTR;
+        int clientWidth = o->clientWidth();
+        int contentWidth = ltr ? o->rightmostPosition(true, false) : o->leftmostPosition(true, false);
+        if (ltr)
+            contentWidth += (o->paddingRight() - o->borderLeft());
+        else {
+            contentWidth = o->width() - contentWidth;
+            contentWidth += (o->paddingLeft() - o->borderRight());
+        }
+        if (dir == MRIGHT) {
+            if (stopAtContentEdge)
+                return max(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
+            else
+                return ltr ? contentWidth : clientWidth;
+        }
+        else {
+            if (stopAtContentEdge)
+                return min(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
+            else
+                return ltr ? -clientWidth : -contentWidth;
+        }
+    }
+    else {
+        int contentHeight = m_layer->renderer()->lowestPosition(true, false) - 
+                            m_layer->renderer()->borderTop() + m_layer->renderer()->paddingBottom();
+        int clientHeight = m_layer->renderer()->clientHeight();
+        if (dir == MUP) {
+            if (stopAtContentEdge)
+                 return min(contentHeight - clientHeight, 0);
+            else
+                return -clientHeight;
+        }
+        else {
+            if (stopAtContentEdge)
+                return max(contentHeight - clientHeight, 0);
+            else 
+                return contentHeight;
+        }
+    }    
+}
+
+void RenderMarquee::start()
+{
+    if (m_timer.isActive() || m_layer->renderer()->style()->marqueeIncrement().isZero())
+        return;
+
+    // We may end up propagating a scroll event. It is important that we suspend events until 
+    // the end of the function since they could delete the layer, including the marquee.
+    FrameView* frameView = m_layer->renderer()->document()->view();
+    if (frameView)
+        frameView->pauseScheduledEvents();
+
+    if (!m_suspended && !m_stopped) {
+        if (isHorizontal())
+            m_layer->scrollToOffset(m_start, 0, false, false);
+        else
+            m_layer->scrollToOffset(0, m_start, false, false);
+    }
+    else {
+        m_suspended = false;
+        m_stopped = false;
+    }
+
+    m_timer.startRepeating(speed() * 0.001);
+
+    if (frameView)
+        frameView->resumeScheduledEvents();
+}
+
+void RenderMarquee::suspend()
+{
+    m_timer.stop();
+    m_suspended = true;
+}
+
+void RenderMarquee::stop()
+{
+    m_timer.stop();
+    m_stopped = true;
+}
+
+void RenderMarquee::updateMarqueePosition()
+{
+    bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
+    if (activate) {
+        EMarqueeBehavior behavior = m_layer->renderer()->style()->marqueeBehavior();
+        m_start = computePosition(direction(), behavior == MALTERNATE);
+        m_end = computePosition(reverseDirection(), behavior == MALTERNATE || behavior == MSLIDE);
+        if (!m_stopped)
+            start();
+    }
+}
+
+void RenderMarquee::updateMarqueeStyle()
+{
+    RenderStyle* s = m_layer->renderer()->style();
+    
+    if (m_direction != s->marqueeDirection() || (m_totalLoops != s->marqueeLoopCount() && m_currentLoop >= m_totalLoops))
+        m_currentLoop = 0; // When direction changes or our loopCount is a smaller number than our current loop, reset our loop.
+    
+    m_totalLoops = s->marqueeLoopCount();
+    m_direction = s->marqueeDirection();
+    
+    if (m_layer->renderer()->isHTMLMarquee()) {
+        // Hack for WinIE.  In WinIE, a value of 0 or lower for the loop count for SLIDE means to only do
+        // one loop.
+        if (m_totalLoops <= 0 && s->marqueeBehavior() == MSLIDE)
+            m_totalLoops = 1;
+        
+        // Hack alert: Set the white-space value to nowrap for horizontal marquees with inline children, thus ensuring
+        // all the text ends up on one line by default.  Limit this hack to the <marquee> element to emulate
+        // WinIE's behavior.  Someone using CSS3 can use white-space: nowrap on their own to get this effect.
+        // Second hack alert: Set the text-align back to auto.  WinIE completely ignores text-align on the
+        // marquee element.
+        // FIXME: Bring these up with the CSS WG.
+        if (isHorizontal() && m_layer->renderer()->childrenInline()) {
+            s->setWhiteSpace(NOWRAP);
+            s->setTextAlign(TAAUTO);
+        }
+    }
+    
+    // Marquee height hack!! Make sure that, if it is a horizontal marquee, the height attribute is overridden 
+    // if it is smaller than the font size. If it is a vertical marquee and height is not specified, we default
+    // to a marquee of 200px.
+    if (isHorizontal()) {
+        if (s->height().isFixed() && s->height().value() < s->fontSize())
+            s->setHeight(Length(s->fontSize(),Fixed));
+    } else if (s->height().isAuto())  //vertical marquee with no specified height
+        s->setHeight(Length(200, Fixed)); 
+   
+    if (speed() != marqueeSpeed()) {
+        m_speed = marqueeSpeed();
+        if (m_timer.isActive())
+            m_timer.startRepeating(speed() * 0.001);
+    }
+    
+    // Check the loop count to see if we should now stop.
+    bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
+    if (activate && !m_timer.isActive())
+        m_layer->renderer()->setNeedsLayout(true);
+    else if (!activate && m_timer.isActive())
+        m_timer.stop();
+}
+
+void RenderMarquee::timerFired(Timer<RenderMarquee>*)
+{
+    if (m_layer->renderer()->needsLayout())
+        return;
+    
+    if (m_reset) {
+        m_reset = false;
+        if (isHorizontal())
+            m_layer->scrollToXOffset(m_start);
+        else
+            m_layer->scrollToYOffset(m_start);
+        return;
+    }
+    
+    RenderStyle* s = m_layer->renderer()->style();
+    
+    int endPoint = m_end;
+    int range = m_end - m_start;
+    int newPos;
+    if (range == 0)
+        newPos = m_end;
+    else {  
+        bool addIncrement = direction() == MUP || direction() == MLEFT;
+        bool isReversed = s->marqueeBehavior() == MALTERNATE && m_currentLoop % 2;
+        if (isReversed) {
+            // We're going in the reverse direction.
+            endPoint = m_start;
+            range = -range;
+            addIncrement = !addIncrement;
+        }
+        bool positive = range > 0;
+        int clientSize = (isHorizontal() ? m_layer->renderer()->clientWidth() : m_layer->renderer()->clientHeight());
+        int increment = max(1, abs(m_layer->renderer()->style()->marqueeIncrement().calcValue(clientSize)));
+        int currentPos = (isHorizontal() ? m_layer->scrollXOffset() : m_layer->scrollYOffset());
+        newPos =  currentPos + (addIncrement ? increment : -increment);
+        if (positive)
+            newPos = min(newPos, endPoint);
+        else
+            newPos = max(newPos, endPoint);
+    }
+
+    if (newPos == endPoint) {
+        m_currentLoop++;
+        if (m_totalLoops > 0 && m_currentLoop >= m_totalLoops)
+            m_timer.stop();
+        else if (s->marqueeBehavior() != MALTERNATE)
+            m_reset = true;
+    }
+    
+    if (isHorizontal())
+        m_layer->scrollToXOffset(newPos);
+    else
+        m_layer->scrollToYOffset(newPos);
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/rendering/RenderMarquee.h b/WebCore/rendering/RenderMarquee.h
new file mode 100644
index 0000000..d9d20cd
--- /dev/null
+++ b/WebCore/rendering/RenderMarquee.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Robert O'Callahan <[email protected]>
+ *   David Baron <[email protected]>
+ *   Christian Biesinger <[email protected]>
+ *   Randall Jesup <[email protected]>
+ *   Roland Mainz <[email protected]>
+ *   Josh Soref <[email protected]>
+ *   Boris Zbarsky <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above.  If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#ifndef RenderMarquee_h
+#define RenderMarquee_h
+
+#include "RenderStyle.h"
+#include "Timer.h"
+
+namespace WebCore {
+
+class RenderLayer;
+
+// This class handles the auto-scrolling of layers with overflow: marquee.
+class RenderMarquee {
+public:
+    RenderMarquee(RenderLayer*);
+
+    int speed() const { return m_speed; }
+    int marqueeSpeed() const;
+
+    EMarqueeDirection reverseDirection() const { return static_cast<EMarqueeDirection>(-direction()); }
+    EMarqueeDirection direction() const;
+
+    bool isHorizontal() const;
+
+    int computePosition(EMarqueeDirection, bool stopAtClientEdge);
+
+    void setEnd(int end) { m_end = end; }
+    
+    void start();
+    void suspend();
+    void stop();
+
+    void updateMarqueeStyle();
+    void updateMarqueePosition();
+
+private:
+    void timerFired(Timer<RenderMarquee>*);
+
+    RenderLayer* m_layer;
+    int m_currentLoop;
+    int m_totalLoops;
+    Timer<RenderMarquee> m_timer;
+    int m_start;
+    int m_end;
+    int m_speed;
+    Length m_height;
+    bool m_reset: 1;
+    bool m_suspended : 1;
+    bool m_stopped : 1;
+    EMarqueeDirection m_direction : 4;
+};
+
+} // namespace WebCore
+
+#endif // RenderMarquee_h
diff --git a/WebCore/rendering/RenderMedia.cpp b/WebCore/rendering/RenderMedia.cpp
new file mode 100644
index 0000000..4953a35
--- /dev/null
+++ b/WebCore/rendering/RenderMedia.cpp
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+
+#if ENABLE(VIDEO)
+#include "RenderMedia.h"
+
+#include "CSSStyleSelector.h"
+#include "Event.h"
+#include "EventNames.h"
+#include "FloatConversion.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLMediaElement.h"
+#include "MediaControlElements.h"
+#include "MouseEvent.h"
+#include "MediaPlayer.h"
+#include "RenderSlider.h"
+#include "SystemTime.h"
+#include <wtf/MathExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static const double cTimeUpdateRepeatDelay = 0.2;
+static const double cOpacityAnimationRepeatDelay = 0.05;
+// FIXME get this from style
+static const double cOpacityAnimationDuration = 0.1;
+
+RenderMedia::RenderMedia(HTMLMediaElement* video)
+    : RenderReplaced(video)
+    , m_timeUpdateTimer(this, &RenderMedia::timeUpdateTimerFired)
+    , m_opacityAnimationTimer(this, &RenderMedia::opacityAnimationTimerFired)
+    , m_mouseOver(false)
+    , m_opacityAnimationStartTime(0)
+    , m_opacityAnimationFrom(0)
+    , m_opacityAnimationTo(1.0f)
+    , m_previousVisible(VISIBLE)
+{
+}
+
+RenderMedia::RenderMedia(HTMLMediaElement* video, const IntSize& intrinsicSize)
+    : RenderReplaced(video, intrinsicSize)
+    , m_timeUpdateTimer(this, &RenderMedia::timeUpdateTimerFired)
+    , m_opacityAnimationTimer(this, &RenderMedia::opacityAnimationTimerFired)
+    , m_mouseOver(false)
+    , m_opacityAnimationStartTime(0)
+    , m_opacityAnimationFrom(0)
+    , m_opacityAnimationTo(1.0f)
+{
+}
+
+RenderMedia::~RenderMedia()
+{
+}
+
+void RenderMedia::destroy()
+{
+    if (m_controlsShadowRoot && m_controlsShadowRoot->renderer()) {
+        removeChild(m_controlsShadowRoot->renderer());
+        m_controlsShadowRoot->detach();
+    }
+    RenderReplaced::destroy();
+}
+
+HTMLMediaElement* RenderMedia::mediaElement() const
+{ 
+    return static_cast<HTMLMediaElement*>(node()); 
+}
+
+MediaPlayer* RenderMedia::player() const
+{
+    return mediaElement()->player();
+}
+
+void RenderMedia::layout()
+{
+    IntSize oldSize = contentBox().size();
+
+    RenderReplaced::layout();
+
+    RenderObject* controlsRenderer = m_controlsShadowRoot ? m_controlsShadowRoot->renderer() : 0;
+    if (!controlsRenderer)
+        return;
+    IntSize newSize = contentBox().size();
+    if (newSize != oldSize || controlsRenderer->needsLayout()) {
+        controlsRenderer->setPos(borderLeft() + paddingLeft(), borderTop() + paddingTop());
+        controlsRenderer->style()->setHeight(Length(newSize.height(), Fixed));
+        controlsRenderer->style()->setWidth(Length(newSize.width(), Fixed));
+        controlsRenderer->setNeedsLayout(true, false);
+        controlsRenderer->layout();
+        setChildNeedsLayout(false);
+    }
+}
+
+RenderObject* RenderMedia::firstChild() const 
+{ 
+    return m_controlsShadowRoot ? m_controlsShadowRoot->renderer() : 0; 
+}
+
+RenderObject* RenderMedia::lastChild() const 
+{ 
+    return m_controlsShadowRoot ? m_controlsShadowRoot->renderer() : 0;
+}
+    
+void RenderMedia::removeChild(RenderObject* child)
+{
+    ASSERT(m_controlsShadowRoot);
+    ASSERT(child == m_controlsShadowRoot->renderer());
+    child->removeLayers(enclosingLayer());
+    static_cast<RenderMediaControlShadowRoot*>(child)->setParent(0);
+}
+    
+void RenderMedia::createControlsShadowRoot()
+{
+    ASSERT(!m_controlsShadowRoot);
+    m_controlsShadowRoot = new MediaControlShadowRootElement(document(), mediaElement());
+}
+
+void RenderMedia::createPanel()
+{
+    ASSERT(!m_panel);
+    RenderStyle* style = getCachedPseudoStyle(RenderStyle::MEDIA_CONTROLS_PANEL);
+    m_panel = new HTMLDivElement(document());
+    RenderObject* renderer = m_panel->createRenderer(renderArena(), style);
+    if (renderer) {
+        m_panel->setRenderer(renderer);
+        renderer->setStyle(style);
+        m_panel->setAttached();
+        m_panel->setInDocument(true);
+        m_controlsShadowRoot->addChild(m_panel);
+        m_controlsShadowRoot->renderer()->addChild(renderer);
+    }
+}
+
+void RenderMedia::createMuteButton()
+{
+    ASSERT(!m_muteButton);
+    m_muteButton = new MediaControlMuteButtonElement(document(), mediaElement());
+    m_muteButton->attachToParent(m_panel.get());
+}
+
+void RenderMedia::createPlayButton()
+{
+    ASSERT(!m_playButton);
+    m_playButton = new MediaControlPlayButtonElement(document(), mediaElement());
+    m_playButton->attachToParent(m_panel.get());
+}
+
+void RenderMedia::createSeekBackButton()
+{
+    ASSERT(!m_seekBackButton);
+    m_seekBackButton = new MediaControlSeekButtonElement(document(), mediaElement(), false);
+    m_seekBackButton->attachToParent(m_panel.get());
+}
+
+void RenderMedia::createSeekForwardButton()
+{
+    ASSERT(!m_seekForwardButton);
+    m_seekForwardButton = new MediaControlSeekButtonElement(document(), mediaElement(), true);
+    m_seekForwardButton->attachToParent(m_panel.get());
+}
+
+void RenderMedia::createTimeline()
+{
+    ASSERT(!m_timeline);
+    m_timeline = new MediaControlTimelineElement(document(), mediaElement());
+    m_timeline->attachToParent(m_panel.get());
+}
+  
+void RenderMedia::createTimeDisplay()
+{
+    ASSERT(!m_timeDisplay);
+    RenderStyle* style = getCachedPseudoStyle(RenderStyle::MEDIA_CONTROLS_TIME_DISPLAY);
+    m_timeDisplay = new HTMLDivElement(document());
+    RenderObject* renderer = m_timeDisplay->createRenderer(renderArena(), style);
+    if (renderer) {
+        m_timeDisplay->setRenderer(renderer);
+        renderer->setStyle(style);
+        m_timeDisplay->setAttached();
+        m_timeDisplay->setInDocument(true);
+        m_panel->addChild(m_timeDisplay);
+        m_panel->renderer()->addChild(renderer);
+    }
+}
+
+void RenderMedia::createFullscreenButton()
+{
+    ASSERT(!m_fullscreenButton);
+    m_fullscreenButton = new MediaControlFullscreenButtonElement(document(), mediaElement());
+    m_fullscreenButton->attachToParent(m_panel.get());
+}
+    
+void RenderMedia::updateFromElement()
+{
+    updateControls();
+}
+            
+void RenderMedia::updateControls()
+{
+    HTMLMediaElement* media = mediaElement();
+    if (!media->controls() || !media->inActiveDocument()) {
+        if (m_controlsShadowRoot) {
+            m_controlsShadowRoot->detach();
+            m_panel = 0;
+            m_muteButton = 0;
+            m_playButton = 0;
+            m_timeline = 0;
+            m_seekBackButton = 0;
+            m_seekForwardButton = 0;
+            m_timeDisplay = 0;
+            m_fullscreenButton = 0;
+            m_controlsShadowRoot = 0;
+        }
+        m_opacityAnimationTo = 1.0f;
+        m_opacityAnimationTimer.stop();
+        m_timeUpdateTimer.stop();
+        return;
+    }
+    
+    if (!m_controlsShadowRoot) {
+        createControlsShadowRoot();
+        createPanel();
+        createMuteButton();
+        createPlayButton();
+        createTimeline();
+        createSeekBackButton();
+        createSeekForwardButton();
+        createTimeDisplay();
+        createFullscreenButton();
+    }
+    
+    if (media->paused() || media->ended() || media->networkState() < HTMLMediaElement::LOADED_METADATA)
+        m_timeUpdateTimer.stop();
+    else
+        m_timeUpdateTimer.startRepeating(cTimeUpdateRepeatDelay);
+    
+    if (m_muteButton)
+        m_muteButton->update();
+    if (m_playButton)
+        m_playButton->update();
+    if (m_timeline)
+        m_timeline->update();
+    if (m_seekBackButton)
+        m_seekBackButton->update();
+    if (m_seekForwardButton)
+        m_seekForwardButton->update();
+    if (m_fullscreenButton)
+        m_fullscreenButton->update();
+    updateTimeDisplay();
+    updateControlVisibility();
+}
+
+void RenderMedia::timeUpdateTimerFired(Timer<RenderMedia>*)
+{
+    if (m_timeline)
+        m_timeline->update(false);
+    updateTimeDisplay();
+}
+    
+String RenderMedia::formatTime(float time)
+{
+    if (!isfinite(time))
+        time = 0;
+    int seconds = (int)time; 
+    int hours = seconds / (60 * 60);
+    int minutes = (seconds / 60) % 60;
+    seconds %= 60;
+    return String::format("%02d:%02d:%02d", hours, minutes, seconds);
+}
+
+void RenderMedia::updateTimeDisplay()
+{
+    if (!m_timeDisplay)
+        return;
+    String timeString = formatTime(mediaElement()->currentTime());
+    ExceptionCode ec;
+    m_timeDisplay->setInnerText(timeString, ec);
+}
+    
+void RenderMedia::updateControlVisibility() 
+{
+    if (!m_panel || !m_panel->renderer())
+        return;
+    // Don't fade for audio controls.
+    HTMLMediaElement* media = mediaElement();
+    if (player() && !player()->hasVideo() || !media->isVideo())
+        return;
+    // do fading manually, css animations don't work well with shadow trees
+    bool visible = style()->visibility() == VISIBLE && (m_mouseOver || media->paused() || media->ended() || media->networkState() < HTMLMediaElement::LOADED_METADATA);
+    if (visible == (m_opacityAnimationTo > 0))
+        return;
+
+    if (style()->visibility() != m_previousVisible) {
+        // don't fade gradually if it the element has just changed visibility
+        m_previousVisible = style()->visibility();
+        m_opacityAnimationTo = m_previousVisible == VISIBLE ? 1.0f : 0;
+        changeOpacity(m_panel.get(), 0);
+        return;
+    }
+
+    if (visible) {
+        m_opacityAnimationFrom = m_panel->renderer()->style()->opacity();
+        m_opacityAnimationTo = 1.0f;
+    } else {
+        m_opacityAnimationFrom = m_panel->renderer()->style()->opacity();
+        m_opacityAnimationTo = 0;
+    }
+    m_opacityAnimationStartTime = currentTime();
+    m_opacityAnimationTimer.startRepeating(cOpacityAnimationRepeatDelay);
+}
+    
+void RenderMedia::changeOpacity(HTMLElement* e, float opacity) 
+{
+    if (!e || !e->renderer() || !e->renderer()->style())
+        return;
+    RefPtr<RenderStyle> s = RenderStyle::clone(e->renderer()->style());
+    s->setOpacity(opacity);
+    // z-index can't be auto if opacity is used
+    s->setZIndex(0);
+    e->renderer()->setStyle(s.release());
+}
+    
+void RenderMedia::opacityAnimationTimerFired(Timer<RenderMedia>*)
+{
+    double time = currentTime() - m_opacityAnimationStartTime;
+    if (time >= cOpacityAnimationDuration) {
+        time = cOpacityAnimationDuration;
+        m_opacityAnimationTimer.stop();
+    }
+    float opacity = narrowPrecisionToFloat(m_opacityAnimationFrom + (m_opacityAnimationTo - m_opacityAnimationFrom) * time / cOpacityAnimationDuration);
+    changeOpacity(m_panel.get(), opacity);
+}
+    
+void RenderMedia::forwardEvent(Event* event)
+{
+    if (event->isMouseEvent() && m_controlsShadowRoot) {
+        MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
+        IntPoint point(mouseEvent->pageX(), mouseEvent->pageY());
+        if (m_muteButton && m_muteButton->renderer() && m_muteButton->renderer()->absoluteBoundingBoxRect().contains(point))
+            m_muteButton->defaultEventHandler(event);
+        if (m_playButton && m_playButton->renderer() && m_playButton->renderer()->absoluteBoundingBoxRect().contains(point))
+            m_playButton->defaultEventHandler(event);
+        if (m_seekBackButton && m_seekBackButton->renderer() && m_seekBackButton->renderer()->absoluteBoundingBoxRect().contains(point))
+            m_seekBackButton->defaultEventHandler(event);
+        if (m_seekForwardButton && m_seekForwardButton->renderer() && m_seekForwardButton->renderer()->absoluteBoundingBoxRect().contains(point))
+            m_seekForwardButton->defaultEventHandler(event);
+        if (m_timeline && m_timeline->renderer() && m_timeline->renderer()->absoluteBoundingBoxRect().contains(point))
+            m_timeline->defaultEventHandler(event);
+        if (m_fullscreenButton && m_fullscreenButton->renderer() && m_fullscreenButton->renderer()->absoluteBoundingBoxRect().contains(point))
+            m_fullscreenButton->defaultEventHandler(event);
+        
+        if (event->type() == eventNames().mouseoverEvent) {
+            m_mouseOver = true;
+            updateControlVisibility();
+        }
+        if (event->type() == eventNames().mouseoutEvent) {
+            // FIXME: moving over scrollbar thumb generates mouseout for the ancestor media element for some reason
+            m_mouseOver = absoluteBoundingBoxRect().contains(point);
+            updateControlVisibility();
+        }
+    }
+}
+
+int RenderMedia::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    int bottom = RenderReplaced::lowestPosition(includeOverflowInterior, includeSelf);
+    if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer())
+        return bottom;
+    
+    return max(bottom,  m_controlsShadowRoot->renderer()->yPos() + m_controlsShadowRoot->renderer()->lowestPosition(includeOverflowInterior, includeSelf));
+}
+
+int RenderMedia::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    int right = RenderReplaced::rightmostPosition(includeOverflowInterior, includeSelf);
+    if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer())
+        return right;
+    
+    return max(right, m_controlsShadowRoot->renderer()->xPos() + m_controlsShadowRoot->renderer()->rightmostPosition(includeOverflowInterior, includeSelf));
+}
+
+int RenderMedia::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    int left = RenderReplaced::leftmostPosition(includeOverflowInterior, includeSelf);
+    if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer())
+        return left;
+    
+    return min(left, m_controlsShadowRoot->renderer()->xPos() +  m_controlsShadowRoot->renderer()->leftmostPosition(includeOverflowInterior, includeSelf));
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/rendering/RenderMedia.h b/WebCore/rendering/RenderMedia.h
new file mode 100644
index 0000000..8f48caf
--- /dev/null
+++ b/WebCore/rendering/RenderMedia.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RenderMedia_h
+#define RenderMedia_h
+
+#if ENABLE(VIDEO)
+
+#include "RenderReplaced.h"
+#include "Timer.h"
+
+namespace WebCore {
+    
+class HTMLInputElement;
+class HTMLMediaElement;
+class MediaControlMuteButtonElement;
+class MediaControlPlayButtonElement;
+class MediaControlSeekButtonElement;
+class MediaControlTimelineElement;
+class MediaControlFullscreenButtonElement;
+class MediaPlayer;
+
+class RenderMedia : public RenderReplaced {
+public:
+    RenderMedia(HTMLMediaElement*);
+    RenderMedia(HTMLMediaElement*, const IntSize& intrinsicSize);
+    virtual ~RenderMedia();
+    
+    virtual RenderObject* firstChild() const;
+    virtual RenderObject* lastChild() const;
+    virtual void removeChild(RenderObject*);
+    virtual void destroy();
+    
+    virtual void layout();
+
+    virtual const char* renderName() const { return "RenderMedia"; }
+    virtual bool isMedia() const { return true; }
+    
+    HTMLMediaElement* mediaElement() const;
+    MediaPlayer* player() const;
+
+    static String formatTime(float time);
+
+    void updateFromElement();
+    void updatePlayer();
+    void updateControls();
+    
+    void forwardEvent(Event*);
+
+    virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+    virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+    virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+
+private:
+    void createControlsShadowRoot();
+    void createPanel();
+    void createMuteButton();
+    void createPlayButton();
+    void createSeekBackButton();
+    void createSeekForwardButton();
+    void createTimeline();
+    void createTimeDisplay();
+    void createFullscreenButton();
+    
+    void timeUpdateTimerFired(Timer<RenderMedia>*);
+    void updateTimeDisplay();
+    
+    void updateControlVisibility();
+    void changeOpacity(HTMLElement*, float opacity);
+    void opacityAnimationTimerFired(Timer<RenderMedia>*);
+
+    RefPtr<HTMLElement> m_controlsShadowRoot;
+    RefPtr<HTMLElement> m_panel;
+    RefPtr<MediaControlMuteButtonElement> m_muteButton;
+    RefPtr<MediaControlPlayButtonElement> m_playButton;
+    RefPtr<MediaControlSeekButtonElement> m_seekBackButton;
+    RefPtr<MediaControlSeekButtonElement> m_seekForwardButton;
+    RefPtr<MediaControlTimelineElement> m_timeline;
+    RefPtr<MediaControlFullscreenButtonElement> m_fullscreenButton;
+    RefPtr<HTMLElement> m_timeDisplay;
+    EventTargetNode* m_lastUnderNode;
+    EventTargetNode* m_nodeUnderMouse;
+    
+    Timer<RenderMedia> m_timeUpdateTimer;
+    Timer<RenderMedia> m_opacityAnimationTimer;
+    bool m_mouseOver;
+    double m_opacityAnimationStartTime;
+    float m_opacityAnimationFrom;
+    float m_opacityAnimationTo;
+    EVisibility m_previousVisible;
+};
+
+} // namespace WebCore
+
+#endif
+#endif // RenderMedia_h
diff --git a/WebCore/rendering/RenderMenuList.cpp b/WebCore/rendering/RenderMenuList.cpp
new file mode 100644
index 0000000..469a73d
--- /dev/null
+++ b/WebCore/rendering/RenderMenuList.cpp
@@ -0,0 +1,435 @@
+/**
+ * This file is part of the select element renderer in WebCore.
+ *
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderMenuList.h"
+
+#include "CSSStyleSelector.h"
+#include "Document.h"
+#include "FontSelector.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "HTMLOptionElement.h"
+#include "HTMLOptGroupElement.h"
+#include "HTMLSelectElement.h"
+#include "PopupMenu.h"
+#include "RenderBR.h"
+#include "RenderScrollbar.h"
+#include "RenderText.h"
+#include "RenderTheme.h"
+#include "NodeRenderStyle.h"
+#include <math.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderMenuList::RenderMenuList(HTMLSelectElement* element)
+    : RenderFlexibleBox(element)
+    , m_buttonText(0)
+    , m_innerBlock(0)
+    , m_optionsChanged(true)
+    , m_optionsWidth(0)
+    , m_popup(0)
+    , m_popupIsVisible(false)
+{
+}
+
+RenderMenuList::~RenderMenuList()
+{
+    if (m_popup)
+        m_popup->disconnectClient();
+    m_popup = 0;
+}
+
+// this static cast is safe because RenderMenuLists are only created for HTMLSelectElements
+HTMLSelectElement* RenderMenuList::selectElement()
+{
+    return static_cast<HTMLSelectElement*>(node());
+}
+
+void RenderMenuList::createInnerBlock()
+{
+    if (m_innerBlock) {
+        ASSERT(firstChild() == m_innerBlock);
+        ASSERT(!m_innerBlock->nextSibling());
+        return;
+    }
+
+    // Create an anonymous block.
+    ASSERT(!firstChild());
+    m_innerBlock = createAnonymousBlock();
+    adjustInnerStyle();
+    RenderFlexibleBox::addChild(m_innerBlock);
+}
+
+void RenderMenuList::adjustInnerStyle()
+{
+    m_innerBlock->style()->setBoxFlex(1.0f);
+    
+    m_innerBlock->style()->setPaddingLeft(Length(theme()->popupInternalPaddingLeft(style()), Fixed));
+    m_innerBlock->style()->setPaddingRight(Length(theme()->popupInternalPaddingRight(style()), Fixed));
+    m_innerBlock->style()->setPaddingTop(Length(theme()->popupInternalPaddingTop(style()), Fixed));
+    m_innerBlock->style()->setPaddingBottom(Length(theme()->popupInternalPaddingBottom(style()), Fixed));
+        
+    if (PopupMenu::itemWritingDirectionIsNatural()) {
+        // Items in the popup will not respect the CSS text-align and direction properties,
+        // so we must adjust our own style to match.
+        m_innerBlock->style()->setTextAlign(LEFT);
+        TextDirection direction = (m_buttonText && m_buttonText->text()->defaultWritingDirection() == WTF::Unicode::RightToLeft) ? RTL : LTR;
+        m_innerBlock->style()->setDirection(direction);
+    }
+}
+
+void RenderMenuList::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    createInnerBlock();
+    m_innerBlock->addChild(newChild, beforeChild);
+}
+
+void RenderMenuList::removeChild(RenderObject* oldChild)
+{
+    if (oldChild == m_innerBlock || !m_innerBlock) {
+        RenderFlexibleBox::removeChild(oldChild);
+        m_innerBlock = 0;
+    } else
+        m_innerBlock->removeChild(oldChild);
+}
+
+void RenderMenuList::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+
+    if (m_buttonText)
+        m_buttonText->setStyle(style());
+    if (m_innerBlock) // RenderBlock handled updating the anonymous block's style.
+        adjustInnerStyle();
+
+    setReplaced(isInline());
+
+    bool fontChanged = !oldStyle || oldStyle->font() != style()->font();
+    if (fontChanged)
+        updateOptionsWidth();
+}
+
+void RenderMenuList::updateOptionsWidth()
+{
+    float maxOptionWidth = 0;
+    const Vector<HTMLElement*>& listItems = static_cast<HTMLSelectElement*>(node())->listItems();
+    int size = listItems.size();    
+    for (int i = 0; i < size; ++i) {
+        HTMLElement* element = listItems[i];
+        if (element->hasTagName(optionTag)) {
+            String text = static_cast<HTMLOptionElement*>(element)->optionText();
+            if (!text.isEmpty())
+                maxOptionWidth = max(maxOptionWidth, style()->font().floatWidth(text));
+        }
+    }
+
+    int width = static_cast<int>(ceilf(maxOptionWidth));
+    if (m_optionsWidth == width)
+        return;
+
+    m_optionsWidth = width;
+    setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+void RenderMenuList::updateFromElement()
+{
+    if (m_optionsChanged) {
+        updateOptionsWidth();
+        m_optionsChanged = false;
+    }
+
+    if (m_popupIsVisible)
+        m_popup->updateFromElement();
+    else
+        setTextFromOption(static_cast<HTMLSelectElement*>(node())->selectedIndex());
+}
+
+void RenderMenuList::setTextFromOption(int optionIndex)
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    const Vector<HTMLElement*>& listItems = select->listItems();
+    int size = listItems.size();
+
+    int i = select->optionToListIndex(optionIndex);
+    String text = "";
+    if (i >= 0 && i < size) {
+        HTMLElement* element = listItems[i];
+        if (element->hasTagName(optionTag))
+            text = static_cast<HTMLOptionElement*>(listItems[i])->optionText();
+    }
+    setText(text.stripWhiteSpace());
+}
+
+void RenderMenuList::setText(const String& s)
+{
+    if (s.isEmpty()) {
+        if (!m_buttonText || !m_buttonText->isBR()) {
+            if (m_buttonText)
+                m_buttonText->destroy();
+            m_buttonText = new (renderArena()) RenderBR(document());
+            m_buttonText->setStyle(style());
+            addChild(m_buttonText);
+        }
+    } else {
+        if (m_buttonText && !m_buttonText->isBR())
+            m_buttonText->setText(s.impl());
+        else {
+            if (m_buttonText)
+                m_buttonText->destroy();
+            m_buttonText = new (renderArena()) RenderText(document(), s.impl());
+            m_buttonText->setStyle(style());
+            addChild(m_buttonText);
+        }
+        adjustInnerStyle();
+    }
+}
+
+String RenderMenuList::text() const
+{
+    return m_buttonText ? m_buttonText->text() : 0;
+}
+
+IntRect RenderMenuList::controlClipRect(int tx, int ty) const
+{
+    // Clip to the intersection of the content box and the content box for the inner box
+    // This will leave room for the arrows which sit in the inner box padding,
+    // and if the inner box ever spills out of the outer box, that will get clipped too.
+    IntRect outerBox(tx + borderLeft() + paddingLeft(), 
+                   ty + borderTop() + paddingTop(),
+                   contentWidth(), 
+                   contentHeight());
+    
+    IntRect innerBox(tx + m_innerBlock->xPos() + m_innerBlock->paddingLeft(), 
+                   ty + m_innerBlock->yPos() + m_innerBlock->paddingTop(),
+                   m_innerBlock->contentWidth(), 
+                   m_innerBlock->contentHeight());
+
+    return intersection(outerBox, innerBox);
+}
+
+void RenderMenuList::calcPrefWidths()
+{
+    m_minPrefWidth = 0;
+    m_maxPrefWidth = 0;
+    
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
+    else
+        m_maxPrefWidth = max(m_optionsWidth, theme()->minimumMenuListSize(style())) + m_innerBlock->paddingLeft() + m_innerBlock->paddingRight();
+
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+        m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+    } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
+        m_minPrefWidth = 0;
+    else
+        m_minPrefWidth = m_maxPrefWidth;
+
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
+        m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+        m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+    }
+
+    int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+    m_minPrefWidth += toAdd;
+    m_maxPrefWidth += toAdd;
+
+    setPrefWidthsDirty(false);
+}
+
+void RenderMenuList::showPopup()
+{
+    if (m_popupIsVisible)
+        return;
+
+    // Create m_innerBlock here so it ends up as the first child.
+    // This is important because otherwise we might try to create m_innerBlock
+    // inside the showPopup call and it would fail.
+    createInnerBlock();
+    if (!m_popup)
+        m_popup = PopupMenu::create(this);
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    m_popupIsVisible = true;
+    m_popup->show(absoluteBoundingBoxRect(), document()->view(),
+        select->optionToListIndex(select->selectedIndex()));
+}
+
+void RenderMenuList::hidePopup()
+{
+    if (m_popup)
+        m_popup->hide();
+    m_popupIsVisible = false;
+}
+
+void RenderMenuList::valueChanged(unsigned listIndex, bool fireOnChange)
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    select->setSelectedIndex(select->listToOptionIndex(listIndex), true, fireOnChange);
+}
+
+String RenderMenuList::itemText(unsigned listIndex) const
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    HTMLElement* element = select->listItems()[listIndex];
+    if (element->hasTagName(optgroupTag))
+        return static_cast<HTMLOptGroupElement*>(element)->groupLabelText();
+    else if (element->hasTagName(optionTag))
+        return static_cast<HTMLOptionElement*>(element)->optionText();
+    return String();
+}
+
+bool RenderMenuList::itemIsEnabled(unsigned listIndex) const
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    HTMLElement* element = select->listItems()[listIndex];
+    if (!element->hasTagName(optionTag))
+        return false;
+    bool groupEnabled = true;
+    if (element->parentNode() && element->parentNode()->hasTagName(optgroupTag))
+        groupEnabled = element->parentNode()->isEnabled();
+    return element->isEnabled() && groupEnabled;
+}
+
+PopupMenuStyle RenderMenuList::itemStyle(unsigned listIndex) const
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    HTMLElement* element = select->listItems()[listIndex];
+    
+    RenderStyle* style = element->renderStyle() ? element->renderStyle() : element->computedStyle();
+    return style ? PopupMenuStyle(style->color(), itemBackgroundColor(listIndex), style->font(), style->visibility() == VISIBLE) : menuStyle();
+}
+
+Color RenderMenuList::itemBackgroundColor(unsigned listIndex) const
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    HTMLElement* element = select->listItems()[listIndex];
+
+    Color backgroundColor;
+    if (element->renderStyle())
+        backgroundColor = element->renderStyle()->backgroundColor();
+    // If the item has an opaque background color, return that.
+    if (!backgroundColor.hasAlpha())
+        return backgroundColor;
+
+    // Otherwise, the item's background is overlayed on top of the menu background.
+    backgroundColor = style()->backgroundColor().blend(backgroundColor);
+    if (!backgroundColor.hasAlpha())
+        return backgroundColor;
+
+    // If the menu background is not opaque, then add an opaque white background behind.
+    return Color(Color::white).blend(backgroundColor);
+}
+
+PopupMenuStyle RenderMenuList::menuStyle() const
+{
+
+    RenderStyle* s = m_innerBlock ? m_innerBlock->style() : style();
+    return PopupMenuStyle(s->color(), s->backgroundColor(), s->font(), s->visibility() == VISIBLE);
+}
+
+HostWindow* RenderMenuList::hostWindow() const
+{
+    return document()->view()->hostWindow();
+}
+
+PassRefPtr<Scrollbar> RenderMenuList::createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
+{
+    RefPtr<Scrollbar> widget;
+    bool hasCustomScrollbarStyle = style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
+    if (hasCustomScrollbarStyle)
+        widget = RenderScrollbar::createCustomScrollbar(client, orientation, this);
+    else
+        widget = Scrollbar::createNativeScrollbar(client, orientation, controlSize);
+    return widget.release();
+}
+
+int RenderMenuList::clientInsetLeft() const
+{
+    return 0;
+}
+
+int RenderMenuList::clientInsetRight() const
+{
+    return 0;
+}
+
+int RenderMenuList::clientPaddingLeft() const
+{
+    return paddingLeft();
+}
+
+int RenderMenuList::clientPaddingRight() const
+{
+    return paddingRight();
+}
+
+int RenderMenuList::listSize() const
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    return select->listItems().size();
+}
+
+int RenderMenuList::selectedIndex() const
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    return select->optionToListIndex(select->selectedIndex());
+}
+
+bool RenderMenuList::itemIsSeparator(unsigned listIndex) const
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    HTMLElement* element = select->listItems()[listIndex];
+    return element->hasTagName(hrTag);
+}
+
+bool RenderMenuList::itemIsLabel(unsigned listIndex) const
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    HTMLElement* element = select->listItems()[listIndex];
+    return element->hasTagName(optgroupTag);
+}
+
+bool RenderMenuList::itemIsSelected(unsigned listIndex) const
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    HTMLElement* element = select->listItems()[listIndex];
+    return element->hasTagName(optionTag)&& static_cast<HTMLOptionElement*>(element)->selected();
+}
+
+void RenderMenuList::setTextFromItem(unsigned listIndex)
+{
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+    setTextFromOption(select->listToOptionIndex(listIndex));
+}
+
+FontSelector* RenderMenuList::fontSelector() const
+{
+    return document()->styleSelector()->fontSelector();
+}
+
+}
diff --git a/WebCore/rendering/RenderMenuList.h b/WebCore/rendering/RenderMenuList.h
new file mode 100644
index 0000000..f31ef32
--- /dev/null
+++ b/WebCore/rendering/RenderMenuList.h
@@ -0,0 +1,119 @@
+/*
+ * This file is part of the select element renderer in WebCore.
+ *
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderMenuList_h
+#define RenderMenuList_h
+
+#include "RenderFlexibleBox.h"
+#include "PopupMenuClient.h"
+
+#if PLATFORM(MAC)
+#define POPUP_MENU_PULLS_DOWN 0
+#else
+#define POPUP_MENU_PULLS_DOWN 1
+#endif
+
+namespace WebCore {
+
+class HTMLSelectElement;
+class PopupMenu;
+
+class RenderMenuList : public RenderFlexibleBox, private PopupMenuClient {
+public:
+    RenderMenuList(HTMLSelectElement*);
+    ~RenderMenuList();
+    
+    HTMLSelectElement* selectElement();
+
+    virtual bool isMenuList() const { return true; }
+
+    virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject*);
+    virtual bool createsAnonymousWrapper() const { return true; }
+    virtual bool canHaveChildren() const { return false; }
+
+    virtual void updateFromElement();
+
+    virtual bool hasControlClip() const { return true; }
+    virtual IntRect controlClipRect(int tx, int ty) const;
+
+    virtual const char* renderName() const { return "RenderMenuList"; }
+
+    virtual void calcPrefWidths();
+
+    bool popupIsVisible() const { return m_popupIsVisible; }
+    void showPopup();
+    void hidePopup();
+
+    void setOptionsChanged(bool changed) { m_optionsChanged = changed; }
+
+    String text() const;
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+private:
+    // PopupMenuClient methods
+    virtual String itemText(unsigned listIndex) const;
+    virtual bool itemIsEnabled(unsigned listIndex) const;
+    virtual PopupMenuStyle itemStyle(unsigned listIndex) const;
+    virtual PopupMenuStyle menuStyle() const;
+    virtual int clientInsetLeft() const;
+    virtual int clientInsetRight() const;
+    virtual int clientPaddingLeft() const;
+    virtual int clientPaddingRight() const;
+    virtual int listSize() const;
+    virtual int selectedIndex() const;
+    virtual bool itemIsSeparator(unsigned listIndex) const;
+    virtual bool itemIsLabel(unsigned listIndex) const;
+    virtual bool itemIsSelected(unsigned listIndex) const;
+    virtual void setTextFromItem(unsigned listIndex);
+    virtual bool valueShouldChangeOnHotTrack() const { return true; }
+    virtual bool shouldPopOver() const { return !POPUP_MENU_PULLS_DOWN; }
+    virtual void valueChanged(unsigned listIndex, bool fireOnChange = true);
+    virtual FontSelector* fontSelector() const;
+    virtual HostWindow* hostWindow() const;
+    virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
+
+    virtual bool hasLineIfEmpty() const { return true; }
+
+    Color itemBackgroundColor(unsigned listIndex) const;
+
+    void createInnerBlock();
+    void adjustInnerStyle();
+    void setText(const String&);
+    void setTextFromOption(int optionIndex);
+    void updateOptionsWidth();
+
+    RenderText* m_buttonText;
+    RenderBlock* m_innerBlock;
+
+    bool m_optionsChanged;
+    int m_optionsWidth;
+
+    RefPtr<PopupMenu> m_popup;
+    bool m_popupIsVisible;
+};
+
+}
+
+#endif
diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp
new file mode 100644
index 0000000..56fb7df
--- /dev/null
+++ b/WebCore/rendering/RenderObject.cpp
@@ -0,0 +1,3212 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ *           (C) 2004 Allan Sandfeld Jensen ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderObject.h"
+
+#include "AXObjectCache.h"
+#include "AffineTransform.h"
+#include "AnimationController.h"
+#include "CSSStyleSelector.h"
+#include "CachedImage.h"
+#include "Chrome.h"
+#include "Document.h"
+#include "Element.h"
+#include "EventHandler.h"
+#include "FloatRect.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "HTMLOListElement.h"
+#include "HitTestRequest.h"
+#include "HitTestResult.h"
+#include "KURL.h"
+#include "Page.h"
+#include "PlatformScreen.h"
+#include "Position.h"
+#include "RenderArena.h"
+#include "RenderCounter.h"
+#include "RenderFlexibleBox.h"
+#include "RenderImageGeneratedContent.h"
+#include "RenderInline.h"
+#include "RenderListItem.h"
+#include "RenderTableCell.h"
+#include "RenderTableCol.h"
+#include "RenderTableRow.h"
+#include "RenderText.h"
+#include "RenderTheme.h"
+#include "RenderView.h"
+#include "SelectionController.h"
+#include "TextResourceDecoder.h"
+#include <algorithm>
+#ifdef ANDROID_LAYOUT
+#include "Settings.h"
+#endif
+#include <stdio.h>
+#include <wtf/RefCountedLeakCounter.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+#ifndef NDEBUG
+static void* baseOfRenderObjectBeingDeleted;
+#endif
+
+bool RenderObject::s_affectsParentBlock = false;
+
+void* RenderObject::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void RenderObject::operator delete(void* ptr, size_t sz)
+{
+    ASSERT(baseOfRenderObjectBeingDeleted == ptr);
+
+    // Stash size where destroy can find it.
+    *(size_t *)ptr = sz;
+}
+
+RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
+{
+    Document* doc = node->document();
+    RenderArena* arena = doc->renderArena();
+
+    // Minimal support for content properties replacing an entire element.
+    // Works only if we have exactly one piece of content and it's a URL.
+    // Otherwise acts as if we didn't support this feature.
+    const ContentData* contentData = style->contentData();
+    if (contentData && !contentData->m_next && contentData->m_type == CONTENT_OBJECT && doc != node) {
+        RenderImageGeneratedContent* image = new (arena) RenderImageGeneratedContent(node);
+        image->setStyle(style);
+        if (StyleImage* styleImage = contentData->m_content.m_image)
+            image->setStyleImage(styleImage);
+        return image;
+    }
+
+    RenderObject* o = 0;
+
+    switch (style->display()) {
+        case NONE:
+            break;
+        case INLINE:
+            o = new (arena) RenderInline(node);
+            break;
+        case BLOCK:
+            o = new (arena) RenderBlock(node);
+            break;
+        case INLINE_BLOCK:
+            o = new (arena) RenderBlock(node);
+            break;
+        case LIST_ITEM:
+            o = new (arena) RenderListItem(node);
+            break;
+        case RUN_IN:
+        case COMPACT:
+            o = new (arena) RenderBlock(node);
+            break;
+        case TABLE:
+        case INLINE_TABLE:
+            o = new (arena) RenderTable(node);
+            break;
+        case TABLE_ROW_GROUP:
+        case TABLE_HEADER_GROUP:
+        case TABLE_FOOTER_GROUP:
+            o = new (arena) RenderTableSection(node);
+            break;
+        case TABLE_ROW:
+            o = new (arena) RenderTableRow(node);
+            break;
+        case TABLE_COLUMN_GROUP:
+        case TABLE_COLUMN:
+            o = new (arena) RenderTableCol(node);
+            break;
+        case TABLE_CELL:
+            o = new (arena) RenderTableCell(node);
+            break;
+        case TABLE_CAPTION:
+            o = new (arena) RenderBlock(node);
+            break;
+        case BOX:
+        case INLINE_BOX:
+            o = new (arena) RenderFlexibleBox(node);
+            break;
+    }
+
+    return o;
+}
+
+#ifndef NDEBUG 
+static WTF::RefCountedLeakCounter renderObjectCounter("RenderObject");
+#endif
+
+RenderObject::RenderObject(Node* node)
+    : CachedResourceClient()
+    , m_style(0)
+    , m_node(node)
+    , m_parent(0)
+    , m_previous(0)
+    , m_next(0)
+#ifndef NDEBUG
+    , m_hasAXObject(false)
+#endif
+    , m_verticalPosition(PositionUndefined)
+    , m_needsLayout(false)
+    , m_needsPositionedMovementLayout(false)
+    , m_normalChildNeedsLayout(false)
+    , m_posChildNeedsLayout(false)
+    , m_prefWidthsDirty(false)
+    , m_floating(false)
+    , m_positioned(false)
+    , m_relPositioned(false)
+    , m_paintBackground(false)
+    , m_isAnonymous(node == node->document())
+    , m_isText(false)
+    , m_inline(true)
+    , m_replaced(false)
+    , m_isDragging(false)
+    , m_hasLayer(false)
+    , m_hasOverflowClip(false)
+    , m_hasTransform(false)
+    , m_hasReflection(false)
+    , m_hasOverrideSize(false)
+    , m_hasCounterNodeMap(false)
+    , m_everHadLayout(false)
+{
+#ifndef NDEBUG
+    renderObjectCounter.increment();
+#endif
+}
+
+RenderObject::~RenderObject()
+{
+    ASSERT(!node() || documentBeingDestroyed() || !document()->frame()->view() || document()->frame()->view()->layoutRoot() != this);
+#ifndef NDEBUG
+    ASSERT(!m_hasAXObject);
+    renderObjectCounter.decrement();
+#endif
+}
+
+bool RenderObject::isDescendantOf(const RenderObject* obj) const
+{
+    for (const RenderObject* r = this; r; r = r->m_parent) {
+        if (r == obj)
+            return true;
+    }
+    return false;
+}
+
+bool RenderObject::isBody() const
+{
+    return node()->hasTagName(bodyTag);
+}
+
+bool RenderObject::isHR() const
+{
+    return element() && element()->hasTagName(hrTag);
+}
+
+bool RenderObject::isHTMLMarquee() const
+{
+    return element() && element()->renderer() == this && element()->hasTagName(marqueeTag);
+}
+
+bool RenderObject::canHaveChildren() const
+{
+    return false;
+}
+
+RenderFlow* RenderObject::continuation() const
+{
+    return 0;
+}
+
+bool RenderObject::isInlineContinuation() const
+{
+    return false;
+}
+
+void RenderObject::addChild(RenderObject*, RenderObject*)
+{
+    ASSERT_NOT_REACHED();
+}
+
+RenderObject* RenderObject::removeChildNode(RenderObject*, bool)
+{
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+void RenderObject::removeChild(RenderObject*)
+{
+    ASSERT_NOT_REACHED();
+}
+
+void RenderObject::moveChildNode(RenderObject*)
+{
+    ASSERT_NOT_REACHED();
+}
+
+void RenderObject::appendChildNode(RenderObject*, bool)
+{
+    ASSERT_NOT_REACHED();
+}
+
+void RenderObject::insertChildNode(RenderObject*, RenderObject*, bool)
+{
+    ASSERT_NOT_REACHED();
+}
+
+RenderObject* RenderObject::nextInPreOrder() const
+{
+    if (RenderObject* o = firstChild())
+        return o;
+
+    return nextInPreOrderAfterChildren();
+}
+
+RenderObject* RenderObject::nextInPreOrderAfterChildren() const
+{
+    RenderObject* o;
+    if (!(o = nextSibling())) {
+        o = parent();
+        while (o && !o->nextSibling())
+            o = o->parent();
+        if (o)
+            o = o->nextSibling();
+    }
+
+    return o;
+}
+
+RenderObject* RenderObject::nextInPreOrder(RenderObject* stayWithin) const
+{
+    if (RenderObject* o = firstChild())
+        return o;
+
+    return nextInPreOrderAfterChildren(stayWithin);
+}
+
+RenderObject* RenderObject::nextInPreOrderAfterChildren(RenderObject* stayWithin) const
+{
+    if (this == stayWithin)
+        return 0;
+
+    RenderObject* o;
+    if (!(o = nextSibling())) {
+        o = parent();
+        while (o && !o->nextSibling()) {
+            o = o->parent();
+            if (o == stayWithin)
+                return 0;
+        }
+        if (o)
+            o = o->nextSibling();
+    }
+
+    return o;
+}
+
+RenderObject* RenderObject::previousInPreOrder() const
+{
+    if (RenderObject* o = previousSibling()) {
+        while (o->lastChild())
+            o = o->lastChild();
+        return o;
+    }
+
+    return parent();
+}
+
+RenderObject* RenderObject::childAt(unsigned index) const
+{
+    RenderObject* child = firstChild();
+    for (unsigned i = 0; child && i < index; i++)
+        child = child->nextSibling();
+    return child;
+}
+
+bool RenderObject::isEditable() const
+{
+    RenderText* textRenderer = 0;
+    if (isText())
+        textRenderer = static_cast<RenderText*>(const_cast<RenderObject*>(this));
+
+    return style()->visibility() == VISIBLE &&
+        element() && element()->isContentEditable() &&
+        ((isBlockFlow() && !firstChild()) ||
+        isReplaced() ||
+        isBR() ||
+        (textRenderer && textRenderer->firstTextBox()));
+}
+
+RenderObject* RenderObject::firstLeafChild() const
+{
+    RenderObject* r = firstChild();
+    while (r) {
+        RenderObject* n = 0;
+        n = r->firstChild();
+        if (!n)
+            break;
+        r = n;
+    }
+    return r;
+}
+
+RenderObject* RenderObject::lastLeafChild() const
+{
+    RenderObject* r = lastChild();
+    while (r) {
+        RenderObject* n = 0;
+        n = r->lastChild();
+        if (!n)
+            break;
+        r = n;
+    }
+    return r;
+}
+
+static void addLayers(RenderObject* obj, RenderLayer* parentLayer, RenderObject*& newObject,
+                      RenderLayer*& beforeChild)
+{
+    if (obj->hasLayer()) {
+        if (!beforeChild && newObject) {
+            // We need to figure out the layer that follows newObject.  We only do
+            // this the first time we find a child layer, and then we update the
+            // pointer values for newObject and beforeChild used by everyone else.
+            beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
+            newObject = 0;
+        }
+        parentLayer->addChild(obj->layer(), beforeChild);
+        return;
+    }
+
+    for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling())
+        addLayers(curr, parentLayer, newObject, beforeChild);
+}
+
+void RenderObject::addLayers(RenderLayer* parentLayer, RenderObject* newObject)
+{
+    if (!parentLayer)
+        return;
+
+    RenderObject* object = newObject;
+    RenderLayer* beforeChild = 0;
+    WebCore::addLayers(this, parentLayer, object, beforeChild);
+}
+
+void RenderObject::removeLayers(RenderLayer* parentLayer)
+{
+    if (!parentLayer)
+        return;
+
+    if (hasLayer()) {
+        parentLayer->removeChild(layer());
+        return;
+    }
+
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+        curr->removeLayers(parentLayer);
+}
+
+void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
+{
+    if (!newParent)
+        return;
+
+    if (hasLayer()) {
+        if (oldParent)
+            oldParent->removeChild(layer());
+        newParent->addChild(layer());
+        return;
+    }
+
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+        curr->moveLayers(oldParent, newParent);
+}
+
+RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint,
+                                         bool checkParent)
+{
+    // Error check the parent layer passed in.  If it's null, we can't find anything.
+    if (!parentLayer)
+        return 0;
+
+    // Step 1: If our layer is a child of the desired parent, then return our layer.
+    RenderLayer* ourLayer = layer();
+    if (ourLayer && ourLayer->parent() == parentLayer)
+        return ourLayer;
+
+    // Step 2: If we don't have a layer, or our layer is the desired parent, then descend
+    // into our siblings trying to find the next layer whose parent is the desired parent.
+    if (!ourLayer || ourLayer == parentLayer) {
+        for (RenderObject* curr = startPoint ? startPoint->nextSibling() : firstChild();
+             curr; curr = curr->nextSibling()) {
+            RenderLayer* nextLayer = curr->findNextLayer(parentLayer, 0, false);
+            if (nextLayer)
+                return nextLayer;
+        }
+    }
+
+    // Step 3: If our layer is the desired parent layer, then we're finished.  We didn't
+    // find anything.
+    if (parentLayer == ourLayer)
+        return 0;
+
+    // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that
+    // follow us to see if we can locate a layer.
+    if (checkParent && parent())
+        return parent()->findNextLayer(parentLayer, this, true);
+
+    return 0;
+}
+
+RenderLayer* RenderObject::enclosingLayer() const
+{
+    const RenderObject* curr = this;
+    while (curr) {
+        RenderLayer* layer = curr->layer();
+        if (layer)
+            return layer;
+        curr = curr->parent();
+    }
+    return 0;
+}
+
+bool RenderObject::requiresLayer()
+{
+    return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection();
+}
+
+RenderBlock* RenderObject::firstLineBlock() const
+{
+    return 0;
+}
+
+int RenderObject::offsetLeft() const
+{
+    RenderObject* offsetPar = offsetParent();
+    if (!offsetPar)
+        return 0;
+    int x = xPos() - offsetPar->borderLeft();
+    if (!isPositioned()) {
+        if (isRelPositioned())
+            x += static_cast<const RenderBox*>(this)->relativePositionOffsetX();
+        RenderObject* curr = parent();
+        while (curr && curr != offsetPar) {
+            x += curr->xPos();
+            curr = curr->parent();
+        }
+        if (offsetPar->isBody() && !offsetPar->isRelPositioned() && !offsetPar->isPositioned())
+            x += offsetPar->xPos();
+    }
+    return x;
+}
+
+int RenderObject::offsetTop() const
+{
+    RenderObject* offsetPar = offsetParent();
+    if (!offsetPar)
+        return 0;
+#ifdef ANDROID_FIX
+    // This is to fix https://bugs.webkit.org/show_bug.cgi?id=23178.
+    int y = yPos() - borderTopExtra() + offsetPar->borderTopExtra() - offsetPar->borderTop();
+#else
+    int y = yPos() - borderTopExtra() - offsetPar->borderTop();
+#endif
+    if (!isPositioned()) {
+        if (isRelPositioned())
+            y += static_cast<const RenderBox*>(this)->relativePositionOffsetY();
+        RenderObject* curr = parent();
+        while (curr && curr != offsetPar) {
+            if (!curr->isTableRow())
+                y += curr->yPos();
+            curr = curr->parent();
+        }
+        if (offsetPar->isBody() && !offsetPar->isRelPositioned() && !offsetPar->isPositioned())
+            y += offsetPar->yPos();
+    }
+    return y;
+}
+
+RenderObject* RenderObject::offsetParent() const
+{
+    // FIXME: It feels like this function could almost be written using containing blocks.
+    if (isBody())
+        return 0;
+
+    bool skipTables = isPositioned() || isRelPositioned();
+    float currZoom = style()->effectiveZoom();
+    RenderObject* curr = parent();
+    while (curr && (!curr->element() ||
+                    (!curr->isPositioned() && !curr->isRelPositioned() && !curr->isBody()))) {
+        if (!skipTables && curr->element() && (curr->element()->hasTagName(tableTag) || 
+                                               curr->element()->hasTagName(tdTag) || curr->element()->hasTagName(thTag)))
+            break;
+        float newZoom = curr->style()->effectiveZoom();
+        if (currZoom != newZoom)
+            break;
+        currZoom = newZoom;
+        curr = curr->parent();
+    }
+    return curr;
+}
+
+int RenderObject::verticalScrollbarWidth() const
+{
+    return includeVerticalScrollbarSize() ? layer()->verticalScrollbarWidth() : 0;
+}
+
+int RenderObject::horizontalScrollbarHeight() const
+{
+    return includeHorizontalScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0;
+}
+
+// More IE extensions.  clientWidth and clientHeight represent the interior of an object
+// excluding border and scrollbar.
+int RenderObject::clientWidth() const
+{
+    return width() - borderLeft() - borderRight() - verticalScrollbarWidth();
+}
+
+int RenderObject::clientHeight() const
+{
+    return height() - borderTop() - borderBottom() - horizontalScrollbarHeight();
+}
+
+// scrollWidth/scrollHeight will be the same as clientWidth/clientHeight unless the
+// object has overflow:hidden/scroll/auto specified and also has overflow.
+int RenderObject::scrollWidth() const
+{
+    return hasOverflowClip() ? layer()->scrollWidth() : overflowWidth();
+}
+
+int RenderObject::scrollHeight() const
+{
+    return hasOverflowClip() ? layer()->scrollHeight() : overflowHeight();
+}
+
+int RenderObject::scrollLeft() const
+{
+    return hasOverflowClip() ? layer()->scrollXOffset() : 0;
+}
+
+int RenderObject::scrollTop() const
+{
+    return hasOverflowClip() ? layer()->scrollYOffset() : 0;
+}
+
+void RenderObject::setScrollLeft(int newLeft)
+{
+    if (hasOverflowClip())
+        layer()->scrollToXOffset(newLeft);
+}
+
+void RenderObject::setScrollTop(int newTop)
+{
+    if (hasOverflowClip())
+        layer()->scrollToYOffset(newTop);
+}
+
+bool RenderObject::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
+{
+    RenderLayer* l = layer();
+    if (l && l->scroll(direction, granularity, multiplier))
+        return true;
+    RenderBlock* b = containingBlock();
+    if (b && !b->isRenderView())
+        return b->scroll(direction, granularity, multiplier);
+    return false;
+}
+    
+bool RenderObject::canBeProgramaticallyScrolled(bool scrollToAnchor) const
+{
+    if (!layer())
+        return false;
+
+    return (hasOverflowClip() && (scrollsOverflow() || (node() && node()->isContentEditable()))) || (node() && node()->isDocumentNode());
+}
+
+void RenderObject::autoscroll()
+{
+    layer()->autoscroll();
+}
+
+void RenderObject::panScroll(const IntPoint& source)
+{
+    layer()->panScrollFromPoint(source);
+}
+
+bool RenderObject::hasStaticX() const
+{
+    return (style()->left().isAuto() && style()->right().isAuto()) || style()->left().isStatic() || style()->right().isStatic();
+}
+
+bool RenderObject::hasStaticY() const
+{
+    return (style()->top().isAuto() && style()->bottom().isAuto()) || style()->top().isStatic();
+}
+
+void RenderObject::markAllDescendantsWithFloatsForLayout(RenderObject*)
+{
+}
+
+void RenderObject::setPrefWidthsDirty(bool b, bool markParents)
+{
+    bool alreadyDirty = m_prefWidthsDirty;
+    m_prefWidthsDirty = b;
+    if (b && !alreadyDirty && markParents && (isText() || (style()->position() != FixedPosition && style()->position() != AbsolutePosition)))
+        invalidateContainerPrefWidths();
+}
+
+void RenderObject::invalidateContainerPrefWidths()
+{
+    // In order to avoid pathological behavior when inlines are deeply nested, we do include them
+    // in the chain that we mark dirty (even though they're kind of irrelevant).
+    RenderObject* o = isTableCell() ? containingBlock() : container();
+    while (o && !o->m_prefWidthsDirty) {
+        o->m_prefWidthsDirty = true;
+        if (o->style()->position() == FixedPosition || o->style()->position() == AbsolutePosition)
+            // A positioned object has no effect on the min/max width of its containing block ever.
+            // We can optimize this case and not go up any further.
+            break;
+        o = o->isTableCell() ? o->containingBlock() : o->container();
+    }
+}
+
+void RenderObject::setNeedsLayout(bool b, bool markParents)
+{
+    bool alreadyNeededLayout = m_needsLayout;
+    m_needsLayout = b;
+    if (b) {
+        if (!alreadyNeededLayout) {
+            if (markParents)
+                markContainingBlocksForLayout();
+            if (hasLayer())
+                layer()->setNeedsFullRepaint();
+        }
+    } else {
+        m_everHadLayout = true;
+        m_posChildNeedsLayout = false;
+        m_normalChildNeedsLayout = false;
+        m_needsPositionedMovementLayout = false;
+    }
+}
+
+void RenderObject::setChildNeedsLayout(bool b, bool markParents)
+{
+    bool alreadyNeededLayout = m_normalChildNeedsLayout;
+    m_normalChildNeedsLayout = b;
+    if (b) {
+        if (!alreadyNeededLayout && markParents)
+            markContainingBlocksForLayout();
+    } else {
+        m_posChildNeedsLayout = false;
+        m_normalChildNeedsLayout = false;
+        m_needsPositionedMovementLayout = false;
+    }
+}
+
+void RenderObject::setNeedsPositionedMovementLayout()
+{
+    bool alreadyNeededLayout = needsLayout();
+    m_needsPositionedMovementLayout = true;
+    if (!alreadyNeededLayout) {
+        markContainingBlocksForLayout();
+        if (hasLayer())
+            layer()->setNeedsFullRepaint();
+    }
+}
+
+static inline bool objectIsRelayoutBoundary(const RenderObject *obj) 
+{
+    // FIXME: In future it may be possible to broaden this condition in order to improve performance.
+    // Table cells are excluded because even when their CSS height is fixed, their height()
+    // may depend on their contents.
+    return obj->isTextField() || obj->isTextArea()
+        || obj->hasOverflowClip() && !obj->style()->width().isIntrinsicOrAuto() && !obj->style()->height().isIntrinsicOrAuto() && !obj->style()->height().isPercent() && !obj->isTableCell()
+#if ENABLE(SVG)
+           || obj->isSVGRoot()
+#endif
+           ;
+}
+    
+void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, RenderObject* newRoot)
+{
+    ASSERT(!scheduleRelayout || !newRoot);
+
+    RenderObject* o = container();
+    RenderObject* last = this;
+
+    while (o) {
+        if (!last->isText() && (last->style()->position() == FixedPosition || last->style()->position() == AbsolutePosition)) {
+            if (last->hasStaticY()) {
+                RenderObject* parent = last->parent();
+                if (!parent->normalChildNeedsLayout()) {
+                    parent->setChildNeedsLayout(true, false);
+                    if (parent != newRoot)
+                        parent->markContainingBlocksForLayout(scheduleRelayout, newRoot);
+                }
+            }
+            if (o->m_posChildNeedsLayout)
+                return;
+            o->m_posChildNeedsLayout = true;
+        } else {
+            if (o->m_normalChildNeedsLayout)
+                return;
+            o->m_normalChildNeedsLayout = true;
+        }
+
+        if (o == newRoot)
+            return;
+
+        last = o;
+        if (scheduleRelayout && objectIsRelayoutBoundary(last))
+            break;
+        o = o->container();
+    }
+
+    if (scheduleRelayout)
+        last->scheduleRelayout();
+}
+
+RenderBlock* RenderObject::containingBlock() const
+{
+    if (isTableCell()) {
+        const RenderTableCell* cell = static_cast<const RenderTableCell*>(this);
+        if (parent() && cell->section())
+            return cell->table();
+        return 0;
+    }
+
+    if (isRenderView())
+        return const_cast<RenderBlock*>(static_cast<const RenderBlock*>(this));
+
+    RenderObject* o = parent();
+    if (!isText() && m_style->position() == FixedPosition) {
+        while (o && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock()))
+            o = o->parent();
+    } else if (!isText() && m_style->position() == AbsolutePosition) {
+        while (o && (o->style()->position() == StaticPosition || (o->isInline() && !o->isReplaced())) && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock())) {
+            // For relpositioned inlines, we return the nearest enclosing block.  We don't try
+            // to return the inline itself.  This allows us to avoid having a positioned objects
+            // list in all RenderInlines and lets us return a strongly-typed RenderBlock* result
+            // from this method.  The container() method can actually be used to obtain the
+            // inline directly.
+            if (o->style()->position() == RelativePosition && o->isInline() && !o->isReplaced())
+                return o->containingBlock();
+            o = o->parent();
+        }
+    } else {
+        while (o && ((o->isInline() && !o->isReplaced()) || o->isTableRow() || o->isTableSection()
+                     || o->isTableCol() || o->isFrameSet() || o->isMedia()
+#if ENABLE(SVG)
+                     || o->isSVGContainer() || o->isSVGRoot()
+#endif
+                     ))
+            o = o->parent();
+    }
+
+    if (!o || !o->isRenderBlock())
+        return 0; // Probably doesn't happen any more, but leave just in case. -dwh
+
+    return static_cast<RenderBlock*>(o);
+}
+
+int RenderObject::containingBlockWidth() const
+{
+    // FIXME ?
+    return containingBlock()->availableWidth();
+}
+
+int RenderObject::containingBlockHeight() const
+{
+    // FIXME ?
+    return containingBlock()->contentHeight();
+}
+
+static bool mustRepaintFillLayers(const RenderObject* renderer, const FillLayer* layer)
+{
+    // Nobody will use multiple layers without wanting fancy positioning.
+    if (layer->next())
+        return true;
+
+    // Make sure we have a valid image.
+    StyleImage* img = layer->image();
+    bool shouldPaintBackgroundImage = img && img->canRender(renderer->style()->effectiveZoom());
+
+    // These are always percents or auto.
+    if (shouldPaintBackgroundImage &&
+        (!layer->xPosition().isZero() || !layer->yPosition().isZero() ||
+         layer->size().width().isPercent() || layer->size().height().isPercent()))
+        // The image will shift unpredictably if the size changes.
+        return true;
+
+    return false;
+}
+
+bool RenderObject::mustRepaintBackgroundOrBorder() const
+{
+    if (hasMask() && mustRepaintFillLayers(this, style()->maskLayers()))
+        return true;
+
+    // If we don't have a background/border/mask, then nothing to do.
+    if (!hasBoxDecorations())
+        return false;
+
+    if (mustRepaintFillLayers(this, style()->backgroundLayers()))
+        return true;
+     
+    // Our fill layers are ok.  Let's check border.
+    if (style()->hasBorder()) {
+        // Border images are not ok.
+        StyleImage* borderImage = style()->borderImage().image();
+        bool shouldPaintBorderImage = borderImage && borderImage->canRender(style()->effectiveZoom());
+
+        // If the image hasn't loaded, we're still using the normal border style.
+        if (shouldPaintBorderImage && borderImage->isLoaded())
+            return true;
+    }
+
+    return false;
+}
+
+void RenderObject::drawBorderArc(GraphicsContext* graphicsContext, int x, int y, float thickness, IntSize radius,
+                                 int angleStart, int angleSpan, BorderSide s, Color c, const Color& textColor,
+                                 EBorderStyle style, bool firstCorner)
+{
+    if ((style == DOUBLE && thickness / 2 < 3) || ((style == RIDGE || style == GROOVE) && thickness / 2 < 2))
+        style = SOLID;
+
+    if (!c.isValid()) {
+        if (style == INSET || style == OUTSET || style == RIDGE || style == GROOVE)
+            c.setRGB(238, 238, 238);
+        else
+            c = textColor;
+    }
+
+    switch (style) {
+        case BNONE:
+        case BHIDDEN:
+            return;
+        case DOTTED:
+        case DASHED:
+            graphicsContext->setStrokeColor(c);
+            graphicsContext->setStrokeStyle(style == DOTTED ? DottedStroke : DashedStroke);
+            graphicsContext->setStrokeThickness(thickness);
+            graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
+            break;
+        case DOUBLE: {
+            float third = thickness / 3.0f;
+            float innerThird = (thickness + 1.0f) / 6.0f;
+            int shiftForInner = static_cast<int>(innerThird * 2.5f);
+
+            int outerY = y;
+            int outerHeight = radius.height() * 2;
+            int innerX = x + shiftForInner;
+            int innerY = y + shiftForInner;
+            int innerWidth = (radius.width() - shiftForInner) * 2;
+            int innerHeight = (radius.height() - shiftForInner) * 2;
+            if (innerThird > 1 && (s == BSTop || (firstCorner && (s == BSLeft || s == BSRight)))) {
+                outerHeight += 2;
+                innerHeight += 2;
+            }
+
+            graphicsContext->setStrokeStyle(SolidStroke);
+            graphicsContext->setStrokeColor(c);
+            graphicsContext->setStrokeThickness(third);
+            graphicsContext->strokeArc(IntRect(x, outerY, radius.width() * 2, outerHeight), angleStart, angleSpan);
+            graphicsContext->setStrokeThickness(innerThird > 2 ? innerThird - 1 : innerThird);
+            graphicsContext->strokeArc(IntRect(innerX, innerY, innerWidth, innerHeight), angleStart, angleSpan);
+            break;
+        }
+        case GROOVE:
+        case RIDGE: {
+            Color c2;
+            if ((style == RIDGE && (s == BSTop || s == BSLeft)) ||
+                    (style == GROOVE && (s == BSBottom || s == BSRight)))
+                c2 = c.dark();
+            else {
+                c2 = c;
+                c = c.dark();
+            }
+
+            graphicsContext->setStrokeStyle(SolidStroke);
+            graphicsContext->setStrokeColor(c);
+            graphicsContext->setStrokeThickness(thickness);
+            graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
+
+            float halfThickness = (thickness + 1.0f) / 4.0f;
+            int shiftForInner = static_cast<int>(halfThickness * 1.5f);
+            graphicsContext->setStrokeColor(c2);
+            graphicsContext->setStrokeThickness(halfThickness > 2 ? halfThickness - 1 : halfThickness);
+            graphicsContext->strokeArc(IntRect(x + shiftForInner, y + shiftForInner, (radius.width() - shiftForInner) * 2,
+                                       (radius.height() - shiftForInner) * 2), angleStart, angleSpan);
+            break;
+        }
+        case INSET:
+            if (s == BSTop || s == BSLeft)
+                c = c.dark();
+        case OUTSET:
+            if (style == OUTSET && (s == BSBottom || s == BSRight))
+                c = c.dark();
+        case SOLID:
+            graphicsContext->setStrokeStyle(SolidStroke);
+            graphicsContext->setStrokeColor(c);
+            graphicsContext->setStrokeThickness(thickness);
+            graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
+            break;
+    }
+}
+
+void RenderObject::drawBorder(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2,
+                              BorderSide s, Color c, const Color& textcolor, EBorderStyle style,
+                              int adjbw1, int adjbw2)
+{
+    int width = (s == BSTop || s == BSBottom ? y2 - y1 : x2 - x1);
+
+    if (style == DOUBLE && width < 3)
+        style = SOLID;
+
+    if (!c.isValid()) {
+        if (style == INSET || style == OUTSET || style == RIDGE || style == GROOVE)
+            c.setRGB(238, 238, 238);
+        else
+            c = textcolor;
+    }
+
+    switch (style) {
+        case BNONE:
+        case BHIDDEN:
+            return;
+        case DOTTED:
+        case DASHED:
+            graphicsContext->setStrokeColor(c);
+            graphicsContext->setStrokeThickness(width);
+            graphicsContext->setStrokeStyle(style == DASHED ? DashedStroke : DottedStroke);
+
+            if (width > 0)
+                switch (s) {
+                    case BSBottom:
+                    case BSTop:
+                        graphicsContext->drawLine(IntPoint(x1, (y1 + y2) / 2), IntPoint(x2, (y1 + y2) / 2));
+                        break;
+                    case BSRight:
+                    case BSLeft:
+                        graphicsContext->drawLine(IntPoint((x1 + x2) / 2, y1), IntPoint((x1 + x2) / 2, y2));
+                        break;
+                }
+            break;
+        case DOUBLE: {
+            int third = (width + 1) / 3;
+
+            if (adjbw1 == 0 && adjbw2 == 0) {
+                graphicsContext->setStrokeStyle(NoStroke);
+                graphicsContext->setFillColor(c);
+                switch (s) {
+                    case BSTop:
+                    case BSBottom:
+                        graphicsContext->drawRect(IntRect(x1, y1, x2 - x1, third));
+                        graphicsContext->drawRect(IntRect(x1, y2 - third, x2 - x1, third));
+                        break;
+                    case BSLeft:
+                        graphicsContext->drawRect(IntRect(x1, y1 + 1, third, y2 - y1 - 1));
+                        graphicsContext->drawRect(IntRect(x2 - third, y1 + 1, third, y2 - y1 - 1));
+                        break;
+                    case BSRight:
+                        graphicsContext->drawRect(IntRect(x1, y1 + 1, third, y2 - y1 - 1));
+                        graphicsContext->drawRect(IntRect(x2 - third, y1 + 1, third, y2 - y1 - 1));
+                        break;
+                }
+            } else {
+                int adjbw1bigthird = ((adjbw1 > 0) ? adjbw1 + 1 : adjbw1 - 1) / 3;
+                int adjbw2bigthird = ((adjbw2 > 0) ? adjbw2 + 1 : adjbw2 - 1) / 3;
+
+                switch (s) {
+                    case BSTop:
+                        drawBorder(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0),
+                                   y1, x2 - max((-adjbw2 * 2 + 1) / 3, 0), y1 + third,
+                                   s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+                        drawBorder(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0),
+                                   y2 - third, x2 - max((adjbw2 * 2 + 1) / 3, 0), y2,
+                                   s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+                        break;
+                    case BSLeft:
+                        drawBorder(graphicsContext, x1, y1 + max((-adjbw1 * 2 + 1) / 3, 0),
+                                   x1 + third, y2 - max((-adjbw2 * 2 + 1) / 3, 0),
+                                   s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+                        drawBorder(graphicsContext, x2 - third, y1 + max((adjbw1 * 2 + 1) / 3, 0),
+                                   x2, y2 - max((adjbw2 * 2 + 1) / 3, 0),
+                                   s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+                        break;
+                    case BSBottom:
+                        drawBorder(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0),
+                                   y1, x2 - max((adjbw2 * 2 + 1) / 3, 0), y1 + third,
+                                   s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+                        drawBorder(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0),
+                                   y2 - third, x2 - max((-adjbw2 * 2 + 1) / 3, 0), y2,
+                                   s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+                        break;
+                    case BSRight:
+                        drawBorder(graphicsContext, x1, y1 + max((adjbw1 * 2 + 1) / 3, 0),
+                                   x1 + third, y2 - max(( adjbw2 * 2 + 1) / 3, 0),
+                                   s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+                        drawBorder(graphicsContext, x2 - third, y1 + max((-adjbw1 * 2 + 1) / 3, 0),
+                                   x2, y2 - max((-adjbw2 * 2 + 1) / 3, 0),
+                                   s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+                        break;
+                    default:
+                        break;
+                }
+            }
+            break;
+        }
+        case RIDGE:
+        case GROOVE:
+        {
+            EBorderStyle s1;
+            EBorderStyle s2;
+            if (style == GROOVE) {
+                s1 = INSET;
+                s2 = OUTSET;
+            } else {
+                s1 = OUTSET;
+                s2 = INSET;
+            }
+
+            int adjbw1bighalf = ((adjbw1 > 0) ? adjbw1 + 1 : adjbw1 - 1) / 2;
+            int adjbw2bighalf = ((adjbw2 > 0) ? adjbw2 + 1 : adjbw2 - 1) / 2;
+
+            switch (s) {
+                case BSTop:
+                    drawBorder(graphicsContext, x1 + max(-adjbw1, 0) / 2, y1, x2 - max(-adjbw2, 0) / 2, (y1 + y2 + 1) / 2,
+                               s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
+                    drawBorder(graphicsContext, x1 + max(adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(adjbw2 + 1, 0) / 2, y2,
+                               s, c, textcolor, s2, adjbw1 / 2, adjbw2 / 2);
+                    break;
+                case BSLeft:
+                    drawBorder(graphicsContext, x1, y1 + max(-adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(-adjbw2, 0) / 2,
+                               s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
+                    drawBorder(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(adjbw1 + 1, 0) / 2, x2, y2 - max(adjbw2 + 1, 0) / 2,
+                               s, c, textcolor, s2, adjbw1 / 2, adjbw2 / 2);
+                    break;
+                case BSBottom:
+                    drawBorder(graphicsContext, x1 + max(adjbw1, 0) / 2, y1, x2 - max(adjbw2, 0) / 2, (y1 + y2 + 1) / 2,
+                               s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
+                    drawBorder(graphicsContext, x1 + max(-adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(-adjbw2 + 1, 0) / 2, y2,
+                               s, c, textcolor, s1, adjbw1/2, adjbw2/2);
+                    break;
+                case BSRight:
+                    drawBorder(graphicsContext, x1, y1 + max(adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(adjbw2, 0) / 2,
+                               s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
+                    drawBorder(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(-adjbw1 + 1, 0) / 2, x2, y2 - max(-adjbw2 + 1, 0) / 2,
+                               s, c, textcolor, s1, adjbw1/2, adjbw2/2);
+                    break;
+            }
+            break;
+        }
+        case INSET:
+            if (s == BSTop || s == BSLeft)
+                c = c.dark();
+            // fall through
+        case OUTSET:
+            if (style == OUTSET && (s == BSBottom || s == BSRight))
+                c = c.dark();
+            // fall through
+        case SOLID: {
+            graphicsContext->setStrokeStyle(NoStroke);
+            graphicsContext->setFillColor(c);
+            ASSERT(x2 >= x1);
+            ASSERT(y2 >= y1);
+            if (!adjbw1 && !adjbw2) {
+                graphicsContext->drawRect(IntRect(x1, y1, x2 - x1, y2 - y1));
+                return;
+            }
+            FloatPoint quad[4];
+            switch (s) {
+                case BSTop:
+                    quad[0] = FloatPoint(x1 + max(-adjbw1, 0), y1);
+                    quad[1] = FloatPoint(x1 + max(adjbw1, 0), y2);
+                    quad[2] = FloatPoint(x2 - max(adjbw2, 0), y2);
+                    quad[3] = FloatPoint(x2 - max(-adjbw2, 0), y1);
+                    break;
+                case BSBottom:
+                    quad[0] = FloatPoint(x1 + max(adjbw1, 0), y1);
+                    quad[1] = FloatPoint(x1 + max(-adjbw1, 0), y2);
+                    quad[2] = FloatPoint(x2 - max(-adjbw2, 0), y2);
+                    quad[3] = FloatPoint(x2 - max(adjbw2, 0), y1);
+                    break;
+                case BSLeft:
+                    quad[0] = FloatPoint(x1, y1 + max(-adjbw1, 0));
+                    quad[1] = FloatPoint(x1, y2 - max(-adjbw2, 0));
+                    quad[2] = FloatPoint(x2, y2 - max(adjbw2, 0));
+                    quad[3] = FloatPoint(x2, y1 + max(adjbw1, 0));
+                    break;
+                case BSRight:
+                    quad[0] = FloatPoint(x1, y1 + max(adjbw1, 0));
+                    quad[1] = FloatPoint(x1, y2 - max(adjbw2, 0));
+                    quad[2] = FloatPoint(x2, y2 - max(-adjbw2, 0));
+                    quad[3] = FloatPoint(x2, y1 + max(-adjbw1, 0));
+                    break;
+            }
+            graphicsContext->drawConvexPolygon(4, quad);
+            break;
+        }
+    }
+}
+
+bool RenderObject::paintNinePieceImage(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style,
+                                       const NinePieceImage& ninePieceImage, CompositeOperator op)
+{
+    StyleImage* styleImage = ninePieceImage.image();
+    if (!styleImage || !styleImage->canRender(style->effectiveZoom()))
+        return false;
+
+    if (!styleImage->isLoaded())
+        return true; // Never paint a nine-piece image incrementally, but don't paint the fallback borders either.
+
+    // If we have a border radius, the image gets clipped to the rounded rect.
+    bool clipped = false;
+    if (style->hasBorderRadius()) {
+        IntRect clipRect(tx, ty, w, h);
+        graphicsContext->save();
+        graphicsContext->addRoundedRectClip(clipRect, style->borderTopLeftRadius(), style->borderTopRightRadius(),
+                                            style->borderBottomLeftRadius(), style->borderBottomRightRadius());
+        clipped = true;
+    }
+
+    // FIXME: border-image is broken with full page zooming when tiling has to happen, since the tiling function
+    // doesn't have any understanding of the zoom that is in effect on the tile.
+    styleImage->setImageContainerSize(IntSize(w, h));
+    IntSize imageSize = styleImage->imageSize(this, 1.0f);
+    int imageWidth = imageSize.width();
+    int imageHeight = imageSize.height();
+
+    int topSlice = min(imageHeight, ninePieceImage.m_slices.top().calcValue(imageHeight));
+    int bottomSlice = min(imageHeight, ninePieceImage.m_slices.bottom().calcValue(imageHeight));
+    int leftSlice = min(imageWidth, ninePieceImage.m_slices.left().calcValue(imageWidth));
+    int rightSlice = min(imageWidth, ninePieceImage.m_slices.right().calcValue(imageWidth));
+
+    ENinePieceImageRule hRule = ninePieceImage.horizontalRule();
+    ENinePieceImageRule vRule = ninePieceImage.verticalRule();
+
+    bool fitToBorder = style->borderImage() == ninePieceImage;
+    
+    int leftWidth = fitToBorder ? style->borderLeftWidth() : leftSlice;
+    int topWidth = fitToBorder ? style->borderTopWidth() : topSlice;
+    int rightWidth = fitToBorder ? style->borderRightWidth() : rightSlice;
+    int bottomWidth = fitToBorder ? style->borderBottomWidth() : bottomSlice;
+
+    bool drawLeft = leftSlice > 0 && leftWidth > 0;
+    bool drawTop = topSlice > 0 && topWidth > 0;
+    bool drawRight = rightSlice > 0 && rightWidth > 0;
+    bool drawBottom = bottomSlice > 0 && bottomWidth > 0;
+    bool drawMiddle = (imageWidth - leftSlice - rightSlice) > 0 && (w - leftWidth - rightWidth) > 0 &&
+                      (imageHeight - topSlice - bottomSlice) > 0 && (h - topWidth - bottomWidth) > 0;
+
+    Image* image = styleImage->image(this, imageSize);
+
+    if (drawLeft) {
+        // Paint the top and bottom left corners.
+
+        // The top left corner rect is (tx, ty, leftWidth, topWidth)
+        // The rect to use from within the image is obtained from our slice, and is (0, 0, leftSlice, topSlice)
+        if (drawTop)
+            graphicsContext->drawImage(image, IntRect(tx, ty, leftWidth, topWidth),
+                                       IntRect(0, 0, leftSlice, topSlice), op);
+
+        // The bottom left corner rect is (tx, ty + h - bottomWidth, leftWidth, bottomWidth)
+        // The rect to use from within the image is (0, imageHeight - bottomSlice, leftSlice, botomSlice)
+        if (drawBottom)
+            graphicsContext->drawImage(image, IntRect(tx, ty + h - bottomWidth, leftWidth, bottomWidth),
+                                       IntRect(0, imageHeight - bottomSlice, leftSlice, bottomSlice), op);
+
+        // Paint the left edge.
+        // Have to scale and tile into the border rect.
+        graphicsContext->drawTiledImage(image, IntRect(tx, ty + topWidth, leftWidth,
+                                        h - topWidth - bottomWidth),
+                                        IntRect(0, topSlice, leftSlice, imageHeight - topSlice - bottomSlice),
+                                        Image::StretchTile, (Image::TileRule)vRule, op);
+    }
+
+    if (drawRight) {
+        // Paint the top and bottom right corners
+        // The top right corner rect is (tx + w - rightWidth, ty, rightWidth, topWidth)
+        // The rect to use from within the image is obtained from our slice, and is (imageWidth - rightSlice, 0, rightSlice, topSlice)
+        if (drawTop)
+            graphicsContext->drawImage(image, IntRect(tx + w - rightWidth, ty, rightWidth, topWidth),
+                                       IntRect(imageWidth - rightSlice, 0, rightSlice, topSlice), op);
+
+        // The bottom right corner rect is (tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth)
+        // The rect to use from within the image is (imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice)
+        if (drawBottom)
+            graphicsContext->drawImage(image, IntRect(tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth),
+                                       IntRect(imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice), op);
+
+        // Paint the right edge.
+        graphicsContext->drawTiledImage(image, IntRect(tx + w - rightWidth, ty + topWidth, rightWidth,
+                                        h - topWidth - bottomWidth),
+                                        IntRect(imageWidth - rightSlice, topSlice, rightSlice, imageHeight - topSlice - bottomSlice),
+                                        Image::StretchTile, (Image::TileRule)vRule, op);
+    }
+
+    // Paint the top edge.
+    if (drawTop)
+        graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty, w - leftWidth - rightWidth, topWidth),
+                                        IntRect(leftSlice, 0, imageWidth - rightSlice - leftSlice, topSlice),
+                                        (Image::TileRule)hRule, Image::StretchTile, op);
+
+    // Paint the bottom edge.
+    if (drawBottom)
+        graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty + h - bottomWidth,
+                                        w - leftWidth - rightWidth, bottomWidth),
+                                        IntRect(leftSlice, imageHeight - bottomSlice, imageWidth - rightSlice - leftSlice, bottomSlice),
+                                        (Image::TileRule)hRule, Image::StretchTile, op);
+
+    // Paint the middle.
+    if (drawMiddle)
+        graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty + topWidth, w - leftWidth - rightWidth,
+                                        h - topWidth - bottomWidth),
+                                        IntRect(leftSlice, topSlice, imageWidth - rightSlice - leftSlice, imageHeight - topSlice - bottomSlice),
+                                        (Image::TileRule)hRule, (Image::TileRule)vRule, op);
+
+    // Clear the clip for the border radius.
+    if (clipped)
+        graphicsContext->restore();
+
+    return true;
+}
+
+void RenderObject::paintBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
+                               const RenderStyle* style, bool begin, bool end)
+{
+    if (paintNinePieceImage(graphicsContext, tx, ty, w, h, style, style->borderImage()))
+        return;
+
+    const Color& tc = style->borderTopColor();
+    const Color& bc = style->borderBottomColor();
+    const Color& lc = style->borderLeftColor();
+    const Color& rc = style->borderRightColor();
+
+    bool tt = style->borderTopIsTransparent();
+    bool bt = style->borderBottomIsTransparent();
+    bool rt = style->borderRightIsTransparent();
+    bool lt = style->borderLeftIsTransparent();
+
+    EBorderStyle ts = style->borderTopStyle();
+    EBorderStyle bs = style->borderBottomStyle();
+    EBorderStyle ls = style->borderLeftStyle();
+    EBorderStyle rs = style->borderRightStyle();
+
+    bool renderTop = ts > BHIDDEN && !tt;
+    bool renderLeft = ls > BHIDDEN && begin && !lt;
+    bool renderRight = rs > BHIDDEN && end && !rt;
+    bool renderBottom = bs > BHIDDEN && !bt;
+
+    // Need sufficient width and height to contain border radius curves.  Sanity check our border radii
+    // and our width/height values to make sure the curves can all fit. If not, then we won't paint
+    // any border radii.
+    bool renderRadii = false;
+    IntSize topLeft = style->borderTopLeftRadius();
+    IntSize topRight = style->borderTopRightRadius();
+    IntSize bottomLeft = style->borderBottomLeftRadius();
+    IntSize bottomRight = style->borderBottomRightRadius();
+
+    if (style->hasBorderRadius() &&
+        static_cast<unsigned>(w) >= static_cast<unsigned>(topLeft.width()) + static_cast<unsigned>(topRight.width()) &&
+        static_cast<unsigned>(w) >= static_cast<unsigned>(bottomLeft.width()) + static_cast<unsigned>(bottomRight.width()) &&
+        static_cast<unsigned>(h) >= static_cast<unsigned>(topLeft.height()) + static_cast<unsigned>(bottomLeft.height()) &&
+        static_cast<unsigned>(h) >= static_cast<unsigned>(topRight.height()) + static_cast<unsigned>(bottomRight.height()))
+        renderRadii = true;
+
+    // Clip to the rounded rectangle.
+    if (renderRadii) {
+        graphicsContext->save();
+        graphicsContext->addRoundedRectClip(IntRect(tx, ty, w, h), topLeft, topRight, bottomLeft, bottomRight);
+    }
+
+    int firstAngleStart, secondAngleStart, firstAngleSpan, secondAngleSpan;
+    float thickness;
+    bool upperLeftBorderStylesMatch = renderLeft && (ts == ls) && (tc == lc);
+    bool upperRightBorderStylesMatch = renderRight && (ts == rs) && (tc == rc) && (ts != OUTSET) && (ts != RIDGE) && (ts != INSET) && (ts != GROOVE);
+    bool lowerLeftBorderStylesMatch = renderLeft && (bs == ls) && (bc == lc) && (bs != OUTSET) && (bs != RIDGE) && (bs != INSET) && (bs != GROOVE);
+    bool lowerRightBorderStylesMatch = renderRight && (bs == rs) && (bc == rc);
+
+    if (renderTop) {
+        bool ignore_left = (renderRadii && topLeft.width() > 0) ||
+            (tc == lc && tt == lt && ts >= OUTSET &&
+             (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET));
+
+        bool ignore_right = (renderRadii && topRight.width() > 0) ||
+            (tc == rc && tt == rt && ts >= OUTSET &&
+             (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET));
+
+        int x = tx;
+        int x2 = tx + w;
+        if (renderRadii) {
+            x += topLeft.width();
+            x2 -= topRight.width();
+        }
+
+        drawBorder(graphicsContext, x, ty, x2, ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
+                   ignore_left ? 0 : style->borderLeftWidth(), ignore_right ? 0 : style->borderRightWidth());
+
+        if (renderRadii) {
+            int leftY = ty;
+
+            // We make the arc double thick and let the clip rect take care of clipping the extra off.
+            // We're doing this because it doesn't seem possible to match the curve of the clip exactly
+            // with the arc-drawing function.
+            thickness = style->borderTopWidth() * 2;
+
+            if (topLeft.width()) {
+                int leftX = tx;
+                // The inner clip clips inside the arc. This is especially important for 1px borders.
+                bool applyLeftInnerClip = (style->borderLeftWidth() < topLeft.width())
+                    && (style->borderTopWidth() < topLeft.height())
+                    && (ts != DOUBLE || style->borderTopWidth() > 6);
+                if (applyLeftInnerClip) {
+                    graphicsContext->save();
+                    graphicsContext->addInnerRoundedRectClip(IntRect(leftX, leftY, topLeft.width() * 2, topLeft.height() * 2),
+                                                             style->borderTopWidth());
+                }
+
+                firstAngleStart = 90;
+                firstAngleSpan = upperLeftBorderStylesMatch ? 90 : 45;
+
+                // Draw upper left arc
+                drawBorderArc(graphicsContext, leftX, leftY, thickness, topLeft, firstAngleStart, firstAngleSpan,
+                              BSTop, tc, style->color(), ts, true);
+                if (applyLeftInnerClip)
+                    graphicsContext->restore();
+            }
+
+            if (topRight.width()) {
+                int rightX = tx + w - topRight.width() * 2;
+                bool applyRightInnerClip = (style->borderRightWidth() < topRight.width())
+                    && (style->borderTopWidth() < topRight.height())
+                    && (ts != DOUBLE || style->borderTopWidth() > 6);
+                if (applyRightInnerClip) {
+                    graphicsContext->save();
+                    graphicsContext->addInnerRoundedRectClip(IntRect(rightX, leftY, topRight.width() * 2, topRight.height() * 2),
+                                                             style->borderTopWidth());
+                }
+
+                if (upperRightBorderStylesMatch) {
+                    secondAngleStart = 0;
+                    secondAngleSpan = 90;
+                } else {
+                    secondAngleStart = 45;
+                    secondAngleSpan = 45;
+                }
+
+                // Draw upper right arc
+                drawBorderArc(graphicsContext, rightX, leftY, thickness, topRight, secondAngleStart, secondAngleSpan,
+                              BSTop, tc, style->color(), ts, false);
+                if (applyRightInnerClip)
+                    graphicsContext->restore();
+            }
+        }
+    }
+
+    if (renderBottom) {
+        bool ignore_left = (renderRadii && bottomLeft.width() > 0) ||
+            (bc == lc && bt == lt && bs >= OUTSET &&
+             (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET));
+
+        bool ignore_right = (renderRadii && bottomRight.width() > 0) ||
+            (bc == rc && bt == rt && bs >= OUTSET &&
+             (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET));
+
+        int x = tx;
+        int x2 = tx + w;
+        if (renderRadii) {
+            x += bottomLeft.width();
+            x2 -= bottomRight.width();
+        }
+
+        drawBorder(graphicsContext, x, ty + h - style->borderBottomWidth(), x2, ty + h, BSBottom, bc, style->color(), bs,
+                   ignore_left ? 0 : style->borderLeftWidth(), ignore_right ? 0 : style->borderRightWidth());
+
+        if (renderRadii) {
+            thickness = style->borderBottomWidth() * 2;
+
+            if (bottomLeft.width()) {
+                int leftX = tx;
+                int leftY = ty + h - bottomLeft.height() * 2;
+                bool applyLeftInnerClip = (style->borderLeftWidth() < bottomLeft.width())
+                    && (style->borderBottomWidth() < bottomLeft.height())
+                    && (bs != DOUBLE || style->borderBottomWidth() > 6);
+                if (applyLeftInnerClip) {
+                    graphicsContext->save();
+                    graphicsContext->addInnerRoundedRectClip(IntRect(leftX, leftY, bottomLeft.width() * 2, bottomLeft.height() * 2),
+                                                             style->borderBottomWidth());
+                }
+
+                if (lowerLeftBorderStylesMatch) {
+                    firstAngleStart = 180;
+                    firstAngleSpan = 90;
+                } else {
+                    firstAngleStart = 225;
+                    firstAngleSpan = 45;
+                }
+
+                // Draw lower left arc
+                drawBorderArc(graphicsContext, leftX, leftY, thickness, bottomLeft, firstAngleStart, firstAngleSpan,
+                              BSBottom, bc, style->color(), bs, true);
+                if (applyLeftInnerClip)
+                    graphicsContext->restore();
+            }
+
+            if (bottomRight.width()) {
+                int rightY = ty + h - bottomRight.height() * 2;
+                int rightX = tx + w - bottomRight.width() * 2;
+                bool applyRightInnerClip = (style->borderRightWidth() < bottomRight.width())
+                    && (style->borderBottomWidth() < bottomRight.height())
+                    && (bs != DOUBLE || style->borderBottomWidth() > 6);
+                if (applyRightInnerClip) {
+                    graphicsContext->save();
+                    graphicsContext->addInnerRoundedRectClip(IntRect(rightX, rightY, bottomRight.width() * 2, bottomRight.height() * 2),
+                                                             style->borderBottomWidth());
+                }
+
+                secondAngleStart = 270;
+                secondAngleSpan = lowerRightBorderStylesMatch ? 90 : 45;
+
+                // Draw lower right arc
+                drawBorderArc(graphicsContext, rightX, rightY, thickness, bottomRight, secondAngleStart, secondAngleSpan,
+                              BSBottom, bc, style->color(), bs, false);
+                if (applyRightInnerClip)
+                    graphicsContext->restore();
+            }
+        }
+    }
+
+    if (renderLeft) {
+        bool ignore_top = (renderRadii && topLeft.height() > 0) ||
+            (tc == lc && tt == lt && ls >= OUTSET &&
+             (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET));
+
+        bool ignore_bottom = (renderRadii && bottomLeft.height() > 0) ||
+            (bc == lc && bt == lt && ls >= OUTSET &&
+             (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET));
+
+        int y = ty;
+        int y2 = ty + h;
+        if (renderRadii) {
+            y += topLeft.height();
+            y2 -= bottomLeft.height();
+        }
+
+        drawBorder(graphicsContext, tx, y, tx + style->borderLeftWidth(), y2, BSLeft, lc, style->color(), ls,
+                   ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
+
+        if (renderRadii && (!upperLeftBorderStylesMatch || !lowerLeftBorderStylesMatch)) {
+            int topX = tx;
+            thickness = style->borderLeftWidth() * 2;
+
+            if (!upperLeftBorderStylesMatch && topLeft.width()) {
+                int topY = ty;
+                bool applyTopInnerClip = (style->borderLeftWidth() < topLeft.width())
+                    && (style->borderTopWidth() < topLeft.height())
+                    && (ls != DOUBLE || style->borderLeftWidth() > 6);
+                if (applyTopInnerClip) {
+                    graphicsContext->save();
+                    graphicsContext->addInnerRoundedRectClip(IntRect(topX, topY, topLeft.width() * 2, topLeft.height() * 2),
+                                                             style->borderLeftWidth());
+                }
+
+                firstAngleStart = 135;
+                firstAngleSpan = 45;
+
+                // Draw top left arc
+                drawBorderArc(graphicsContext, topX, topY, thickness, topLeft, firstAngleStart, firstAngleSpan,
+                              BSLeft, lc, style->color(), ls, true);
+                if (applyTopInnerClip)
+                    graphicsContext->restore();
+            }
+
+            if (!lowerLeftBorderStylesMatch && bottomLeft.width()) {
+                int bottomY = ty + h - bottomLeft.height() * 2;
+                bool applyBottomInnerClip = (style->borderLeftWidth() < bottomLeft.width())
+                    && (style->borderBottomWidth() < bottomLeft.height())
+                    && (ls != DOUBLE || style->borderLeftWidth() > 6);
+                if (applyBottomInnerClip) {
+                    graphicsContext->save();
+                    graphicsContext->addInnerRoundedRectClip(IntRect(topX, bottomY, bottomLeft.width() * 2, bottomLeft.height() * 2),
+                                                             style->borderLeftWidth());
+                }
+
+                secondAngleStart = 180;
+                secondAngleSpan = 45;
+
+                // Draw bottom left arc
+                drawBorderArc(graphicsContext, topX, bottomY, thickness, bottomLeft, secondAngleStart, secondAngleSpan,
+                              BSLeft, lc, style->color(), ls, false);
+                if (applyBottomInnerClip)
+                    graphicsContext->restore();
+            }
+        }
+    }
+
+    if (renderRight) {
+        bool ignore_top = (renderRadii && topRight.height() > 0) ||
+            ((tc == rc) && (tt == rt) &&
+            (rs >= DOTTED || rs == INSET) &&
+            (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET));
+
+        bool ignore_bottom = (renderRadii && bottomRight.height() > 0) ||
+            ((bc == rc) && (bt == rt) &&
+            (rs >= DOTTED || rs == INSET) &&
+            (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET));
+
+        int y = ty;
+        int y2 = ty + h;
+        if (renderRadii) {
+            y += topRight.height();
+            y2 -= bottomRight.height();
+        }
+
+        drawBorder(graphicsContext, tx + w - style->borderRightWidth(), y, tx + w, y2, BSRight, rc, style->color(), rs,
+                   ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
+
+        if (renderRadii && (!upperRightBorderStylesMatch || !lowerRightBorderStylesMatch)) {
+            thickness = style->borderRightWidth() * 2;
+
+            if (!upperRightBorderStylesMatch && topRight.width()) {
+                int topX = tx + w - topRight.width() * 2;
+                int topY = ty;
+                bool applyTopInnerClip = (style->borderRightWidth() < topRight.width())
+                    && (style->borderTopWidth() < topRight.height())
+                    && (rs != DOUBLE || style->borderRightWidth() > 6);
+                if (applyTopInnerClip) {
+                    graphicsContext->save();
+                    graphicsContext->addInnerRoundedRectClip(IntRect(topX, topY, topRight.width() * 2, topRight.height() * 2),
+                                                             style->borderRightWidth());
+                }
+
+                firstAngleStart = 0;
+                firstAngleSpan = 45;
+
+                // Draw top right arc
+                drawBorderArc(graphicsContext, topX, topY, thickness, topRight, firstAngleStart, firstAngleSpan,
+                              BSRight, rc, style->color(), rs, true);
+                if (applyTopInnerClip)
+                    graphicsContext->restore();
+            }
+
+            if (!lowerRightBorderStylesMatch && bottomRight.width()) {
+                int bottomX = tx + w - bottomRight.width() * 2;
+                int bottomY = ty + h - bottomRight.height() * 2;
+                bool applyBottomInnerClip = (style->borderRightWidth() < bottomRight.width())
+                    && (style->borderBottomWidth() < bottomRight.height())
+                    && (rs != DOUBLE || style->borderRightWidth() > 6);
+                if (applyBottomInnerClip) {
+                    graphicsContext->save();
+                    graphicsContext->addInnerRoundedRectClip(IntRect(bottomX, bottomY, bottomRight.width() * 2, bottomRight.height() * 2),
+                                                             style->borderRightWidth());
+                }
+
+                secondAngleStart = 315;
+                secondAngleSpan = 45;
+
+                // Draw bottom right arc
+                drawBorderArc(graphicsContext, bottomX, bottomY, thickness, bottomRight, secondAngleStart, secondAngleSpan,
+                              BSRight, rc, style->color(), rs, false);
+                if (applyBottomInnerClip)
+                    graphicsContext->restore();
+            }
+        }
+    }
+
+    if (renderRadii)
+        graphicsContext->restore();
+}
+
+void RenderObject::paintBoxShadow(GraphicsContext* context, int tx, int ty, int w, int h, const RenderStyle* s, bool begin, bool end)
+{
+    // FIXME: Deal with border-image.  Would be great to use border-image as a mask.
+
+    IntRect rect(tx, ty, w, h);
+    bool hasBorderRadius = s->hasBorderRadius();
+    bool hasOpaqueBackground = s->backgroundColor().isValid() && s->backgroundColor().alpha() == 255;
+    for (ShadowData* shadow = s->boxShadow(); shadow; shadow = shadow->next) {
+        context->save();
+
+        IntSize shadowOffset(shadow->x, shadow->y);
+        int shadowBlur = shadow->blur;
+        IntRect fillRect(rect);
+
+        if (hasBorderRadius) {
+            IntRect shadowRect(rect);
+            shadowRect.inflate(shadowBlur);
+            shadowRect.move(shadowOffset);
+            context->clip(shadowRect);
+
+            // Move the fill just outside the clip, adding 1 pixel separation so that the fill does not
+            // bleed in (due to antialiasing) if the context is transformed.
+            IntSize extraOffset(w + max(0, shadowOffset.width()) + shadowBlur + 1, 0);
+            shadowOffset -= extraOffset;
+            fillRect.move(extraOffset);
+        }
+
+        context->setShadow(shadowOffset, shadowBlur, shadow->color);
+        if (hasBorderRadius) {
+            IntSize topLeft = begin ? s->borderTopLeftRadius() : IntSize();
+            IntSize topRight = end ? s->borderTopRightRadius() : IntSize();
+            IntSize bottomLeft = begin ? s->borderBottomLeftRadius() : IntSize();
+            IntSize bottomRight = end ? s->borderBottomRightRadius() : IntSize();
+            if (!hasOpaqueBackground)
+                context->clipOutRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
+            context->fillRoundedRect(fillRect, topLeft, topRight, bottomLeft, bottomRight, Color::black);
+        } else {
+            if (!hasOpaqueBackground)
+                context->clipOut(rect);
+            context->fillRect(fillRect, Color::black);
+        }
+        context->restore();
+    }
+}
+
+void RenderObject::addLineBoxRects(Vector<IntRect>&, unsigned startOffset, unsigned endOffset, bool useSelectionHeight)
+{
+}
+
+void RenderObject::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel)
+{
+    // For blocks inside inlines, we go ahead and include margins so that we run right up to the
+    // inline boxes above and below us (thus getting merged with them to form a single irregular
+    // shape).
+    if (topLevel && continuation()) {
+        rects.append(IntRect(tx, ty - collapsedMarginTop(),
+                             width(), height() + collapsedMarginTop() + collapsedMarginBottom()));
+        continuation()->absoluteRects(rects,
+                                      tx - xPos() + continuation()->containingBlock()->xPos(),
+                                      ty - yPos() + continuation()->containingBlock()->yPos(), topLevel);
+    } else
+        rects.append(IntRect(tx, ty, width(), height() + borderTopExtra() + borderBottomExtra()));
+}
+
+IntRect RenderObject::absoluteBoundingBoxRect()
+{
+    int x, y;
+    absolutePosition(x, y);
+    Vector<IntRect> rects;
+    absoluteRects(rects, x, y);
+
+    size_t n = rects.size();
+    if (!n)
+        return IntRect();
+
+    IntRect result = rects[0];
+    for (size_t i = 1; i < n; ++i)
+        result.unite(rects[i]);
+    return result;
+}
+
+void RenderObject::addAbsoluteRectForLayer(IntRect& result)
+{
+    if (hasLayer())
+        result.unite(absoluteBoundingBoxRect());
+    for (RenderObject* current = firstChild(); current; current = current->nextSibling())
+        current->addAbsoluteRectForLayer(result);
+}
+
+IntRect RenderObject::paintingRootRect(IntRect& topLevelRect)
+{
+    IntRect result = absoluteBoundingBoxRect();
+    topLevelRect = result;
+    for (RenderObject* current = firstChild(); current; current = current->nextSibling())
+        current->addAbsoluteRectForLayer(result);
+    return result;
+}
+
+void RenderObject::addPDFURLRect(GraphicsContext* context, const IntRect& rect)
+{
+    if (rect.isEmpty())
+        return;
+    Node* node = element();
+    if (!node || !node->isLink() || !node->isElementNode())
+        return;
+    const AtomicString& href = static_cast<Element*>(node)->getAttribute(hrefAttr);
+    if (href.isNull())
+        return;
+    context->setURLForRect(node->document()->completeURL(href), rect);
+}
+
+
+void RenderObject::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
+{
+    // For blocks inside inlines, we go ahead and include margins so that we run right up to the
+    // inline boxes above and below us (thus getting merged with them to form a single irregular
+    // shape).
+    if (continuation()) {
+        graphicsContext->addFocusRingRect(IntRect(tx, ty - collapsedMarginTop(), width(), height() + collapsedMarginTop() + collapsedMarginBottom()));
+        continuation()->addFocusRingRects(graphicsContext,
+                                          tx - xPos() + continuation()->containingBlock()->xPos(),
+                                          ty - yPos() + continuation()->containingBlock()->yPos());
+    } else
+        graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
+}
+
+void RenderObject::paintOutline(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style)
+{
+    if (!hasOutline())
+        return;
+
+    int ow = style->outlineWidth();
+
+    EBorderStyle os = style->outlineStyle();
+
+    Color oc = style->outlineColor();
+    if (!oc.isValid())
+        oc = style->color();
+
+    int offset = style->outlineOffset();
+
+    if (style->outlineStyleIsAuto() || hasOutlineAnnotation()) {
+        if (!theme()->supportsFocusRing(style)) {
+            // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
+            graphicsContext->initFocusRing(ow, offset);
+            if (style->outlineStyleIsAuto())
+                addFocusRingRects(graphicsContext, tx, ty);
+            else
+                addPDFURLRect(graphicsContext, graphicsContext->focusRingBoundingRect());
+            graphicsContext->drawFocusRing(oc);
+            graphicsContext->clearFocusRing();
+        }
+    }
+
+    if (style->outlineStyleIsAuto() || style->outlineStyle() == BNONE)
+        return;
+
+    tx -= offset;
+    ty -= offset;
+    w += 2 * offset;
+    h += 2 * offset;
+
+    if (h < 0 || w < 0)
+        return;
+
+    drawBorder(graphicsContext, tx - ow, ty - ow, tx, ty + h + ow,
+               BSLeft, Color(oc), style->color(), os, ow, ow);
+
+    drawBorder(graphicsContext, tx - ow, ty - ow, tx + w + ow, ty,
+               BSTop, Color(oc), style->color(), os, ow, ow);
+
+    drawBorder(graphicsContext, tx + w, ty - ow, tx + w + ow, ty + h + ow,
+               BSRight, Color(oc), style->color(), os, ow, ow);
+
+    drawBorder(graphicsContext, tx - ow, ty + h, tx + w + ow, ty + h + ow,
+               BSBottom, Color(oc), style->color(), os, ow, ow);
+}
+
+void RenderObject::paint(PaintInfo& /*paintInfo*/, int /*tx*/, int /*ty*/)
+{
+}
+
+void RenderObject::repaint(bool immediate)
+{
+    // Can't use view(), since we might be unrooted.
+    RenderObject* o = this;
+    while (o->parent())
+        o = o->parent();
+    if (!o->isRenderView())
+        return;
+    RenderView* view = static_cast<RenderView*>(o);
+    if (view->printing())
+        return; // Don't repaint if we're printing.
+    view->repaintViewRectangle(absoluteClippedOverflowRect(), immediate);
+}
+
+void RenderObject::repaintRectangle(const IntRect& r, bool immediate)
+{
+    // Can't use view(), since we might be unrooted.
+    RenderObject* o = this;
+    while (o->parent())
+        o = o->parent();
+    if (!o->isRenderView())
+        return;
+    RenderView* view = static_cast<RenderView*>(o);
+    if (view->printing())
+        return; // Don't repaint if we're printing.
+    IntRect absRect(r);
+    absRect.move(view->layoutDelta());
+    computeAbsoluteRepaintRect(absRect);
+    view->repaintViewRectangle(absRect, immediate);
+}
+
+bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const IntRect& oldOutlineBox)
+{
+    RenderView* v = view();
+    if (v->printing())
+        return false; // Don't repaint if we're printing.
+
+    IntRect newBounds = absoluteClippedOverflowRect();
+    IntRect newOutlineBox;
+
+    bool fullRepaint = selfNeedsLayout();
+    // Presumably a background or a border exists if border-fit:lines was specified.
+    if (!fullRepaint && style()->borderFit() == BorderFitLines)
+        fullRepaint = true;
+    if (!fullRepaint) {
+        newOutlineBox = absoluteOutlineBox();
+        if (newOutlineBox.location() != oldOutlineBox.location() || (mustRepaintBackgroundOrBorder() && (newBounds != oldBounds || newOutlineBox != oldOutlineBox)))
+            fullRepaint = true;
+    }
+    if (fullRepaint) {
+        v->repaintViewRectangle(oldBounds);
+        if (newBounds != oldBounds)
+            v->repaintViewRectangle(newBounds);
+        return true;
+    }
+
+    if (newBounds == oldBounds && newOutlineBox == oldOutlineBox)
+        return false;
+
+    int deltaLeft = newBounds.x() - oldBounds.x();
+    if (deltaLeft > 0)
+        v->repaintViewRectangle(IntRect(oldBounds.x(), oldBounds.y(), deltaLeft, oldBounds.height()));
+    else if (deltaLeft < 0)
+        v->repaintViewRectangle(IntRect(newBounds.x(), newBounds.y(), -deltaLeft, newBounds.height()));
+
+    int deltaRight = newBounds.right() - oldBounds.right();
+    if (deltaRight > 0)
+        v->repaintViewRectangle(IntRect(oldBounds.right(), newBounds.y(), deltaRight, newBounds.height()));
+    else if (deltaRight < 0)
+        v->repaintViewRectangle(IntRect(newBounds.right(), oldBounds.y(), -deltaRight, oldBounds.height()));
+
+    int deltaTop = newBounds.y() - oldBounds.y();
+    if (deltaTop > 0)
+        v->repaintViewRectangle(IntRect(oldBounds.x(), oldBounds.y(), oldBounds.width(), deltaTop));
+    else if (deltaTop < 0)
+        v->repaintViewRectangle(IntRect(newBounds.x(), newBounds.y(), newBounds.width(), -deltaTop));
+
+    int deltaBottom = newBounds.bottom() - oldBounds.bottom();
+    if (deltaBottom > 0)
+        v->repaintViewRectangle(IntRect(newBounds.x(), oldBounds.bottom(), newBounds.width(), deltaBottom));
+    else if (deltaBottom < 0)
+        v->repaintViewRectangle(IntRect(oldBounds.x(), newBounds.bottom(), oldBounds.width(), -deltaBottom));
+
+    if (newOutlineBox == oldOutlineBox)
+        return false;
+
+    // We didn't move, but we did change size.  Invalidate the delta, which will consist of possibly
+    // two rectangles (but typically only one).
+    RenderStyle* outlineStyle = !isInline() && continuation() ? continuation()->style() : style();
+    int ow = outlineStyle->outlineSize();
+    ShadowData* boxShadow = style()->boxShadow();
+    int width = abs(newOutlineBox.width() - oldOutlineBox.width());
+    if (width) {
+        int shadowRight = 0;
+        for (ShadowData* shadow = boxShadow; shadow; shadow = shadow->next)
+            shadowRight = max(shadow->x + shadow->blur, shadowRight);
+
+        int borderWidth = max(-outlineStyle->outlineOffset(), max(borderRight(), max(style()->borderTopRightRadius().width(), style()->borderBottomRightRadius().width()))) + max(ow, shadowRight);
+        IntRect rightRect(newOutlineBox.x() + min(newOutlineBox.width(), oldOutlineBox.width()) - borderWidth,
+            newOutlineBox.y(),
+            width + borderWidth,
+            max(newOutlineBox.height(), oldOutlineBox.height()));
+        int right = min(newBounds.right(), oldBounds.right());
+        if (rightRect.x() < right) {
+            rightRect.setWidth(min(rightRect.width(), right - rightRect.x()));
+            v->repaintViewRectangle(rightRect);
+        }
+    }
+    int height = abs(newOutlineBox.height() - oldOutlineBox.height());
+    if (height) {
+        int shadowBottom = 0;
+        for (ShadowData* shadow = boxShadow; shadow; shadow = shadow->next)
+            shadowBottom = max(shadow->y + shadow->blur, shadowBottom);
+
+        int borderHeight = max(-outlineStyle->outlineOffset(), max(borderBottom(), max(style()->borderBottomLeftRadius().height(), style()->borderBottomRightRadius().height()))) + max(ow, shadowBottom);
+        IntRect bottomRect(newOutlineBox.x(),
+            min(newOutlineBox.bottom(), oldOutlineBox.bottom()) - borderHeight,
+            max(newOutlineBox.width(), oldOutlineBox.width()),
+            height + borderHeight);
+        int bottom = min(newBounds.bottom(), oldBounds.bottom());
+        if (bottomRect.y() < bottom) {
+            bottomRect.setHeight(min(bottomRect.height(), bottom - bottomRect.y()));
+            v->repaintViewRectangle(bottomRect);
+        }
+    }
+    return false;
+}
+
+void RenderObject::repaintDuringLayoutIfMoved(const IntRect& rect)
+{
+}
+
+void RenderObject::repaintOverhangingFloats(bool paintAllDescendants)
+{
+}
+
+bool RenderObject::checkForRepaintDuringLayout() const
+{
+    // FIXME: <https://bugs.webkit.org/show_bug.cgi?id=20885> It is probably safe to also require
+    // m_everHadLayout. Currently, only RenderBlock::layoutBlock() adds this condition. See also
+    // <https://bugs.webkit.org/show_bug.cgi?id=15129>.
+    return !document()->view()->needsFullRepaint() && !hasLayer();
+}
+
+IntRect RenderObject::getAbsoluteRepaintRectWithOutline(int ow)
+{
+    IntRect r(absoluteClippedOverflowRect());
+    r.inflate(ow);
+
+    if (continuation() && !isInline())
+        r.inflateY(collapsedMarginTop());
+
+    if (isInlineFlow()) {
+        for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+            if (!curr->isText())
+                r.unite(curr->getAbsoluteRepaintRectWithOutline(ow));
+        }
+    }
+
+    return r;
+}
+
+IntRect RenderObject::absoluteClippedOverflowRect()
+{
+    if (parent())
+        return parent()->absoluteClippedOverflowRect();
+    return IntRect();
+}
+
+void RenderObject::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
+{
+    if (RenderObject* o = parent()) {
+        if (o->isBlockFlow()) {
+            RenderBlock* cb = static_cast<RenderBlock*>(o);
+            if (cb->hasColumns())
+                cb->adjustRectForColumns(rect);
+        }
+
+        if (o->hasOverflowClip()) {
+            // o->height() is inaccurate if we're in the middle of a layout of |o|, so use the
+            // layer's size instead.  Even if the layer's size is wrong, the layer itself will repaint
+            // anyway if its size does change.
+            IntRect boxRect(0, 0, o->layer()->width(), o->layer()->height());
+            int x = rect.x();
+            int y = rect.y();
+            o->layer()->subtractScrollOffset(x, y); // For overflow:auto/scroll/hidden.
+            IntRect repaintRect(x, y, rect.width(), rect.height());
+            rect = intersection(repaintRect, boxRect);
+            if (rect.isEmpty())
+                return;
+        }
+
+        o->computeAbsoluteRepaintRect(rect, fixed);
+    }
+}
+
+void RenderObject::dirtyLinesFromChangedChild(RenderObject* child)
+{
+}
+
+#ifndef NDEBUG
+
+void RenderObject::showTreeForThis() const
+{
+    if (element())
+        element()->showTreeForThis();
+}
+
+#endif // NDEBUG
+
+Color RenderObject::selectionBackgroundColor() const
+{
+    Color color;
+    if (style()->userSelect() != SELECT_NONE) {
+        RenderStyle* pseudoStyle = getCachedPseudoStyle(RenderStyle::SELECTION);
+        if (pseudoStyle && pseudoStyle->backgroundColor().isValid())
+            color = pseudoStyle->backgroundColor().blendWithWhite();
+        else
+            color = document()->frame()->selection()->isFocusedAndActive() ?
+                    theme()->activeSelectionBackgroundColor() :
+                    theme()->inactiveSelectionBackgroundColor();
+    }
+
+    return color;
+}
+
+Color RenderObject::selectionForegroundColor() const
+{
+    Color color;
+    if (style()->userSelect() == SELECT_NONE)
+        return color;
+
+    if (RenderStyle* pseudoStyle = getCachedPseudoStyle(RenderStyle::SELECTION)) {
+        color = pseudoStyle->textFillColor();
+        if (!color.isValid())
+            color = pseudoStyle->color();
+    } else
+        color = document()->frame()->selection()->isFocusedAndActive() ?
+                theme()->platformActiveSelectionForegroundColor() :
+                theme()->platformInactiveSelectionForegroundColor();
+
+    return color;
+}
+
+Node* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const
+{
+    if (!dhtmlOK && !uaOK)
+        return 0;
+
+    for (const RenderObject* curr = this; curr; curr = curr->parent()) {
+        Node* elt = curr->element();
+        if (elt && elt->nodeType() == Node::TEXT_NODE) {
+            // Since there's no way for the author to address the -webkit-user-drag style for a text node,
+            // we use our own judgement.
+            if (uaOK && view()->frameView()->frame()->eventHandler()->shouldDragAutoNode(curr->node(), IntPoint(x, y))) {
+                dhtmlWillDrag = false;
+                return curr->node();
+            }
+            if (elt->canStartSelection())
+                // In this case we have a click in the unselected portion of text.  If this text is
+                // selectable, we want to start the selection process instead of looking for a parent
+                // to try to drag.
+                return 0;
+        } else {
+            EUserDrag dragMode = curr->style()->userDrag();
+            if (dhtmlOK && dragMode == DRAG_ELEMENT) {
+                dhtmlWillDrag = true;
+                return curr->node();
+            }
+            if (uaOK && dragMode == DRAG_AUTO
+                    && view()->frameView()->frame()->eventHandler()->shouldDragAutoNode(curr->node(), IntPoint(x, y))) {
+                dhtmlWillDrag = false;
+                return curr->node();
+            }
+        }
+    }
+    return 0;
+}
+
+void RenderObject::selectionStartEnd(int& spos, int& epos) const
+{
+    view()->selectionStartEnd(spos, epos);
+}
+
+RenderBlock* RenderObject::createAnonymousBlock()
+{
+    RefPtr<RenderStyle> newStyle = RenderStyle::create();
+    newStyle->inheritFrom(m_style.get());
+    newStyle->setDisplay(BLOCK);
+
+    RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
+    newBox->setStyle(newStyle.release());
+    return newBox;
+}
+
+void RenderObject::handleDynamicFloatPositionChange()
+{
+    // We have gone from not affecting the inline status of the parent flow to suddenly
+    // having an impact.  See if there is a mismatch between the parent flow's
+    // childrenInline() state and our state.
+    setInline(style()->isDisplayInlineType());
+    if (isInline() != parent()->childrenInline()) {
+        if (!isInline()) {
+            if (parent()->isRenderInline()) {
+                // We have to split the parent flow.
+                RenderInline* parentInline = static_cast<RenderInline*>(parent());
+                RenderBlock* newBox = parentInline->createAnonymousBlock();
+
+                RenderFlow* oldContinuation = parent()->continuation();
+                parentInline->setContinuation(newBox);
+
+                RenderObject* beforeChild = nextSibling();
+                parent()->removeChildNode(this);
+                parentInline->splitFlow(beforeChild, newBox, this, oldContinuation);
+            } else if (parent()->isRenderBlock()) {
+                RenderBlock* o = static_cast<RenderBlock*>(parent());
+                o->makeChildrenNonInline();
+                if (o->isAnonymousBlock() && o->parent())
+                    o->parent()->removeLeftoverAnonymousBlock(o);
+                // o may be dead here
+            }
+        } else {
+            // An anonymous block must be made to wrap this inline.
+            RenderBlock* box = createAnonymousBlock();
+            parent()->insertChildNode(box, this);
+            box->appendChildNode(parent()->removeChildNode(this));
+        }
+    }
+}
+
+void RenderObject::setAnimatableStyle(PassRefPtr<RenderStyle> style)
+{
+    if (!isText() && style)
+        setStyle(animation()->updateAnimations(this, style.get()));
+    else
+        setStyle(style);
+}
+
+void RenderObject::setStyle(PassRefPtr<RenderStyle> style)
+{
+    if (m_style == style)
+        return;
+
+    RenderStyle::Diff diff = RenderStyle::Equal;
+    if (m_style)
+        diff = m_style->diff(style.get());
+
+    // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
+    if (diff == RenderStyle::RepaintLayer && !hasLayer())
+        diff = RenderStyle::Repaint;
+
+    styleWillChange(diff, style.get());
+    
+    RefPtr<RenderStyle> oldStyle = m_style.release();
+    m_style = style;
+
+    updateFillImages(oldStyle ? oldStyle->backgroundLayers() : 0, m_style ? m_style->backgroundLayers() : 0);
+    updateFillImages(oldStyle ? oldStyle->maskLayers() : 0, m_style ? m_style->maskLayers() : 0);
+
+    updateImage(oldStyle ? oldStyle->borderImage().image() : 0, m_style ? m_style->borderImage().image() : 0);
+    updateImage(oldStyle ? oldStyle->maskBoxImage().image() : 0, m_style ? m_style->maskBoxImage().image() : 0);
+
+    styleDidChange(diff, oldStyle.get());
+}
+
+void RenderObject::setStyleInternal(PassRefPtr<RenderStyle> style)
+{
+    m_style = style;
+}
+
+void RenderObject::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+{
+    if (m_style) {
+        // If our z-index changes value or our visibility changes,
+        // we need to dirty our stacking context's z-order list.
+        if (newStyle) {
+#if ENABLE(DASHBOARD_SUPPORT)
+            if (m_style->visibility() != newStyle->visibility() ||
+                    m_style->zIndex() != newStyle->zIndex() ||
+                    m_style->hasAutoZIndex() != newStyle->hasAutoZIndex())
+                document()->setDashboardRegionsDirty(true);
+#endif
+
+            if ((m_style->hasAutoZIndex() != newStyle->hasAutoZIndex() ||
+                    m_style->zIndex() != newStyle->zIndex() ||
+                    m_style->visibility() != newStyle->visibility()) && hasLayer()) {
+                layer()->dirtyStackingContextZOrderLists();
+                if (m_style->hasAutoZIndex() != newStyle->hasAutoZIndex() ||
+                        m_style->visibility() != newStyle->visibility())
+                    layer()->dirtyZOrderLists();
+            }
+            // keep layer hierarchy visibility bits up to date if visibility changes
+            if (m_style->visibility() != newStyle->visibility()) {
+                if (RenderLayer* l = enclosingLayer()) {
+                    if (newStyle->visibility() == VISIBLE)
+                        l->setHasVisibleContent(true);
+                    else if (l->hasVisibleContent() && (this == l->renderer() || l->renderer()->style()->visibility() != VISIBLE)) {
+                        l->dirtyVisibleContentStatus();
+                        if (diff > RenderStyle::RepaintLayer)
+                            repaint();
+                    }
+                }
+            }
+        }
+
+        // The background of the root element or the body element could propagate up to
+        // the canvas.  Just dirty the entire canvas when our style changes substantially.
+        if (diff >= RenderStyle::Repaint && element() &&
+                (element()->hasTagName(htmlTag) || element()->hasTagName(bodyTag)))
+            view()->repaint();
+        else if (m_parent && !isText()) {
+            // Do a repaint with the old style first, e.g., for example if we go from
+            // having an outline to not having an outline.
+            if (diff == RenderStyle::RepaintLayer) {
+                layer()->repaintIncludingDescendants();
+                if (!(m_style->clip() == newStyle->clip()))
+                    layer()->clearClipRects();
+            } else if (diff == RenderStyle::Repaint || newStyle->outlineSize() < m_style->outlineSize())
+                repaint();
+        }
+
+        // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
+        // end up being destroyed.
+        if (diff == RenderStyle::Layout && hasLayer() &&
+                (m_style->position() != newStyle->position() ||
+                 m_style->zIndex() != newStyle->zIndex() ||
+                 m_style->hasAutoZIndex() != newStyle->hasAutoZIndex() ||
+                 !(m_style->clip() == newStyle->clip()) ||
+                 m_style->hasClip() != newStyle->hasClip() ||
+                 m_style->opacity() != newStyle->opacity()))
+            layer()->repaintIncludingDescendants();
+
+        // When a layout hint happens and an object's position style changes, we have to do a layout
+        // to dirty the render tree using the old position value now.
+        if (diff == RenderStyle::Layout && m_parent && m_style->position() != newStyle->position()) {
+            markContainingBlocksForLayout();
+            if (m_style->position() == StaticPosition)
+                repaint();
+            if (isFloating() && !isPositioned() && (newStyle->position() == AbsolutePosition || newStyle->position() == FixedPosition))
+                removeFromObjectLists();
+            if (isRenderBlock()) {
+                if (newStyle->position() == StaticPosition)
+                    // Clear our positioned objects list. Our absolutely positioned descendants will be
+                    // inserted into our containing block's positioned objects list during layout.
+                    removePositionedObjects(0);
+                else if (m_style->position() == StaticPosition) {
+                    // Remove our absolutely positioned descendants from their current containing block.
+                    // They will be inserted into our positioned objects list during layout.
+                    RenderObject* cb = parent();
+                    while (cb && (cb->style()->position() == StaticPosition || (cb->isInline() && !cb->isReplaced())) && !cb->isRenderView()) {
+                        if (cb->style()->position() == RelativePosition && cb->isInline() && !cb->isReplaced()) {
+                            cb = cb->containingBlock();
+                            break;
+                        }
+                        cb = cb->parent();
+                    }
+                    cb->removePositionedObjects(static_cast<RenderBlock*>(this));
+                }
+            }
+        }
+
+        if (isFloating() && (m_style->floating() != newStyle->floating()))
+            // For changes in float styles, we need to conceivably remove ourselves
+            // from the floating objects list.
+            removeFromObjectLists();
+        else if (isPositioned() && (newStyle->position() != AbsolutePosition && newStyle->position() != FixedPosition))
+            // For changes in positioning styles, we need to conceivably remove ourselves
+            // from the positioned objects list.
+            removeFromObjectLists();
+
+        s_affectsParentBlock = isFloatingOrPositioned() &&
+            (!newStyle->isFloating() && newStyle->position() != AbsolutePosition && newStyle->position() != FixedPosition)
+            && parent() && (parent()->isBlockFlow() || parent()->isInlineFlow());
+
+        // reset style flags
+        if (diff == RenderStyle::Layout || diff == RenderStyle::LayoutPositionedMovementOnly) {
+            m_floating = false;
+            m_positioned = false;
+            m_relPositioned = false;
+        }
+        m_paintBackground = false;
+        m_hasOverflowClip = false;
+        m_hasTransform = false;
+        m_hasReflection = false;
+    } else
+        s_affectsParentBlock = false;
+
+    if (view()->frameView()) {
+        // FIXME: A better solution would be to only invalidate the fixed regions when scrolling.  It's overkill to
+        // prevent the entire view from blitting on a scroll.
+        bool newStyleSlowScroll = newStyle && (newStyle->position() == FixedPosition || newStyle->hasFixedBackgroundImage());
+        bool oldStyleSlowScroll = m_style && (m_style->position() == FixedPosition || m_style->hasFixedBackgroundImage());
+        if (oldStyleSlowScroll != newStyleSlowScroll) {
+            if (oldStyleSlowScroll)
+                view()->frameView()->removeSlowRepaintObject();
+            if (newStyleSlowScroll)
+                view()->frameView()->addSlowRepaintObject();
+        }
+    }
+}
+
+void RenderObject::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    setHasBoxDecorations(m_style->hasBorder() || m_style->hasBackground() || m_style->hasAppearance() || m_style->boxShadow());
+
+    if (s_affectsParentBlock)
+        handleDynamicFloatPositionChange();
+
+    // No need to ever schedule repaints from a style change of a text run, since
+    // we already did this for the parent of the text run.
+    // We do have to schedule layouts, though, since a style change can force us to
+    // need to relayout.
+    if (diff == RenderStyle::Layout && m_parent)
+        setNeedsLayoutAndPrefWidthsRecalc();
+    else if (diff == RenderStyle::LayoutPositionedMovementOnly && m_parent && !isText())
+        setNeedsPositionedMovementLayout();
+    else if (m_parent && !isText() && (diff == RenderStyle::RepaintLayer || diff == RenderStyle::Repaint))
+        // Do a repaint with the new style now, e.g., for example if we go from
+        // not having an outline to having an outline.
+        repaint();
+}
+
+void RenderObject::updateFillImages(const FillLayer* oldLayers, const FillLayer* newLayers)
+{
+    // FIXME: This will be slow when a large number of images is used.  Fix by using a dict.
+    for (const FillLayer* currOld = oldLayers; currOld; currOld = currOld->next()) {
+        if (currOld->image() && (!newLayers || !newLayers->containsImage(currOld->image())))
+            currOld->image()->removeClient(this);
+    }
+    for (const FillLayer* currNew = newLayers; currNew; currNew = currNew->next()) {
+        if (currNew->image() && (!oldLayers || !oldLayers->containsImage(currNew->image())))
+            currNew->image()->addClient(this);
+    }
+}
+
+void RenderObject::updateImage(StyleImage* oldImage, StyleImage* newImage)
+{
+    if (oldImage != newImage) {
+        if (oldImage)
+            oldImage->removeClient(this);
+        if (newImage)
+            newImage->addClient(this);
+    }
+}
+
+IntRect RenderObject::viewRect() const
+{
+    return view()->viewRect();
+}
+
+bool RenderObject::absolutePosition(int& xPos, int& yPos, bool f) const
+{
+    RenderObject* o = parent();
+    if (o) {
+        o->absolutePosition(xPos, yPos, f);
+        yPos += o->borderTopExtra();
+        if (o->hasOverflowClip())
+            o->layer()->subtractScrollOffset(xPos, yPos);
+        return true;
+    } else {
+        xPos = yPos = 0;
+        return false;
+    }
+}
+
+IntRect RenderObject::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
+{
+   if (extraWidthToEndOfLine)
+       *extraWidthToEndOfLine = 0;
+
+    return IntRect();
+}
+
+int RenderObject::paddingTop() const
+{
+    int w = 0;
+    Length padding = m_style->paddingTop();
+    if (padding.isPercent())
+        w = containingBlock()->availableWidth();
+#ifdef ANDROID_LAYOUT    
+    // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding.
+    if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR &&
+            padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING)
+        return ANDROID_SSR_MARGIN_PADDING;
+#endif
+    return padding.calcMinValue(w);
+}
+
+int RenderObject::paddingBottom() const
+{
+    int w = 0;
+    Length padding = style()->paddingBottom();
+    if (padding.isPercent())
+        w = containingBlock()->availableWidth();
+#ifdef ANDROID_LAYOUT    
+    // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding.
+    if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR &&
+            padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING)
+        return ANDROID_SSR_MARGIN_PADDING;
+#endif
+    return padding.calcMinValue(w);
+}
+
+int RenderObject::paddingLeft() const
+{
+    int w = 0;
+    Length padding = style()->paddingLeft();
+    if (padding.isPercent())
+        w = containingBlock()->availableWidth();
+#ifdef ANDROID_LAYOUT    
+    // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding.
+    if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR &&
+            padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING)
+        return ANDROID_SSR_MARGIN_PADDING;
+#endif
+    return padding.calcMinValue(w);
+}
+
+int RenderObject::paddingRight() const
+{
+    int w = 0;
+    Length padding = style()->paddingRight();
+    if (padding.isPercent())
+        w = containingBlock()->availableWidth();
+#ifdef ANDROID_LAYOUT    
+    // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding.
+    if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR &&
+            padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING)
+        return ANDROID_SSR_MARGIN_PADDING;
+#endif
+    return padding.calcMinValue(w);
+}
+
+RenderView* RenderObject::view() const
+{
+    return static_cast<RenderView*>(document()->renderer());
+}
+
+bool RenderObject::hasOutlineAnnotation() const
+{
+    return element() && element()->isLink() && document()->printing();
+}
+
+RenderObject* RenderObject::container() const
+{
+    // This method is extremely similar to containingBlock(), but with a few notable
+    // exceptions.
+    // (1) It can be used on orphaned subtrees, i.e., it can be called safely even when
+    // the object is not part of the primary document subtree yet.
+    // (2) For normal flow elements, it just returns the parent.
+    // (3) For absolute positioned elements, it will return a relative positioned inline.
+    // containingBlock() simply skips relpositioned inlines and lets an enclosing block handle
+    // the layout of the positioned object.  This does mean that calcAbsoluteHorizontal and
+    // calcAbsoluteVertical have to use container().
+    RenderObject* o = parent();
+
+    if (isText())
+        return o;
+
+    EPosition pos = m_style->position();
+    if (pos == FixedPosition) {
+        // container() can be called on an object that is not in the
+        // tree yet.  We don't call view() since it will assert if it
+        // can't get back to the canvas.  Instead we just walk as high up
+        // as we can.  If we're in the tree, we'll get the root.  If we
+        // aren't we'll get the root of our little subtree (most likely
+        // we'll just return 0).
+        while (o && o->parent() && !(o->hasTransform() && o->isRenderBlock()))
+            o = o->parent();
+    } else if (pos == AbsolutePosition) {
+        // Same goes here.  We technically just want our containing block, but
+        // we may not have one if we're part of an uninstalled subtree.  We'll
+        // climb as high as we can though.
+        while (o && o->style()->position() == StaticPosition && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock()))
+            o = o->parent();
+    }
+
+    return o;
+}
+
+// This code has been written to anticipate the addition of CSS3-::outside and ::inside generated
+// content (and perhaps XBL).  That's why it uses the render tree and not the DOM tree.
+RenderObject* RenderObject::hoverAncestor() const
+{
+    return (!isInline() && continuation()) ? continuation() : parent();
+}
+
+bool RenderObject::isSelectionBorder() const
+{
+    SelectionState st = selectionState();
+    return st == SelectionStart || st == SelectionEnd || st == SelectionBoth;
+}
+
+void RenderObject::removeFromObjectLists()
+{
+    if (documentBeingDestroyed())
+        return;
+
+    if (isFloating()) {
+        RenderBlock* outermostBlock = containingBlock();
+        for (RenderBlock* p = outermostBlock; p && !p->isRenderView(); p = p->containingBlock()) {
+            if (p->containsFloat(this))
+                outermostBlock = p;
+        }
+
+        if (outermostBlock)
+            outermostBlock->markAllDescendantsWithFloatsForLayout(this);
+    }
+
+    if (isPositioned()) {
+        RenderObject* p;
+        for (p = parent(); p; p = p->parent()) {
+            if (p->isRenderBlock())
+                static_cast<RenderBlock*>(p)->removePositionedObject(this);
+        }
+    }
+}
+
+bool RenderObject::documentBeingDestroyed() const
+{
+    return !document()->renderer();
+}
+
+void RenderObject::destroy()
+{
+    // If this renderer is being autoscrolled, stop the autoscroll timer
+    if (document()->frame() && document()->frame()->eventHandler()->autoscrollRenderer() == this)
+        document()->frame()->eventHandler()->stopAutoscrollTimer(true);
+
+    if (m_hasCounterNodeMap)
+        RenderCounter::destroyCounterNodes(this);
+
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->remove(this);
+
+    animation()->cancelAnimations(this);
+
+    // By default no ref-counting. RenderWidget::destroy() doesn't call
+    // this function because it needs to do ref-counting. If anything
+    // in this function changes, be sure to fix RenderWidget::destroy() as well.
+
+    remove();
+
+    RenderArena* arena = renderArena();
+
+    if (hasLayer())
+        layer()->destroy(arena);
+
+    arenaDelete(arena, this);
+}
+
+void RenderObject::arenaDelete(RenderArena* arena, void* base)
+{
+    if (m_style) {
+        for (const FillLayer* bgLayer = m_style->backgroundLayers(); bgLayer; bgLayer = bgLayer->next()) {
+            if (StyleImage* backgroundImage = bgLayer->image())
+                backgroundImage->removeClient(this);
+        }
+
+        for (const FillLayer* maskLayer = m_style->maskLayers(); maskLayer; maskLayer = maskLayer->next()) {
+            if (StyleImage* maskImage = maskLayer->image())
+                maskImage->removeClient(this);
+        }
+
+        if (StyleImage* borderImage = m_style->borderImage().image())
+            borderImage->removeClient(this);
+
+        if (StyleImage* maskBoxImage = m_style->maskBoxImage().image())
+            maskBoxImage->removeClient(this);
+    }
+
+#ifndef NDEBUG
+    void* savedBase = baseOfRenderObjectBeingDeleted;
+    baseOfRenderObjectBeingDeleted = base;
+#endif
+    delete this;
+#ifndef NDEBUG
+    baseOfRenderObjectBeingDeleted = savedBase;
+#endif
+
+    // Recover the size left there for us by operator delete and free the memory.
+    arena->free(*(size_t*)base, base);
+}
+
+VisiblePosition RenderObject::positionForCoordinates(int x, int y)
+{
+    return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM);
+}
+
+void RenderObject::updateDragState(bool dragOn)
+{
+    bool valueChanged = (dragOn != m_isDragging);
+    m_isDragging = dragOn;
+    if (valueChanged && style()->affectedByDragRules())
+        element()->setChanged();
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+        curr->updateDragState(dragOn);
+    if (continuation())
+        continuation()->updateDragState(dragOn);
+}
+
+bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, const IntPoint& point, int tx, int ty, HitTestFilter hitTestFilter)
+{
+    bool inside = false;
+    if (hitTestFilter != HitTestSelf) {
+        // First test the foreground layer (lines and inlines).
+        inside = nodeAtPoint(request, result, point.x(), point.y(), tx, ty, HitTestForeground);
+
+        // Test floats next.
+        if (!inside)
+            inside = nodeAtPoint(request, result, point.x(), point.y(), tx, ty, HitTestFloat);
+
+        // Finally test to see if the mouse is in the background (within a child block's background).
+        if (!inside)
+            inside = nodeAtPoint(request, result, point.x(), point.y(), tx, ty, HitTestChildBlockBackgrounds);
+    }
+
+    // See if the mouse is inside us but not any of our descendants
+    if (hitTestFilter != HitTestDescendants && !inside)
+        inside = nodeAtPoint(request, result, point.x(), point.y(), tx, ty, HitTestBlockBackground);
+
+    return inside;
+}
+
+void RenderObject::updateHitTestResult(HitTestResult& result, const IntPoint& point)
+{
+    if (result.innerNode())
+        return;
+
+    Node* node = element();
+    IntPoint localPoint(point);
+    if (isRenderView())
+        node = document()->documentElement();
+    else if (!isInline() && continuation())
+        // We are in the margins of block elements that are part of a continuation.  In
+        // this case we're actually still inside the enclosing inline element that was
+        // split.  Go ahead and set our inner node accordingly.
+        node = continuation()->element();
+
+    if (node) {
+        if (node->renderer() && node->renderer()->continuation() && node->renderer() != this) {
+            // We're in the continuation of a split inline.  Adjust our local point to be in the coordinate space
+            // of the principal renderer's containing block.  This will end up being the innerNonSharedNode.
+            RenderObject* firstBlock = node->renderer()->containingBlock();
+            
+            // Get our containing block.
+            RenderObject* block = this;
+            if (isInline())
+                block = containingBlock();
+        
+            localPoint.move(block->xPos() - firstBlock->xPos(), block->yPos() - firstBlock->yPos());
+        }
+
+        result.setInnerNode(node);
+        if (!result.innerNonSharedNode())
+            result.setInnerNonSharedNode(node);
+        result.setLocalPoint(localPoint);
+    }
+}
+
+bool RenderObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int /*x*/, int /*y*/, int /*tx*/, int /*ty*/, HitTestAction)
+{
+    return false;
+}
+
+int RenderObject::verticalPositionHint(bool firstLine) const
+{
+    if (firstLine) // We're only really a first-line style if the document actually uses first-line rules.
+        firstLine = document()->usesFirstLineRules();
+    int vpos = m_verticalPosition;
+    if (m_verticalPosition == PositionUndefined || firstLine) {
+        vpos = getVerticalPosition(firstLine);
+        if (!firstLine)
+            m_verticalPosition = vpos;
+    }
+
+    return vpos;
+}
+
+int RenderObject::getVerticalPosition(bool firstLine) const
+{
+    if (!isInline())
+        return 0;
+
+    // This method determines the vertical position for inline elements.
+    int vpos = 0;
+    EVerticalAlign va = style()->verticalAlign();
+    if (va == TOP)
+        vpos = PositionTop;
+    else if (va == BOTTOM)
+        vpos = PositionBottom;
+    else {
+        bool checkParent = parent()->isInline() && !parent()->isInlineBlockOrInlineTable() && parent()->style()->verticalAlign() != TOP && parent()->style()->verticalAlign() != BOTTOM;
+        vpos = checkParent ? parent()->verticalPositionHint(firstLine) : 0;
+        // don't allow elements nested inside text-top to have a different valignment.
+        if (va == BASELINE)
+            return vpos;
+
+        const Font& f = parent()->style(firstLine)->font();
+        int fontsize = f.pixelSize();
+
+        if (va == SUB)
+            vpos += fontsize / 5 + 1;
+        else if (va == SUPER)
+            vpos -= fontsize / 3 + 1;
+        else if (va == TEXT_TOP)
+            vpos += baselinePosition(firstLine) - f.ascent();
+        else if (va == MIDDLE)
+            vpos += -static_cast<int>(f.xHeight() / 2) - lineHeight(firstLine) / 2 + baselinePosition(firstLine);
+        else if (va == TEXT_BOTTOM) {
+            vpos += f.descent();
+            if (!isReplaced())
+                vpos -= style(firstLine)->font().descent();
+        } else if (va == BASELINE_MIDDLE)
+            vpos += -lineHeight(firstLine) / 2 + baselinePosition(firstLine);
+        else if (va == LENGTH)
+            vpos -= style()->verticalAlignLength().calcValue(lineHeight(firstLine));
+    }
+
+    return vpos;
+}
+
+int RenderObject::lineHeight(bool firstLine, bool /*isRootLineBox*/) const
+{
+    RenderStyle* s = style(firstLine);
+
+    Length lh = s->lineHeight();
+
+    // its "unset", choose nice default
+    if (lh.isNegative())
+        return s->font().lineSpacing();
+
+    if (lh.isPercent())
+        return lh.calcMinValue(s->fontSize());
+
+    // its fixed
+    return lh.value();
+}
+
+int RenderObject::baselinePosition(bool firstLine, bool isRootLineBox) const
+{
+    const Font& f = style(firstLine)->font();
+    return f.ascent() + (lineHeight(firstLine, isRootLineBox) - f.height()) / 2;
+}
+
+void RenderObject::scheduleRelayout()
+{
+    if (isRenderView()) {
+        FrameView* view = static_cast<RenderView*>(this)->frameView();
+        if (view)
+            view->scheduleRelayout();
+    } else if (parent()) {
+        FrameView* v = view() ? view()->frameView() : 0;
+        if (v)
+            v->scheduleRelayoutOfSubtree(this);
+    }
+}
+
+void RenderObject::removeLeftoverAnonymousBlock(RenderBlock*)
+{
+}
+
+InlineBox* RenderObject::createInlineBox(bool, bool isRootLineBox, bool)
+{
+    ASSERT(!isRootLineBox);
+    return new (renderArena()) InlineBox(this);
+}
+
+void RenderObject::dirtyLineBoxes(bool, bool)
+{
+}
+
+InlineBox* RenderObject::inlineBoxWrapper() const
+{
+    return 0;
+}
+
+void RenderObject::setInlineBoxWrapper(InlineBox*)
+{
+}
+
+void RenderObject::deleteLineBoxWrapper()
+{
+}
+
+RenderStyle* RenderObject::firstLineStyle() const
+{
+    if (!document()->usesFirstLineRules())
+        return m_style.get();
+
+    RenderStyle* s = m_style.get();
+    const RenderObject* obj = isText() ? parent() : this;
+    if (obj->isBlockFlow()) {
+        RenderBlock* firstLineBlock = obj->firstLineBlock();
+        if (firstLineBlock)
+            s = firstLineBlock->getCachedPseudoStyle(RenderStyle::FIRST_LINE, style());
+    } else if (!obj->isAnonymous() && obj->isInlineFlow()) {
+        RenderStyle* parentStyle = obj->parent()->firstLineStyle();
+        if (parentStyle != obj->parent()->style()) {
+            // A first-line style is in effect. We need to cache a first-line style
+            // for ourselves.
+            style()->setHasPseudoStyle(RenderStyle::FIRST_LINE_INHERITED);
+            s = obj->getCachedPseudoStyle(RenderStyle::FIRST_LINE_INHERITED, parentStyle);
+        }
+    }
+    return s;
+}
+
+RenderStyle* RenderObject::getCachedPseudoStyle(RenderStyle::PseudoId pseudo, RenderStyle* parentStyle) const
+{
+    if (pseudo < RenderStyle::FIRST_INTERNAL_PSEUDOID && !style()->hasPseudoStyle(pseudo))
+        return 0;
+
+    RenderStyle* cachedStyle = style()->getCachedPseudoStyle(pseudo);
+    if (cachedStyle)
+        return cachedStyle;
+    
+    RefPtr<RenderStyle> result = getUncachedPseudoStyle(pseudo, parentStyle);
+    if (result)
+        return style()->addCachedPseudoStyle(result.release());
+    return 0;
+}
+
+PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyle(RenderStyle::PseudoId pseudo, RenderStyle* parentStyle) const
+{
+    if (pseudo < RenderStyle::FIRST_INTERNAL_PSEUDOID && !style()->hasPseudoStyle(pseudo))
+        return 0;
+    
+    if (!parentStyle)
+        parentStyle = style();
+
+    Node* node = element();
+    while (node && !node->isElementNode())
+        node = node->parentNode();
+    if (!node)
+        return 0;
+
+    RefPtr<RenderStyle> result;
+    if (pseudo == RenderStyle::FIRST_LINE_INHERITED) {
+        result = document()->styleSelector()->styleForElement(static_cast<Element*>(node), parentStyle, false);
+        result->setStyleType(RenderStyle::FIRST_LINE_INHERITED);
+    } else
+        result = document()->styleSelector()->pseudoStyleForElement(pseudo, static_cast<Element*>(node), parentStyle);
+    return result.release();
+}
+
+static Color decorationColor(RenderStyle* style)
+{
+    Color result;
+    if (style->textStrokeWidth() > 0) {
+        // Prefer stroke color if possible but not if it's fully transparent.
+        result = style->textStrokeColor();
+        if (!result.isValid())
+            result = style->color();
+        if (result.alpha())
+            return result;
+    }
+    
+    result = style->textFillColor();
+    if (!result.isValid())
+        result = style->color();
+    return result;
+}
+
+void RenderObject::getTextDecorationColors(int decorations, Color& underline, Color& overline,
+                                           Color& linethrough, bool quirksMode)
+{
+    RenderObject* curr = this;
+    do {
+        int currDecs = curr->style()->textDecoration();
+        if (currDecs) {
+            if (currDecs & UNDERLINE) {
+                decorations &= ~UNDERLINE;
+                underline = decorationColor(curr->style());
+            }
+            if (currDecs & OVERLINE) {
+                decorations &= ~OVERLINE;
+                overline = decorationColor(curr->style());
+            }
+            if (currDecs & LINE_THROUGH) {
+                decorations &= ~LINE_THROUGH;
+                linethrough = decorationColor(curr->style());
+            }
+        }
+        curr = curr->parent();
+        if (curr && curr->isRenderBlock() && curr->continuation())
+            curr = curr->continuation();
+    } while (curr && decorations && (!quirksMode || !curr->element() ||
+                                     (!curr->element()->hasTagName(aTag) && !curr->element()->hasTagName(fontTag))));
+
+    // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
+    if (decorations && curr) {
+        if (decorations & UNDERLINE)
+            underline = decorationColor(curr->style());
+        if (decorations & OVERLINE)
+            overline = decorationColor(curr->style());
+        if (decorations & LINE_THROUGH)
+            linethrough = decorationColor(curr->style());
+    }
+}
+
+void RenderObject::updateWidgetPosition()
+{
+}
+
+#if ENABLE(DASHBOARD_SUPPORT)
+void RenderObject::addDashboardRegions(Vector<DashboardRegionValue>& regions)
+{
+    // Convert the style regions to absolute coordinates.
+    if (style()->visibility() != VISIBLE)
+        return;
+
+    const Vector<StyleDashboardRegion>& styleRegions = style()->dashboardRegions();
+    unsigned i, count = styleRegions.size();
+    for (i = 0; i < count; i++) {
+        StyleDashboardRegion styleRegion = styleRegions[i];
+
+        int w = width();
+        int h = height();
+
+        DashboardRegionValue region;
+        region.label = styleRegion.label;
+        region.bounds = IntRect(styleRegion.offset.left().value(),
+                                styleRegion.offset.top().value(),
+                                w - styleRegion.offset.left().value() - styleRegion.offset.right().value(),
+                                h - styleRegion.offset.top().value() - styleRegion.offset.bottom().value());
+        region.type = styleRegion.type;
+
+        region.clip = region.bounds;
+        computeAbsoluteRepaintRect(region.clip);
+        if (region.clip.height() < 0) {
+            region.clip.setHeight(0);
+            region.clip.setWidth(0);
+        }
+
+        int x, y;
+        absolutePosition(x, y);
+        region.bounds.setX(x + styleRegion.offset.left().value());
+        region.bounds.setY(y + styleRegion.offset.top().value());
+
+        if (document()->frame()) {
+            float pageScaleFactor = document()->frame()->page()->chrome()->scaleFactor();
+            if (pageScaleFactor != 1.0f) {
+                region.bounds.scale(pageScaleFactor);
+                region.clip.scale(pageScaleFactor);
+            }
+        }
+
+        regions.append(region);
+    }
+}
+
+void RenderObject::collectDashboardRegions(Vector<DashboardRegionValue>& regions)
+{
+    // RenderTexts don't have their own style, they just use their parent's style,
+    // so we don't want to include them.
+    if (isText())
+        return;
+
+    addDashboardRegions(regions);
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+        curr->collectDashboardRegions(regions);
+}
+#endif
+
+bool RenderObject::avoidsFloats() const
+{
+    return isReplaced() || hasOverflowClip() || isHR();
+}
+
+bool RenderObject::shrinkToAvoidFloats() const
+{
+    // FIXME: Technically we should be able to shrink replaced elements on a line, but this is difficult to accomplish, since this
+    // involves doing a relayout during findNextLineBreak and somehow overriding the containingBlockWidth method to return the
+    // current remaining width on a line.
+    if (isInline() && !isHTMLMarquee() || !avoidsFloats())
+        return false;
+
+    // All auto-width objects that avoid floats should always use lineWidth.
+    return style()->width().isAuto();
+}
+
+UChar RenderObject::backslashAsCurrencySymbol() const
+{
+    if (Node *node = element()) {
+        if (TextResourceDecoder* decoder = node->document()->decoder())
+            return decoder->encoding().backslashAsCurrencySymbol();
+    }
+    return '\\';
+}
+
+bool RenderObject::willRenderImage(CachedImage*)
+{
+    // Without visibility we won't render (and therefore don't care about animation).
+    if (style()->visibility() != VISIBLE)
+        return false;
+
+    // If we're not in a window (i.e., we're dormant from being put in the b/f cache or in a background tab)
+    // then we don't want to render either.
+    return !document()->inPageCache() && !document()->view()->isOffscreen();
+}
+
+int RenderObject::maximalOutlineSize(PaintPhase p) const
+{
+    if (p != PaintPhaseOutline && p != PaintPhaseSelfOutline && p != PaintPhaseChildOutlines)
+        return 0;
+    return static_cast<RenderView*>(document()->renderer())->maximalOutlineSize();
+}
+
+int RenderObject::caretMinOffset() const
+{
+    return 0;
+}
+
+int RenderObject::caretMaxOffset() const
+{
+    if (isReplaced())
+        return element() ? max(1U, element()->childNodeCount()) : 1;
+    if (isHR())
+        return 1;
+    return 0;
+}
+
+unsigned RenderObject::caretMaxRenderedOffset() const
+{
+    return 0;
+}
+
+int RenderObject::previousOffset(int current) const
+{
+    return current - 1;
+}
+
+int RenderObject::nextOffset(int current) const
+{
+    return current + 1;
+}
+
+int RenderObject::maxTopMargin(bool positive) const
+{
+    return positive ? max(0, marginTop()) : -min(0, marginTop());
+}
+
+int RenderObject::maxBottomMargin(bool positive) const
+{
+    return positive ? max(0, marginBottom()) : -min(0, marginBottom());
+}
+
+IntRect RenderObject::contentBox() const
+{
+    return IntRect(borderLeft() + paddingLeft(), borderTop() + paddingTop(),
+        contentWidth(), contentHeight());
+}
+
+IntRect RenderObject::absoluteContentBox() const
+{
+    IntRect rect = contentBox();
+    int x, y;
+    absolutePositionForContent(x, y);
+    rect.move(x, y);
+    return rect;
+}
+
+void RenderObject::adjustRectForOutlineAndShadow(IntRect& rect) const
+{
+    int outlineSize = !isInline() && continuation() ? continuation()->style()->outlineSize() : style()->outlineSize();
+    if (ShadowData* boxShadow = style()->boxShadow()) {
+        int shadowLeft = 0;
+        int shadowRight = 0;
+        int shadowTop = 0;
+        int shadowBottom = 0;
+
+        do {
+            shadowLeft = min(boxShadow->x - boxShadow->blur - outlineSize, shadowLeft);
+            shadowRight = max(boxShadow->x + boxShadow->blur + outlineSize, shadowRight);
+            shadowTop = min(boxShadow->y - boxShadow->blur - outlineSize, shadowTop);
+            shadowBottom = max(boxShadow->y + boxShadow->blur + outlineSize, shadowBottom);
+
+            boxShadow = boxShadow->next;
+        } while (boxShadow);
+
+        rect.move(shadowLeft, shadowTop);
+        rect.setWidth(rect.width() - shadowLeft + shadowRight);
+        rect.setHeight(rect.height() - shadowTop + shadowBottom);
+    } else
+        rect.inflate(outlineSize);
+}
+
+IntRect RenderObject::absoluteOutlineBox() const
+{
+    IntRect box = borderBox();
+    int x, y;
+    absolutePosition(x, y);
+    box.move(x, y);
+    box.move(view()->layoutDelta());
+    adjustRectForOutlineAndShadow(box);
+    return box;
+}
+
+bool RenderObject::isScrollable() const
+{
+    RenderLayer* l = enclosingLayer();
+    return l && (l->verticalScrollbar() || l->horizontalScrollbar());
+}
+
+AnimationController* RenderObject::animation() const
+{
+    return document()->frame()->animation();
+}
+
+void RenderObject::imageChanged(CachedImage* image)
+{
+    imageChanged(static_cast<WrappedImagePtr>(image));
+}
+
+IntRect RenderObject::reflectionBox() const
+{
+    IntRect result;
+    if (!m_style->boxReflect())
+        return result;
+    IntRect box = borderBox();
+    result = box;
+    switch (m_style->boxReflect()->direction()) {
+        case ReflectionBelow:
+            result.move(0, box.height() + reflectionOffset());
+            break;
+        case ReflectionAbove:
+            result.move(0, -box.height() - reflectionOffset());
+            break;
+        case ReflectionLeft:
+            result.move(-box.width() - reflectionOffset(), 0);
+            break;
+        case ReflectionRight:
+            result.move(box.width() + reflectionOffset(), 0);
+            break;
+    }
+    return result;
+}
+
+int RenderObject::reflectionOffset() const
+{
+    if (!m_style->boxReflect())
+        return 0;
+    if (m_style->boxReflect()->direction() == ReflectionLeft || m_style->boxReflect()->direction() == ReflectionRight)
+        return m_style->boxReflect()->offset().calcValue(borderBox().width());
+    return m_style->boxReflect()->offset().calcValue(borderBox().height());
+}
+
+#if ENABLE(SVG)
+
+FloatRect RenderObject::relativeBBox(bool) const
+{
+    return FloatRect();
+}
+
+AffineTransform RenderObject::localTransform() const
+{
+    return AffineTransform(1, 0, 0, 1, xPos(), yPos());
+}
+
+AffineTransform RenderObject::absoluteTransform() const
+{
+    if (parent())
+        return localTransform() * parent()->absoluteTransform();
+    return localTransform();
+}
+
+#endif // ENABLE(SVG)
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+
+void showTree(const WebCore::RenderObject* ro)
+{
+    if (ro)
+        ro->showTreeForThis();
+}
+
+#endif
diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h
new file mode 100644
index 0000000..b904c41
--- /dev/null
+++ b/WebCore/rendering/RenderObject.h
@@ -0,0 +1,974 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ *           (C) 2004 Allan Sandfeld Jensen ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderObject_h
+#define RenderObject_h
+
+#include "CachedResourceClient.h"
+#include "Document.h"
+#include "RenderStyle.h"
+#include "ScrollTypes.h"
+#include "VisiblePosition.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class AffineTransform;
+class AnimationController;
+class Color;
+class Document;
+class Element;
+class Event;
+class FloatRect;
+class FrameView;
+class HTMLAreaElement;
+class HitTestResult;
+class InlineBox;
+class InlineFlowBox;
+class Position;
+class RenderArena;
+class RenderBlock;
+class RenderFlow;
+class RenderFrameSet;
+class RenderLayer;
+class RenderTable;
+class RenderText;
+class RenderView;
+class String;
+
+struct HitTestRequest;
+
+/*
+ *  The painting of a layer occurs in three distinct phases.  Each phase involves
+ *  a recursive descent into the layer's render objects. The first phase is the background phase.
+ *  The backgrounds and borders of all blocks are painted.  Inlines are not painted at all.
+ *  Floats must paint above block backgrounds but entirely below inline content that can overlap them.
+ *  In the foreground phase, all inlines are fully painted.  Inline replaced elements will get all
+ *  three phases invoked on them during this phase.
+ */
+
+enum PaintPhase {
+    PaintPhaseBlockBackground,
+    PaintPhaseChildBlockBackground,
+    PaintPhaseChildBlockBackgrounds,
+    PaintPhaseFloat,
+    PaintPhaseForeground,
+    PaintPhaseOutline,
+    PaintPhaseChildOutlines,
+    PaintPhaseSelfOutline,
+    PaintPhaseSelection,
+    PaintPhaseCollapsedTableBorders,
+    PaintPhaseTextClip,
+    PaintPhaseMask
+};
+
+enum PaintRestriction {
+    PaintRestrictionNone,
+    PaintRestrictionSelectionOnly,
+    PaintRestrictionSelectionOnlyBlackText
+};
+
+enum HitTestFilter {
+    HitTestAll,
+    HitTestSelf,
+    HitTestDescendants
+};
+
+enum HitTestAction {
+    HitTestBlockBackground,
+    HitTestChildBlockBackground,
+    HitTestChildBlockBackgrounds,
+    HitTestFloat,
+    HitTestForeground
+};
+
+enum VerticalPositionHint {
+    PositionTop = -0x7fffffff,
+    PositionBottom = 0x7fffffff,
+    PositionUndefined = static_cast<int>(0x80000000)
+};
+
+#if ENABLE(DASHBOARD_SUPPORT)
+struct DashboardRegionValue {
+    bool operator==(const DashboardRegionValue& o) const
+    {
+        return type == o.type && bounds == o.bounds && clip == o.clip && label == o.label;
+    }
+    bool operator!=(const DashboardRegionValue& o) const
+    {
+        return !(*this == o);
+    }
+
+    String label;
+    IntRect bounds;
+    IntRect clip;
+    int type;
+};
+#endif
+
+// FIXME: This should be a HashSequencedSet, but we don't have that data structure yet.
+// This means the paint order of outlines will be wrong, although this is a minor issue.
+typedef HashSet<RenderFlow*> RenderFlowSequencedSet;
+
+// Base class for all rendering tree objects.
+class RenderObject : public CachedResourceClient {
+    friend class RenderContainer;
+    friend class RenderSVGContainer;
+    friend class RenderLayer;
+public:
+    // Anonymous objects should pass the document as their node, and they will then automatically be
+    // marked as anonymous in the constructor.
+    RenderObject(Node*);
+    virtual ~RenderObject();
+
+    virtual const char* renderName() const { return "RenderObject"; }
+
+    RenderObject* parent() const { return m_parent; }
+    bool isDescendantOf(const RenderObject*) const;
+
+    RenderObject* previousSibling() const { return m_previous; }
+    RenderObject* nextSibling() const { return m_next; }
+
+    virtual RenderObject* firstChild() const { return 0; }
+    virtual RenderObject* lastChild() const { return 0; }
+
+    RenderObject* nextInPreOrder() const;
+    RenderObject* nextInPreOrder(RenderObject* stayWithin) const;
+    RenderObject* nextInPreOrderAfterChildren() const;
+    RenderObject* nextInPreOrderAfterChildren(RenderObject* stayWithin) const;
+    RenderObject* previousInPreOrder() const;
+    RenderObject* childAt(unsigned) const;
+
+    RenderObject* firstLeafChild() const;
+    RenderObject* lastLeafChild() const;
+
+    virtual RenderLayer* layer() const { return 0; }
+    RenderLayer* enclosingLayer() const;
+    void addLayers(RenderLayer* parentLayer, RenderObject* newObject);
+    void removeLayers(RenderLayer* parentLayer);
+    void moveLayers(RenderLayer* oldParent, RenderLayer* newParent);
+    RenderLayer* findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent = true);
+    virtual void positionChildLayers() { }
+    virtual bool requiresLayer();
+
+    virtual IntRect getOverflowClipRect(int /*tx*/, int /*ty*/) { return IntRect(0, 0, 0, 0); }
+    virtual IntRect getClipRect(int /*tx*/, int /*ty*/) { return IntRect(0, 0, 0, 0); }
+    bool hasClip() { return isPositioned() && style()->hasClip(); }
+
+    virtual int getBaselineOfFirstLineBox() const { return -1; }
+    virtual int getBaselineOfLastLineBox() const { return -1; }
+
+    virtual bool isEmpty() const { return firstChild() == 0; }
+
+    virtual bool isEdited() const { return false; }
+    virtual void setEdited(bool) { }
+
+#ifndef NDEBUG
+    void setHasAXObject(bool flag) { m_hasAXObject = flag; }
+    bool hasAXObject() const { return m_hasAXObject; }
+#endif
+
+    // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
+    // children.
+    virtual RenderBlock* firstLineBlock() const;
+
+    // Called when an object that was floating or positioned becomes a normal flow object
+    // again.  We have to make sure the render tree updates as needed to accommodate the new
+    // normal flow object.
+    void handleDynamicFloatPositionChange();
+
+    // This function is a convenience helper for creating an anonymous block that inherits its
+    // style from this RenderObject.
+    RenderBlock* createAnonymousBlock();
+
+    // Whether or not a positioned element requires normal flow x/y to be computed
+    // to determine its position.
+    bool hasStaticX() const;
+    bool hasStaticY() const;
+    virtual void setStaticX(int /*staticX*/) { }
+    virtual void setStaticY(int /*staticY*/) { }
+    virtual int staticX() const { return 0; }
+    virtual int staticY() const { return 0; }
+
+    // RenderObject tree manipulation
+    //////////////////////////////////////////
+    virtual bool canHaveChildren() const;
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const { return true; }
+    virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject*);
+    virtual bool createsAnonymousWrapper() const { return false; }
+
+    // raw tree manipulation
+    virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
+    virtual void appendChildNode(RenderObject*, bool fullAppend = true);
+    virtual void insertChildNode(RenderObject* child, RenderObject* before, bool fullInsert = true);
+    // Designed for speed.  Don't waste time doing a bunch of work like layer updating and repainting when we know that our
+    // change in parentage is not going to affect anything.
+    virtual void moveChildNode(RenderObject*);
+    //////////////////////////////////////////
+
+protected:
+    //////////////////////////////////////////
+    // Helper functions. Dangerous to use!
+    void setPreviousSibling(RenderObject* previous) { m_previous = previous; }
+    void setNextSibling(RenderObject* next) { m_next = next; }
+    void setParent(RenderObject* parent) { m_parent = parent; }
+    //////////////////////////////////////////
+private:
+    void addAbsoluteRectForLayer(IntRect& result);
+
+public:
+#ifndef NDEBUG
+    void showTreeForThis() const;
+#endif
+
+    static RenderObject* createObject(Node*, RenderStyle*);
+
+    // Overloaded new operator.  Derived classes must override operator new
+    // in order to allocate out of the RenderArena.
+    void* operator new(size_t, RenderArena*) throw();
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void*, size_t);
+
+private:
+    // The normal operator new is disallowed on all render objects.
+    void* operator new(size_t) throw();
+
+public:
+    RenderArena* renderArena() const { return document()->renderArena(); }
+
+    virtual bool isApplet() const { return false; }
+    virtual bool isBR() const { return false; }
+    virtual bool isBlockFlow() const { return false; }
+    virtual bool isCounter() const { return false; }
+    virtual bool isFieldset() const { return false; }
+    virtual bool isFrame() const { return false; }
+    virtual bool isFrameSet() const { return false; }
+    virtual bool isImage() const { return false; }
+    virtual bool isInlineBlockOrInlineTable() const { return false; }
+    virtual bool isInlineContinuation() const;
+    virtual bool isInlineFlow() const { return false; }
+    virtual bool isListBox() const { return false; }
+    virtual bool isListItem() const { return false; }
+    virtual bool isListMarker() const { return false; }
+    virtual bool isMedia() const { return false; }
+    virtual bool isMenuList() const { return false; }
+    virtual bool isRenderBlock() const { return false; }
+    virtual bool isRenderImage() const { return false; }
+    virtual bool isRenderInline() const { return false; }
+    virtual bool isRenderPart() const { return false; }
+    virtual bool isRenderView() const { return false; }
+    virtual bool isSlider() const { return false; }
+    virtual bool isTable() const { return false; }
+    virtual bool isTableCell() const { return false; }
+    virtual bool isTableCol() const { return false; }
+    virtual bool isTableRow() const { return false; }
+    virtual bool isTableSection() const { return false; }
+    virtual bool isTextArea() const { return false; }
+    virtual bool isTextField() const { return false; }
+    virtual bool isWidget() const { return false; }
+
+
+    bool isRoot() const { return document()->documentElement() == node(); }
+    bool isBody() const;
+    bool isHR() const;
+
+    bool isHTMLMarquee() const;
+
+    virtual bool childrenInline() const { return false; }
+    virtual void setChildrenInline(bool) { }
+
+    virtual RenderFlow* continuation() const;
+
+#if ENABLE(SVG)
+    virtual bool isSVGRoot() const { return false; }
+    virtual bool isSVGContainer() const { return false; }
+    virtual bool isSVGHiddenContainer() const { return false; }
+    virtual bool isRenderPath() const { return false; }
+    virtual bool isSVGText() const { return false; }
+
+    virtual FloatRect relativeBBox(bool includeStroke = true) const;
+
+    virtual AffineTransform localTransform() const;
+    virtual AffineTransform absoluteTransform() const;
+#endif
+
+    virtual bool isEditable() const;
+
+    bool isAnonymous() const { return m_isAnonymous; }
+    void setIsAnonymous(bool b) { m_isAnonymous = b; }
+    bool isAnonymousBlock() const
+    {
+        return m_isAnonymous && style()->display() == BLOCK && style()->styleType() == RenderStyle::NOPSEUDO && !isListMarker();
+    }
+
+    bool isFloating() const { return m_floating; }
+    bool isPositioned() const { return m_positioned; } // absolute or fixed positioning
+    bool isRelPositioned() const { return m_relPositioned; } // relative positioning
+    bool isText() const  { return m_isText; }
+    bool isInline() const { return m_inline; }  // inline object
+    bool isCompact() const { return style()->display() == COMPACT; } // compact object
+    bool isRunIn() const { return style()->display() == RUN_IN; } // run-in object
+    bool isDragging() const { return m_isDragging; }
+    bool isReplaced() const { return m_replaced; } // a "replaced" element (see CSS)
+    
+    bool hasLayer() const { return m_hasLayer; }
+    
+    bool hasBoxDecorations() const { return m_paintBackground; }
+    bool mustRepaintBackgroundOrBorder() const;
+
+    bool hasHorizontalBordersPaddingOrMargin() const { return hasHorizontalBordersOrPadding() || marginLeft() != 0 || marginRight() != 0; }
+    bool hasHorizontalBordersOrPadding() const { return borderLeft() != 0 || borderRight() != 0 || paddingLeft() != 0 || paddingRight() != 0; }
+                                                              
+    bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout || m_needsPositionedMovementLayout; }
+    bool selfNeedsLayout() const { return m_needsLayout; }
+    bool needsPositionedMovementLayout() const { return m_needsPositionedMovementLayout; }
+    bool needsPositionedMovementLayoutOnly() const { return m_needsPositionedMovementLayout && !m_needsLayout && !m_normalChildNeedsLayout && !m_posChildNeedsLayout; }
+    bool posChildNeedsLayout() const { return m_posChildNeedsLayout; }
+    bool normalChildNeedsLayout() const { return m_normalChildNeedsLayout; }
+    
+    bool prefWidthsDirty() const { return m_prefWidthsDirty; }
+
+    bool isSelectionBorder() const;
+
+    bool hasOverflowClip() const { return m_hasOverflowClip; }
+    virtual bool hasControlClip() const { return false; }
+    virtual IntRect controlClipRect(int /*tx*/, int /*ty*/) const { return IntRect(); }
+
+    bool hasAutoVerticalScrollbar() const { return hasOverflowClip() && (style()->overflowY() == OAUTO || style()->overflowY() == OOVERLAY); }
+    bool hasAutoHorizontalScrollbar() const { return hasOverflowClip() && (style()->overflowX() == OAUTO || style()->overflowX() == OOVERLAY); }
+
+    bool scrollsOverflow() const { return scrollsOverflowX() || scrollsOverflowY(); }
+    bool scrollsOverflowX() const { return hasOverflowClip() && (style()->overflowX() == OSCROLL || hasAutoHorizontalScrollbar()); }
+    bool scrollsOverflowY() const { return hasOverflowClip() && (style()->overflowY() == OSCROLL || hasAutoVerticalScrollbar()); }
+
+    virtual int verticalScrollbarWidth() const;
+    virtual int horizontalScrollbarHeight() const;
+    
+    bool hasTransform() const { return m_hasTransform; }
+    bool hasMask() const { return style() && style()->hasMask(); }
+    virtual IntRect maskClipRect() { return borderBox(); }
+
+private:
+    bool includeVerticalScrollbarSize() const { return hasOverflowClip() && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO); }
+    bool includeHorizontalScrollbarSize() const { return hasOverflowClip() && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO); }
+
+public:
+    // The pseudo element style can be cached or uncached.  Use the cached method if the pseudo element doesn't respect
+    // any pseudo classes (and therefore has no concept of changing state).
+    RenderStyle* getCachedPseudoStyle(RenderStyle::PseudoId, RenderStyle* parentStyle = 0) const;
+    PassRefPtr<RenderStyle> getUncachedPseudoStyle(RenderStyle::PseudoId, RenderStyle* parentStyle = 0) const;
+    
+    void updateDragState(bool dragOn);
+
+    RenderView* view() const;
+
+    // don't even think about making this method virtual!
+    Node* element() const { return m_isAnonymous ? 0 : m_node; }
+    Document* document() const { return m_node->document(); }
+    void setNode(Node* node) { m_node = node; }
+    Node* node() const { return m_node; }
+
+    bool hasOutlineAnnotation() const;
+    bool hasOutline() const { return style()->hasOutline() || hasOutlineAnnotation(); }
+
+   /**
+     * returns the object containing this one. can be different from parent for
+     * positioned elements
+     */
+    RenderObject* container() const;
+    RenderObject* hoverAncestor() const;
+
+    virtual void markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove = 0);
+    void markContainingBlocksForLayout(bool scheduleRelayout = true, RenderObject* newRoot = 0);
+    void setNeedsLayout(bool b, bool markParents = true);
+    void setChildNeedsLayout(bool b, bool markParents = true);
+    void setNeedsPositionedMovementLayout();
+    void setPrefWidthsDirty(bool, bool markParents = true);
+    void invalidateContainerPrefWidths();
+    virtual void invalidateCounters() { }
+    
+    void setNeedsLayoutAndPrefWidthsRecalc()
+    {
+        setNeedsLayout(true);
+        setPrefWidthsDirty(true);
+    }
+
+    void setPositioned(bool b = true)  { m_positioned = b;  }
+    void setRelPositioned(bool b = true) { m_relPositioned = b; }
+    void setFloating(bool b = true) { m_floating = b; }
+    void setInline(bool b = true) { m_inline = b; }
+    void setHasBoxDecorations(bool b = true) { m_paintBackground = b; }
+    void setRenderText() { m_isText = true; }
+    void setReplaced(bool b = true) { m_replaced = b; }
+    void setHasOverflowClip(bool b = true) { m_hasOverflowClip = b; }
+    void setHasLayer(bool b = true) { m_hasLayer = b; }
+    void setHasTransform(bool b = true) { m_hasTransform = b; }
+    void setHasReflection(bool b = true) { m_hasReflection = b; }
+
+    void scheduleRelayout();
+
+    void updateFillImages(const FillLayer*, const FillLayer*);
+    void updateImage(StyleImage*, StyleImage*);
+
+    virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun = false);
+    virtual void dirtyLineBoxes(bool fullLayout, bool isRootLineBox = false);
+
+    // For inline replaced elements, this function returns the inline box that owns us.  Enables
+    // the replaced RenderObject to quickly determine what line it is contained on and to easily
+    // iterate over structures on the line.
+    virtual InlineBox* inlineBoxWrapper() const;
+    virtual void setInlineBoxWrapper(InlineBox*);
+    virtual void deleteLineBoxWrapper();
+
+    // for discussion of lineHeight see CSS2 spec
+    virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
+    // for the vertical-align property of inline elements
+    // the difference between this objects baseline position and the lines baseline position.
+    virtual int verticalPositionHint(bool firstLine) const;
+    // the offset of baseline from the top of the object.
+    virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
+
+    /*
+     * Paint the object and its children, clipped by (x|y|w|h).
+     * (tx|ty) is the calculated position of the parent
+     */
+    struct PaintInfo {
+        PaintInfo(GraphicsContext* newContext, const IntRect& newRect, PaintPhase newPhase, bool newForceBlackText,
+                  RenderObject* newPaintingRoot, RenderFlowSequencedSet* newOutlineObjects)
+            : context(newContext)
+            , rect(newRect)
+            , phase(newPhase)
+            , forceBlackText(newForceBlackText)
+            , paintingRoot(newPaintingRoot)
+            , outlineObjects(newOutlineObjects)
+        {
+        }
+
+        GraphicsContext* context;
+        IntRect rect;
+        PaintPhase phase;
+        bool forceBlackText;
+        RenderObject* paintingRoot; // used to draw just one element and its visual kids
+        RenderFlowSequencedSet* outlineObjects; // used to list outlines that should be painted by a block with inline children
+    };
+
+    virtual void paint(PaintInfo&, int tx, int ty);
+    void paintBorder(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, bool begin = true, bool end = true);
+    bool paintNinePieceImage(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, const NinePieceImage&, CompositeOperator = CompositeSourceOver);
+    void paintOutline(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*);
+    void paintBoxShadow(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, bool begin = true, bool end = true);
+
+    // RenderBox implements this.
+    virtual void paintBoxDecorations(PaintInfo&, int tx, int ty) { }
+    virtual void paintMask(PaintInfo&, int tx, int ty) { }
+    virtual void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*,
+                                        int clipy, int cliph, int tx, int ty, int width, int height,
+                                        InlineFlowBox* box = 0, CompositeOperator = CompositeSourceOver) { }
+
+    
+    /*
+     * Calculates the actual width of the object (only for non inline
+     * objects)
+     */
+    virtual void calcWidth() { }
+
+    /*
+     * This function should cause the Element to calculate its
+     * width and height and the layout of its content
+     *
+     * when the Element calls setNeedsLayout(false), layout() is no
+     * longer called during relayouts, as long as there is no
+     * style sheet change. When that occurs, m_needsLayout will be
+     * set to true and the Element receives layout() calls
+     * again.
+     */
+    virtual void layout() = 0;
+
+    /* This function performs a layout only if one is needed. */
+    void layoutIfNeeded() { if (needsLayout()) layout(); }
+
+    // Called when a positioned object moves but doesn't necessarily change size.  A simplified layout is attempted
+    // that just updates the object's position. If the size does change, the object remains dirty.
+    virtual void tryLayoutDoingPositionedMovementOnly() { }
+    
+    // used for element state updates that cannot be fixed with a
+    // repaint and do not need a relayout
+    virtual void updateFromElement() { }
+
+    // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.)
+    virtual int availableWidth() const { return contentWidth(); }
+    
+    virtual int availableHeight() const { return 0; }
+
+    virtual void updateWidgetPosition();
+
+#if ENABLE(DASHBOARD_SUPPORT)
+    void addDashboardRegions(Vector<DashboardRegionValue>&);
+    void collectDashboardRegions(Vector<DashboardRegionValue>&);
+#endif
+
+    bool hitTest(const HitTestRequest&, HitTestResult&, const IntPoint&, int tx, int ty, HitTestFilter = HitTestAll);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+    void updateHitTestResult(HitTestResult&, const IntPoint&);
+
+    virtual VisiblePosition positionForCoordinates(int x, int y);
+    VisiblePosition positionForPoint(const IntPoint& point) { return positionForCoordinates(point.x(), point.y()); }
+
+    virtual void dirtyLinesFromChangedChild(RenderObject*);
+
+    // Called to update a style that is allowed to trigger animations.
+    // FIXME: Right now this will typically be called only when updating happens from the DOM on explicit elements.
+    // We don't yet handle generated content animation such as first-letter or before/after (we'll worry about this later).
+    void setAnimatableStyle(PassRefPtr<RenderStyle>);
+
+    // Set the style of the object and update the state of the object accordingly.
+    virtual void setStyle(PassRefPtr<RenderStyle>);
+
+    // Updates only the local style ptr of the object.  Does not update the state of the object,
+    // and so only should be called when the style is known not to have changed (or from setStyle).
+    void setStyleInternal(PassRefPtr<RenderStyle>);
+
+    // returns the containing block level element for this element.
+    RenderBlock* containingBlock() const;
+
+    // return just the width of the containing block
+    virtual int containingBlockWidth() const;
+    // return just the height of the containing block
+    virtual int containingBlockHeight() const;
+
+    // content area (box minus padding/border)
+    IntRect contentBox() const;
+    IntRect absoluteContentBox() const;
+    int contentWidth() const { return clientWidth() - paddingLeft() - paddingRight(); }
+    int contentHeight() const { return clientHeight() - paddingTop() - paddingBottom(); }
+
+    // used by flexible boxes to impose a flexed width/height override
+    virtual int overrideSize() const { return 0; }
+    virtual int overrideWidth() const { return 0; }
+    virtual int overrideHeight() const { return 0; }
+    virtual void setOverrideSize(int /*overrideSize*/) { }
+
+    // relative to parent node
+    virtual void setPos(int /*xPos*/, int /*yPos*/) { }
+    virtual void setWidth(int /*width*/) { }
+    virtual void setHeight(int /*height*/) { }
+    virtual void setRect(const IntRect& rect) { setPos(rect.x(), rect.y()); setWidth(rect.width()); setHeight(rect.height()); }
+
+    virtual int xPos() const { return 0; }
+    virtual int yPos() const { return 0; }
+
+    // calculate client position of box
+    virtual bool absolutePosition(int& x, int& y, bool fixed = false) const;
+
+    // This function is used to deal with the extra top space that can occur in table cells (called borderTopExtra).
+    // The children of the cell do not factor this space in, so we have to add it in.  Any code that wants to
+    // accurately deal with the contents of a cell must call this function instad of absolutePosition.
+    bool absolutePositionForContent(int& xPos, int& yPos, bool fixed = false) const
+    {
+        bool result = absolutePosition(xPos, yPos, fixed);
+        yPos += borderTopExtra();
+        return result;
+    }
+
+    // width and height are without margins but include paddings and borders
+    virtual int width() const { return 0; }
+    virtual int height() const { return 0; }
+
+    virtual IntRect borderBox() const { return IntRect(0, 0, width(), height()); }
+    IntRect absoluteOutlineBox() const;
+
+    // The height of a block when you include normal flow overflow spillage out of the bottom
+    // of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside
+    // it would have an overflow height of borderTop() + paddingTop() + 100px.
+    virtual int overflowHeight(bool /*includeInterior*/ = true) const { return height(); }
+    virtual int overflowWidth(bool /*includeInterior*/ = true) const { return width(); }
+    virtual void setOverflowHeight(int) { }
+    virtual void setOverflowWidth(int) { }
+    virtual int overflowLeft(bool /*includeInterior*/ = true) const { return 0; }
+    virtual int overflowTop(bool /*includeInterior*/ = true) const { return 0; }
+    virtual IntRect overflowRect(bool /*includeInterior*/ = true) const { return borderBox(); }
+
+    // IE extensions. Used to calculate offsetWidth/Height.  Overridden by inlines (RenderFlow)
+    // to return the remaining width on a given line (and the height of a single line).
+    virtual int offsetWidth() const { return width(); }
+    virtual int offsetHeight() const { return height() + borderTopExtra() + borderBottomExtra(); }
+
+    // IE extensions.  Also supported by Gecko.  We override in render flow to get the
+    // left and top correct. -dwh
+    virtual int offsetLeft() const;
+    virtual int offsetTop() const;
+    virtual RenderObject* offsetParent() const;
+
+    // More IE extensions.  clientWidth and clientHeight represent the interior of an object
+    // excluding border and scrollbar.  clientLeft/Top are just the borderLeftWidth and borderTopWidth.
+    int clientLeft() const { return borderLeft(); }
+    int clientTop() const { return borderTop(); }
+    int clientWidth() const;
+    int clientHeight() const;
+
+    // scrollWidth/scrollHeight will be the same as clientWidth/clientHeight unless the
+    // object has overflow:hidden/scroll/auto specified and also has overflow.
+    // scrollLeft/Top return the current scroll position.  These methods are virtual so that objects like
+    // textareas can scroll shadow content (but pretend that they are the objects that are
+    // scrolling).
+    virtual int scrollLeft() const;
+    virtual int scrollTop() const;
+    virtual int scrollWidth() const;
+    virtual int scrollHeight() const;
+    virtual void setScrollLeft(int);
+    virtual void setScrollTop(int);
+
+    virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f);
+    virtual bool canBeProgramaticallyScrolled(bool) const;
+    virtual void autoscroll();
+    virtual void stopAutoscroll() { }
+
+    virtual void panScroll(const IntPoint&);
+
+    virtual bool isScrollable() const;
+
+    // The following seven functions are used to implement collapsing margins.
+    // All objects know their maximal positive and negative margins.  The
+    // formula for computing a collapsed margin is |maxPosMargin|-|maxNegmargin|.
+    // For a non-collapsing, e.g., a leaf element, this formula will simply return
+    // the margin of the element.  Blocks override the maxTopMargin and maxBottomMargin
+    // methods.
+    virtual bool isSelfCollapsingBlock() const { return false; }
+    virtual int collapsedMarginTop() const { return maxTopMargin(true) - maxTopMargin(false); }
+    virtual int collapsedMarginBottom() const { return maxBottomMargin(true) - maxBottomMargin(false); }
+    virtual bool isTopMarginQuirk() const { return false; }
+    virtual bool isBottomMarginQuirk() const { return false; }
+
+    virtual int maxTopMargin(bool positive) const;
+    virtual int maxBottomMargin(bool positive) const;
+
+    virtual int marginTop() const { return 0; }
+    virtual int marginBottom() const { return 0; }
+    virtual int marginLeft() const { return 0; }
+    virtual int marginRight() const { return 0; }
+
+    // Virtual since table cells override
+    virtual int paddingTop() const;
+    virtual int paddingBottom() const;
+    virtual int paddingLeft() const;
+    virtual int paddingRight() const;
+
+    virtual int borderTop() const { return style()->borderTopWidth(); }
+    virtual int borderBottom() const { return style()->borderBottomWidth(); }
+    virtual int borderTopExtra() const { return 0; }
+    virtual int borderBottomExtra() const { return 0; }
+    virtual int borderLeft() const { return style()->borderLeftWidth(); }
+    virtual int borderRight() const { return style()->borderRightWidth(); }
+
+    virtual void addLineBoxRects(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
+
+    virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
+    IntRect absoluteBoundingBoxRect();
+
+    // the rect that will be painted if this object is passed as the paintingRoot
+    IntRect paintingRootRect(IntRect& topLevelRect);
+
+    void addPDFURLRect(GraphicsContext*, const IntRect&);
+
+    virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+
+    virtual int minPrefWidth() const { return 0; }
+    virtual int maxPrefWidth() const { return 0; }
+
+    RenderStyle* style() const { return m_style.get(); }
+    RenderStyle* firstLineStyle() const;
+    RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); }
+
+    void getTextDecorationColors(int decorations, Color& underline, Color& overline,
+                                 Color& linethrough, bool quirksMode = false);
+
+    enum BorderSide {
+        BSTop,
+        BSBottom,
+        BSLeft,
+        BSRight
+    };
+
+    void drawBorderArc(GraphicsContext*, int x, int y, float thickness, IntSize radius, int angleStart,
+                       int angleSpan, BorderSide, Color, const Color& textcolor, EBorderStyle, bool firstCorner);
+    void drawBorder(GraphicsContext*, int x1, int y1, int x2, int y2, BorderSide,
+                    Color, const Color& textcolor, EBorderStyle, int adjbw1, int adjbw2);
+
+    // Repaint the entire object.  Called when, e.g., the color of a border changes, or when a border
+    // style changes.
+    void repaint(bool immediate = false);
+
+    // Repaint a specific subrectangle within a given object.  The rect |r| is in the object's coordinate space.
+    void repaintRectangle(const IntRect&, bool immediate = false);
+
+    // Repaint only if our old bounds and new bounds are different.
+    bool repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const IntRect& oldOutlineBox);
+
+    // Repaint only if the object moved.
+    virtual void repaintDuringLayoutIfMoved(const IntRect& rect);
+
+    // Called to repaint a block's floats.
+    virtual void repaintOverhangingFloats(bool paintAllDescendants = false);
+
+    bool checkForRepaintDuringLayout() const;
+
+    // Returns the rect that should be repainted whenever this object changes.  The rect is in the view's
+    // coordinate space.  This method deals with outlines and overflow.
+    virtual IntRect absoluteClippedOverflowRect();
+
+    IntRect getAbsoluteRepaintRectWithOutline(int ow);
+
+    // Given a rect in the object's coordinate space, this method converts the rectangle to the view's
+    // coordinate space.
+    virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed = false);
+
+    virtual unsigned int length() const { return 1; }
+
+    bool isFloatingOrPositioned() const { return (isFloating() || isPositioned()); }
+    virtual bool containsFloats() { return false; }
+    virtual bool containsFloat(RenderObject*) { return false; }
+    virtual bool hasOverhangingFloats() { return false; }
+    virtual bool expandsToEncloseOverhangingFloats() const { return isFloating() && style()->height().isAuto(); }
+
+    virtual void removePositionedObjects(RenderBlock*) { }
+
+    virtual bool avoidsFloats() const;
+    bool shrinkToAvoidFloats() const;
+
+    // positioning of inline children (bidi)
+    virtual void position(InlineBox*) { }
+
+    bool isTransparent() const { return style()->opacity() < 1.0f; }
+    float opacity() const { return style()->opacity(); }
+
+    bool hasReflection() const { return m_hasReflection; }
+    IntRect reflectionBox() const;
+    int reflectionOffset() const;
+
+    // Applied as a "slop" to dirty rect checks during the outline painting phase's dirty-rect checks.
+    int maximalOutlineSize(PaintPhase) const;
+
+    enum SelectionState {
+        SelectionNone, // The object is not selected.
+        SelectionStart, // The object either contains the start of a selection run or is the start of a run
+        SelectionInside, // The object is fully encompassed by a selection run
+        SelectionEnd, // The object either contains the end of a selection run or is the end of a run
+        SelectionBoth // The object contains an entire run or is the sole selected object in that run
+    };
+
+    // The current selection state for an object.  For blocks, the state refers to the state of the leaf
+    // descendants (as described above in the SelectionState enum declaration).
+    virtual SelectionState selectionState() const { return SelectionNone; }
+
+    // Sets the selection state for an object.
+    virtual void setSelectionState(SelectionState state) { if (parent()) parent()->setSelectionState(state); }
+
+    // A single rectangle that encompasses all of the selected objects within this object.  Used to determine the tightest
+    // possible bounding box for the selection.
+    virtual IntRect selectionRect(bool) { return IntRect(); }
+
+    // Whether or not an object can be part of the leaf elements of the selection.
+    virtual bool canBeSelectionLeaf() const { return false; }
+
+    // Whether or not a block has selected children.
+    virtual bool hasSelectedChildren() const { return false; }
+
+    // Obtains the selection colors that should be used when painting a selection.
+    Color selectionBackgroundColor() const;
+    Color selectionForegroundColor() const;
+
+    // Whether or not a given block needs to paint selection gaps.
+    virtual bool shouldPaintSelectionGaps() const { return false; }
+
+    // This struct is used when the selection changes to cache the old and new state of the selection for each RenderObject.
+    struct SelectionInfo {
+        SelectionInfo()
+            : m_object(0)
+            , m_state(SelectionNone)
+        {
+        }
+
+        SelectionInfo(RenderObject* o, bool clipToVisibleContent)
+            : m_object(o)
+            , m_rect(o->needsLayout() ? IntRect() : o->selectionRect(clipToVisibleContent))
+            , m_state(o->selectionState())
+        {
+        }
+
+        RenderObject* object() const { return m_object; }
+        IntRect rect() const { return m_rect; }
+        SelectionState state() const { return m_state; }
+
+        RenderObject* m_object;
+        IntRect m_rect;
+        SelectionState m_state;
+    };
+
+    Node* draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const;
+
+    /**
+     * Returns the content coordinates of the caret within this render object.
+     * @param offset zero-based offset determining position within the render object.
+     * @param override @p true if input overrides existing characters,
+     * @p false if it inserts them. The width of the caret depends on this one.
+     * @param extraWidthToEndOfLine optional out arg to give extra width to end of line -
+     * useful for character range rect computations
+     */
+    virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
+
+    virtual int lowestPosition(bool /*includeOverflowInterior*/ = true, bool /*includeSelf*/ = true) const { return 0; }
+    virtual int rightmostPosition(bool /*includeOverflowInterior*/ = true, bool /*includeSelf*/ = true) const { return 0; }
+    virtual int leftmostPosition(bool /*includeOverflowInterior*/ = true, bool /*includeSelf*/ = true) const { return 0; }
+
+    virtual void calcVerticalMargins() { }
+    void removeFromObjectLists();
+
+    // When performing a global document tear-down, the renderer of the document is cleared.  We use this
+    // as a hook to detect the case of document destruction and don't waste time doing unnecessary work.
+    bool documentBeingDestroyed() const;
+
+    virtual void destroy();
+
+    // Virtual function helpers for CSS3 Flexible Box Layout
+    virtual bool isFlexibleBox() const { return false; }
+    virtual bool isFlexingChildren() const { return false; }
+    virtual bool isStretchingChildren() const { return false; }
+
+    // Convenience, to avoid repeating the code to dig down to get this.
+    UChar backslashAsCurrencySymbol() const;
+
+    virtual int caretMinOffset() const;
+    virtual int caretMaxOffset() const;
+    virtual unsigned caretMaxRenderedOffset() const;
+
+    virtual int previousOffset(int current) const;
+    virtual int nextOffset(int current) const;
+
+    virtual void imageChanged(CachedImage* image);
+    virtual void imageChanged(WrappedImagePtr data) { };
+    virtual bool willRenderImage(CachedImage*);
+
+    virtual void selectionStartEnd(int& spos, int& epos) const;
+
+    RenderObject* paintingRootForChildren(PaintInfo& paintInfo) const
+    {
+        // if we're the painting root, kids draw normally, and see root of 0
+        return (!paintInfo.paintingRoot || paintInfo.paintingRoot == this) ? 0 : paintInfo.paintingRoot;
+    }
+
+    bool shouldPaintWithinRoot(PaintInfo& paintInfo) const
+    {
+        return !paintInfo.paintingRoot || paintInfo.paintingRoot == this;
+    }
+#ifdef ANDROID_LAYOUT
+    virtual bool hasChildTable() const { return false; }
+#endif
+
+    bool hasOverrideSize() const { return m_hasOverrideSize; }
+    void setHasOverrideSize(bool b) { m_hasOverrideSize = b; }
+    
+    void remove() { if (parent()) parent()->removeChild(this); }
+
+    void invalidateVerticalPosition() { m_verticalPosition = PositionUndefined; }
+    
+    virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
+    
+    virtual void capsLockStateMayHaveChanged() { }
+
+    AnimationController* animation() const;
+
+protected:
+    // Overrides should call the superclass at the end
+    virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
+    // Overrides should call the superclass at the start
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+    
+    virtual void printBoxDecorations(GraphicsContext*, int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*tx*/, int /*ty*/) { }
+
+    virtual IntRect viewRect() const;
+
+    int getVerticalPosition(bool firstLine) const;
+
+    void adjustRectForOutlineAndShadow(IntRect&) const;
+
+    void arenaDelete(RenderArena*, void* objectBase);
+
+private:
+    RefPtr<RenderStyle> m_style;
+
+    Node* m_node;
+
+    RenderObject* m_parent;
+    RenderObject* m_previous;
+    RenderObject* m_next;
+
+#ifndef NDEBUG
+    bool m_hasAXObject;
+#endif
+    mutable int m_verticalPosition;
+
+    bool m_needsLayout               : 1;
+    bool m_needsPositionedMovementLayout :1;
+    bool m_normalChildNeedsLayout    : 1;
+    bool m_posChildNeedsLayout       : 1;
+    bool m_prefWidthsDirty           : 1;
+    bool m_floating                  : 1;
+
+    bool m_positioned                : 1;
+    bool m_relPositioned             : 1;
+    bool m_paintBackground           : 1; // if the box has something to paint in the
+                                          // background painting phase (background, border, etc)
+
+    bool m_isAnonymous               : 1;
+    bool m_isText                    : 1;
+    bool m_inline                    : 1;
+    bool m_replaced                  : 1;
+    bool m_isDragging                : 1;
+
+    bool m_hasLayer                  : 1;
+    bool m_hasOverflowClip           : 1;
+    bool m_hasTransform              : 1;
+    bool m_hasReflection             : 1;
+
+    bool m_hasOverrideSize           : 1;
+    
+public:
+    bool m_hasCounterNodeMap         : 1;
+    bool m_everHadLayout             : 1;
+
+private:
+    // Store state between styleWillChange and styleDidChange
+    static bool s_affectsParentBlock;
+};
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showTree(const WebCore::RenderObject*);
+#endif
+
+#endif // RenderObject_h
diff --git a/WebCore/rendering/RenderPart.cpp b/WebCore/rendering/RenderPart.cpp
new file mode 100644
index 0000000..a9a821e
--- /dev/null
+++ b/WebCore/rendering/RenderPart.cpp
@@ -0,0 +1,117 @@
+/**
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 2000 Simon Hausmann <[email protected]>
+ *           (C) 2000 Stefan Schimanski ([email protected])
+ * Copyright (C) 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#include "config.h"
+#include "RenderPart.h"
+
+#include "Document.h"
+#include "Frame.h"
+#include "FrameTree.h"
+#include "FrameView.h"
+#include "HTMLFrameOwnerElement.h"
+#include "HTMLNames.h"
+#include "Page.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderPart::RenderPart(HTMLFrameOwnerElement* node)
+    : RenderWidget(node)
+{
+    // init RenderObject attributes
+    setInline(false);
+}
+
+RenderPart::~RenderPart()
+{
+    // Since deref ends up calling setWidget back on us, need to make sure
+    // that widget is already 0 so it won't do any work.
+    Widget* widget = m_widget;
+    m_widget = 0;
+    if (widget && widget->isFrameView())
+        static_cast<FrameView*>(widget)->deref();
+    else
+        delete widget;
+}
+
+void RenderPart::setWidget(Widget* widget)
+{
+    if (widget != m_widget) {
+        if (widget && widget->isFrameView())
+            static_cast<FrameView*>(widget)->ref();
+        RenderWidget::setWidget(widget);
+
+        // make sure the scrollbars are set correctly for restore
+        // ### find better fix
+        viewCleared();
+    }
+}
+
+void RenderPart::viewCleared()
+{
+}
+
+void RenderPart::deleteWidget()
+{
+    if (m_widget && m_widget->isFrameView())
+        static_cast<FrameView*>(m_widget)->deref();
+    else
+        delete m_widget;
+}
+
+// FIXME: This should not be necessary.  Remove this once WebKit knows to properly schedule
+// layouts using WebCore when objects resize.
+void RenderPart::updateWidgetPosition()
+{
+    if (!m_widget)
+        return;
+    
+    int x, y, width, height;
+    absolutePosition(x, y);
+    x += borderLeft() + paddingLeft();
+    y += borderTop() + paddingTop();
+    width = m_width - borderLeft() - borderRight() - paddingLeft() - paddingRight();
+    height = m_height - borderTop() - borderBottom() - paddingTop() - paddingBottom();
+    IntRect newBounds(x,y,width,height);
+    bool boundsChanged = newBounds != m_widget->frameRect();
+    if (boundsChanged) {
+        // The widget changed positions.  Update the frame geometry.
+        RenderArena *arena = ref();
+        element()->ref();
+        m_widget->setFrameRect(newBounds);
+        element()->deref();
+        deref(arena);
+    }
+
+    // if the frame bounds got changed, or if view needs layout (possibly indicating
+    // content size is wrong) we have to do a layout to set the right widget size
+    if (m_widget && m_widget->isFrameView()) {
+        FrameView* frameView = static_cast<FrameView*>(m_widget);
+        if (boundsChanged || frameView->needsLayout())
+            frameView->layout();
+    }
+}
+
+}
diff --git a/WebCore/rendering/RenderPart.h b/WebCore/rendering/RenderPart.h
new file mode 100644
index 0000000..e339468
--- /dev/null
+++ b/WebCore/rendering/RenderPart.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 2000 Simon Hausmann <[email protected]>
+ * Copyright (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderPart_h
+#define RenderPart_h
+
+#include "RenderWidget.h"
+
+namespace WebCore {
+
+class Frame;
+class HTMLFrameOwnerElement;
+
+class RenderPart : public RenderWidget {
+public:
+    RenderPart(HTMLFrameOwnerElement*);
+    virtual ~RenderPart();
+    
+    virtual bool isRenderPart() const { return true; }
+    virtual const char* renderName() const { return "RenderPart"; }
+
+    virtual void setWidget(Widget*);
+
+    // FIXME: This should not be necessary.
+    // Remove this once WebKit knows to properly schedule layouts using WebCore when objects resize.
+    virtual void updateWidgetPosition();
+
+    bool hasFallbackContent() const { return m_hasFallbackContent; }
+
+    virtual void viewCleared();
+
+protected:
+    bool m_hasFallbackContent;
+
+private:
+    virtual void deleteWidget();
+};
+
+}
+
+#endif
diff --git a/WebCore/rendering/RenderPartObject.cpp b/WebCore/rendering/RenderPartObject.cpp
new file mode 100644
index 0000000..75ecdec
--- /dev/null
+++ b/WebCore/rendering/RenderPartObject.cpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 2000 Simon Hausmann <[email protected]>
+ *           (C) 2000 Stefan Schimanski ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderPartObject.h"
+
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameLoaderClient.h"
+#include "FrameTree.h"
+#include "FrameView.h"
+#include "HTMLEmbedElement.h"
+#include "HTMLIFrameElement.h"
+#include "HTMLNames.h"
+#include "HTMLObjectElement.h"
+#include "HTMLParamElement.h"
+#include "MIMETypeRegistry.h"
+#include "Page.h"
+#include "Text.h"
+
+#ifdef FLATTEN_IFRAME
+#include "RenderView.h"
+#endif
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderPartObject::RenderPartObject(HTMLFrameOwnerElement* element)
+    : RenderPart(element)
+{
+    // init RenderObject attributes
+    setInline(true);
+    m_hasFallbackContent = false;
+}
+
+RenderPartObject::~RenderPartObject()
+{
+    if (m_view)
+        m_view->removeWidgetToUpdate(this);
+}
+
+static bool isURLAllowed(Document* doc, const String& url)
+{
+    if (doc->frame()->page()->frameCount() >= 200)
+        return false;
+
+    // We allow one level of self-reference because some sites depend on that.
+    // But we don't allow more than one.
+    KURL completeURL = doc->completeURL(url);
+    bool foundSelfReference = false;
+    for (Frame* frame = doc->frame(); frame; frame = frame->tree()->parent()) {
+        if (equalIgnoringRef(frame->loader()->url(), completeURL)) {
+            if (foundSelfReference)
+                return false;
+            foundSelfReference = true;
+        }
+    }
+    return true;
+}
+
+static inline void mapClassIdToServiceType(const String& classId, String& serviceType)
+{
+    // It is ActiveX, but the nsplugin system handling
+    // should also work, that's why we don't override the
+    // serviceType with application/x-activex-handler
+    // but let the KTrader in khtmlpart::createPart() detect
+    // the user's preference: launch with activex viewer or
+    // with nspluginviewer (Niko)
+    if (classId.contains("D27CDB6E-AE6D-11cf-96B8-444553540000"))
+        serviceType = "application/x-shockwave-flash";
+    else if (classId.contains("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA"))
+        serviceType = "audio/x-pn-realaudio-plugin";
+    else if (classId.contains("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"))
+        serviceType = "video/quicktime";
+    else if (classId.contains("166B1BCA-3F9C-11CF-8075-444553540000"))
+        serviceType = "application/x-director";
+    else if (classId.contains("6BF52A52-394A-11d3-B153-00C04F79FAA6"))
+        serviceType = "application/x-mplayer2";
+    else if (!classId.isEmpty()) {
+        // We have a clsid, means this is Active X (Niko)
+        serviceType = "application/x-activex-handler";
+    }
+}
+
+void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
+{
+  String url;
+  String serviceType;
+  Vector<String> paramNames;
+  Vector<String> paramValues;
+  Frame* frame = m_view->frame();
+  
+  if (element()->hasTagName(objectTag)) {
+
+      HTMLObjectElement* o = static_cast<HTMLObjectElement*>(element());
+
+      o->setNeedWidgetUpdate(false);
+      if (!o->isFinishedParsingChildren())
+        return;
+      // Check for a child EMBED tag.
+      HTMLEmbedElement* embed = 0;
+      for (Node* child = o->firstChild(); child;) {
+          if (child->hasTagName(embedTag)) {
+              embed = static_cast<HTMLEmbedElement*>(child);
+              break;
+          } else if (child->hasTagName(objectTag))
+              child = child->nextSibling();         // Don't descend into nested OBJECT tags
+          else
+              child = child->traverseNextNode(o);   // Otherwise descend (EMBEDs may be inside COMMENT tags)
+      }
+      
+      // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT.
+      HTMLElement *embedOrObject;
+      if (embed) {
+          embedOrObject = (HTMLElement *)embed;
+          url = embed->url();
+          serviceType = embed->serviceType();
+      } else
+          embedOrObject = (HTMLElement *)o;
+      
+      // If there was no URL or type defined in EMBED, try the OBJECT tag.
+      if (url.isEmpty())
+          url = o->url();
+      if (serviceType.isEmpty())
+          serviceType = o->serviceType();
+      
+      HashSet<StringImpl*, CaseFoldingHash> uniqueParamNames;
+      
+      // Scan the PARAM children.
+      // Get the URL and type from the params if we don't already have them.
+      // Get the attributes from the params if there is no EMBED tag.
+      Node *child = o->firstChild();
+      while (child && (url.isEmpty() || serviceType.isEmpty() || !embed)) {
+          if (child->hasTagName(paramTag)) {
+              HTMLParamElement* p = static_cast<HTMLParamElement*>(child);
+              String name = p->name();
+              if (url.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url")))
+                  url = p->value();
+              if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) {
+                  serviceType = p->value();
+                  int pos = serviceType.find(";");
+                  if (pos != -1)
+                      serviceType = serviceType.left(pos);
+              }
+              if (!embed && !name.isEmpty()) {
+                  uniqueParamNames.add(name.impl());
+                  paramNames.append(p->name());
+                  paramValues.append(p->value());
+              }
+          }
+          child = child->nextSibling();
+      }
+      
+      // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE attribute in the tag
+      // points to the Java plugin itself (an ActiveX component) while the actual applet CODEBASE is
+      // in a PARAM tag. See <http://java.sun.com/products/plugin/1.2/docs/tags.html>. This means
+      // we have to explicitly suppress the tag's CODEBASE attribute if there is none in a PARAM,
+      // else our Java plugin will misinterpret it. [4004531]
+      String codebase;
+      if (!embed && MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) {
+          codebase = "codebase";
+          uniqueParamNames.add(codebase.impl()); // pretend we found it in a PARAM already
+      }
+      
+      // Turn the attributes of either the EMBED tag or OBJECT tag into arrays, but don't override PARAM values.
+      NamedAttrMap* attributes = embedOrObject->attributes();
+      if (attributes) {
+          for (unsigned i = 0; i < attributes->length(); ++i) {
+              Attribute* it = attributes->attributeItem(i);
+              const AtomicString& name = it->name().localName();
+              if (embed || !uniqueParamNames.contains(name.impl())) {
+                  paramNames.append(name.string());
+                  paramValues.append(it->value().string());
+              }
+          }
+      }
+      
+      // If we still don't have a type, try to map from a specific CLASSID to a type.
+      if (serviceType.isEmpty() && !o->classId().isEmpty())
+          mapClassIdToServiceType(o->classId(), serviceType);
+      
+      if (!isURLAllowed(document(), url))
+          return;
+
+      // Find out if we support fallback content.
+      m_hasFallbackContent = false;
+      for (Node *child = o->firstChild(); child && !m_hasFallbackContent; child = child->nextSibling()) {
+          if ((!child->isTextNode() && !child->hasTagName(embedTag) && !child->hasTagName(paramTag)) || // Discount <embed> and <param>
+              (child->isTextNode() && !static_cast<Text*>(child)->containsOnlyWhitespace()))
+              m_hasFallbackContent = true;
+      }
+      
+      if (onlyCreateNonNetscapePlugins) {
+          KURL completedURL;
+          if (!url.isEmpty())
+              completedURL = frame->loader()->completeURL(url);
+        
+          if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin)
+              return;
+      }
+      
+      bool success = frame->loader()->requestObject(this, url, AtomicString(o->name()), serviceType, paramNames, paramValues);
+      if (!success && m_hasFallbackContent)
+          o->renderFallbackContent();
+  } else if (element()->hasTagName(embedTag)) {
+      HTMLEmbedElement *o = static_cast<HTMLEmbedElement*>(element());
+      o->setNeedWidgetUpdate(false);
+      url = o->url();
+      serviceType = o->serviceType();
+
+      if (url.isEmpty() && serviceType.isEmpty())
+          return;
+      if (!isURLAllowed(document(), url))
+          return;
+      
+      // add all attributes set on the embed object
+      NamedAttrMap* a = o->attributes();
+      if (a) {
+          for (unsigned i = 0; i < a->length(); ++i) {
+              Attribute* it = a->attributeItem(i);
+              paramNames.append(it->name().localName().string());
+              paramValues.append(it->value().string());
+          }
+      }
+      
+      if (onlyCreateNonNetscapePlugins) {
+          KURL completedURL;
+          if (!url.isEmpty())
+              completedURL = frame->loader()->completeURL(url);
+          
+          if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin)
+              return;
+          
+      }
+      
+      frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues);
+  }
+}
+
+void RenderPartObject::layout()
+{
+    ASSERT(needsLayout());
+
+    calcWidth();
+    calcHeight();
+    
+#ifdef FLATTEN_IFRAME
+    // Some IFrames have a width and/or height of 1 when they are meant to be
+    // hidden. If that is the case, don't try to expand.
+    if (m_widget && m_widget->isFrameView() &&
+            m_width > 1 && m_height > 1) {
+        FrameView* view = static_cast<FrameView*>(m_widget);
+        RenderView* root = NULL;
+        if (view->frame() && view->frame()->document() &&
+            view->frame()->document()->renderer() && view->frame()->document()->renderer()->isRenderView())
+            root = static_cast<RenderView*>(view->frame()->document()->renderer());
+        if (root) {
+            // Update the dimensions to get the correct minimum preferred width
+            updateWidgetPosition();
+
+            // Use the preferred width if it is larger.
+            m_width = max(m_width, root->minPrefWidth());
+            int extraWidth = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+            int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom();
+            // Resize the view to recalc the height.
+            int height = m_height - extraHeight;
+            int width = m_width - extraWidth;
+            if (width > view->width())
+                height = 0;
+            if (width != view->width() || height != view->height()) {
+                view->resize(width, height);
+                root->setNeedsLayout(true, false);
+            }
+            // Layout the view.
+            if (view->needsLayout())
+                view->layout();
+            int contentHeight = view->contentsHeight();
+            int contentWidth = view->contentsWidth();
+            // Do not shrink iframes with specified sizes
+            if (contentHeight > m_height || style()->height().isAuto())
+                m_height = contentHeight;
+            m_width = std::min(contentWidth, 800);
+        }
+    }
+#endif
+    adjustOverflowForBoxShadow();
+
+    RenderPart::layout();
+
+    if (!m_widget && m_view)
+        m_view->addWidgetToUpdate(this);
+    
+    setNeedsLayout(false);
+}
+
+void RenderPartObject::viewCleared()
+{
+    if (element() && m_widget && m_widget->isFrameView()) {
+        FrameView* view = static_cast<FrameView*>(m_widget);
+        int marginw = -1;
+        int marginh = -1;
+        if (element()->hasTagName(iframeTag)) {
+            HTMLIFrameElement* frame = static_cast<HTMLIFrameElement*>(element());
+            marginw = frame->getMarginWidth();
+            marginh = frame->getMarginHeight();
+        }
+        if (marginw != -1)
+            view->setMarginWidth(marginw);
+        if (marginh != -1)
+            view->setMarginHeight(marginh);
+    }
+}
+
+}
diff --git a/WebCore/rendering/RenderPartObject.h b/WebCore/rendering/RenderPartObject.h
new file mode 100644
index 0000000..98de5b9
--- /dev/null
+++ b/WebCore/rendering/RenderPartObject.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 2000 Simon Hausmann <[email protected]>
+ * Copyright (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderPartObject_h
+#define RenderPartObject_h
+
+#include "RenderPart.h"
+
+namespace WebCore {
+
+class RenderPartObject : public RenderPart {
+public:
+    RenderPartObject(HTMLFrameOwnerElement*);
+    virtual ~RenderPartObject();
+
+    virtual const char* renderName() const { return "RenderPartObject"; }
+
+    virtual void layout();
+    void updateWidget(bool onlyCreateNonNetscapePlugins);
+
+    virtual void viewCleared();
+};
+
+} // namespace WebCore
+
+#endif // RenderPartObject_h
diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp
new file mode 100644
index 0000000..e825f76
--- /dev/null
+++ b/WebCore/rendering/RenderPath.cpp
@@ -0,0 +1,449 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005, 2008 Rob Buis <[email protected]>
+                  2005, 2007 Eric Seidel <[email protected]>
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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
+    aint with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderPath.h"
+
+#include <math.h>
+
+#include "FloatPoint.h"
+#include "GraphicsContext.h"
+#include "PointerEventsHitRules.h"
+#include "RenderSVGContainer.h"
+#include "SVGPaintServer.h"
+#include "SVGRenderSupport.h"
+#include "SVGResourceFilter.h"
+#include "SVGResourceMarker.h"
+#include "SVGResourceMasker.h"
+#include "SVGStyledTransformableElement.h"
+#include "SVGTransformList.h"
+#include "SVGURIReference.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+// RenderPath
+RenderPath::RenderPath(RenderStyle* style, SVGStyledTransformableElement* node)
+    : RenderObject(node)
+{
+    ASSERT(style != 0);
+    ASSERT(static_cast<SVGElement*>(node)->isStyledTransformable());
+}
+
+RenderPath::~RenderPath()
+{
+}
+
+AffineTransform RenderPath::localTransform() const
+{
+    return m_localTransform;
+}
+
+FloatPoint RenderPath::mapAbsolutePointToLocal(const FloatPoint& point) const
+{
+    // FIXME: does it make sense to map incoming points with the inverse of the
+    // absolute transform? 
+    double localX;
+    double localY;
+    absoluteTransform().inverse().map(point.x(), point.y(), &localX, &localY);
+    return FloatPoint::narrowPrecision(localX, localY);
+}
+
+bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill) const
+{
+    if (m_path.isEmpty())
+        return false;
+
+    if (requiresFill && !SVGPaintServer::fillPaintServer(style(), this))
+        return false;
+
+    return m_path.contains(point, style()->svgStyle()->fillRule());
+}
+
+FloatRect RenderPath::relativeBBox(bool includeStroke) const
+{
+    if (m_path.isEmpty())
+        return FloatRect();
+
+    if (includeStroke) {
+        if (m_strokeBbox.isEmpty())
+            m_strokeBbox = strokeBBox();
+
+        return m_strokeBbox;
+    }
+
+    if (m_fillBBox.isEmpty())
+        m_fillBBox = m_path.boundingRect();
+
+    return m_fillBBox;
+}
+
+void RenderPath::setPath(const Path& newPath)
+{
+    m_path = newPath;
+    m_strokeBbox = FloatRect();
+    m_fillBBox = FloatRect();
+}
+
+const Path& RenderPath::path() const
+{
+    return m_path;
+}
+
+bool RenderPath::calculateLocalTransform()
+{
+    AffineTransform oldTransform = m_localTransform;
+    m_localTransform = static_cast<SVGStyledTransformableElement*>(element())->animatedLocalTransform();
+    return (m_localTransform != oldTransform);
+}
+
+void RenderPath::layout()
+{
+    IntRect oldBounds;
+    IntRect oldOutlineBox;
+    bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
+    if (checkForRepaint) {
+        oldBounds = m_absoluteBounds;
+        oldOutlineBox = absoluteOutlineBox();
+    }
+        
+    calculateLocalTransform();
+
+    setPath(static_cast<SVGStyledTransformableElement*>(element())->toPathData());
+
+    m_absoluteBounds = absoluteClippedOverflowRect();
+
+    setWidth(m_absoluteBounds.width());
+    setHeight(m_absoluteBounds.height());
+
+    if (checkForRepaint)
+        repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+
+    setNeedsLayout(false);
+}
+
+IntRect RenderPath::absoluteClippedOverflowRect()
+{
+    FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true));
+
+    // Markers can expand the bounding box
+    repaintRect.unite(m_markerBounds);
+
+#if ENABLE(SVG_FILTERS)
+    // Filters can expand the bounding box
+    SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter());
+    if (filter)
+        repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect));
+#endif
+
+    if (!repaintRect.isEmpty())
+        repaintRect.inflate(1); // inflate 1 pixel for antialiasing
+
+    return enclosingIntRect(repaintRect);
+}
+
+bool RenderPath::requiresLayer()
+{
+    return false;
+}
+
+int RenderPath::lineHeight(bool b, bool isRootLineBox) const
+{
+    return relativeBBox(true).height();
+}
+
+int RenderPath::baselinePosition(bool b, bool isRootLineBox) const
+{
+    return relativeBBox(true).height();
+}
+
+static inline void fillAndStrokePath(const Path& path, GraphicsContext* context, RenderStyle* style, RenderPath* object)
+{
+    context->beginPath();
+
+    SVGPaintServer* fillPaintServer = SVGPaintServer::fillPaintServer(style, object);
+    if (fillPaintServer) {
+        context->addPath(path);
+        fillPaintServer->draw(context, object, ApplyToFillTargetType);
+    }
+    
+    SVGPaintServer* strokePaintServer = SVGPaintServer::strokePaintServer(style, object);
+    if (strokePaintServer) {
+        context->addPath(path); // path is cleared when filled.
+        strokePaintServer->draw(context, object, ApplyToStrokeTargetType);
+    }
+}
+
+void RenderPath::paint(PaintInfo& paintInfo, int, int)
+{
+    if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || m_path.isEmpty())
+        return;
+            
+    paintInfo.context->save();
+    paintInfo.context->concatCTM(localTransform());
+
+    SVGResourceFilter* filter = 0;
+
+    FloatRect boundingBox = relativeBBox(true);
+    if (paintInfo.phase == PaintPhaseForeground) {
+        PaintInfo savedInfo(paintInfo);
+
+        prepareToRenderSVGContent(this, paintInfo, boundingBox, filter);
+        if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES)
+            paintInfo.context->setUseAntialiasing(false);
+        fillAndStrokePath(m_path, paintInfo.context, style(), this);
+
+        if (static_cast<SVGStyledElement*>(element())->supportsMarkers())
+            m_markerBounds = drawMarkersIfNeeded(paintInfo.context, paintInfo.rect, m_path);
+
+        finishRenderSVGContent(this, paintInfo, boundingBox, filter, savedInfo.context);
+    }
+
+    if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth())
+        paintOutline(paintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()),
+            static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height()), style());
+    
+    paintInfo.context->restore();
+}
+
+void RenderPath::addFocusRingRects(GraphicsContext* graphicsContext, int, int) 
+{
+    graphicsContext->addFocusRingRect(enclosingIntRect(relativeBBox(true)));
+}
+
+void RenderPath::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+{
+    rects.append(absoluteClippedOverflowRect());
+}
+
+bool RenderPath::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int, int, HitTestAction hitTestAction)
+{
+    // We only draw in the forground phase, so we only hit-test then.
+    if (hitTestAction != HitTestForeground)
+        return false;
+    
+    IntPoint absolutePoint(_x, _y);
+
+    PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, style()->svgStyle()->pointerEvents());
+
+    bool isVisible = (style()->visibility() == VISIBLE);
+    if (isVisible || !hitRules.requireVisible) {
+        FloatPoint hitPoint = mapAbsolutePointToLocal(absolutePoint);
+        if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke) && strokeContains(hitPoint, hitRules.requireStroke))
+            || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill) && fillContains(hitPoint, hitRules.requireFill))) {
+            updateHitTestResult(result, absolutePoint);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+enum MarkerType {
+    Start,
+    Mid,
+    End
+};
+
+struct MarkerData {
+    FloatPoint origin;
+    FloatPoint subpathStart;
+    double strokeWidth;
+    FloatPoint inslopePoints[2];
+    FloatPoint outslopePoints[2];
+    MarkerType type;
+    SVGResourceMarker* marker;
+};
+
+struct DrawMarkersData {
+    DrawMarkersData(GraphicsContext*, SVGResourceMarker* startMarker, SVGResourceMarker* midMarker, double strokeWidth);
+    GraphicsContext* context;
+    int elementIndex;
+    MarkerData previousMarkerData;
+    SVGResourceMarker* midMarker;
+};
+
+DrawMarkersData::DrawMarkersData(GraphicsContext* c, SVGResourceMarker *start, SVGResourceMarker *mid, double strokeWidth)
+    : context(c)
+    , elementIndex(0)
+    , midMarker(mid)
+{
+    previousMarkerData.origin = FloatPoint();
+    previousMarkerData.subpathStart = FloatPoint();
+    previousMarkerData.strokeWidth = strokeWidth;
+    previousMarkerData.marker = start;
+    previousMarkerData.type = Start;
+}
+
+static void drawMarkerWithData(GraphicsContext* context, MarkerData &data)
+{
+    if (!data.marker)
+        return;
+
+    FloatPoint inslopeChange = data.inslopePoints[1] - FloatSize(data.inslopePoints[0].x(), data.inslopePoints[0].y());
+    FloatPoint outslopeChange = data.outslopePoints[1] - FloatSize(data.outslopePoints[0].x(), data.outslopePoints[0].y());
+
+    double inslope = rad2deg(atan2(inslopeChange.y(), inslopeChange.x()));
+    double outslope = rad2deg(atan2(outslopeChange.y(), outslopeChange.x()));
+
+    double angle = 0.0;
+    switch (data.type) {
+        case Start:
+            angle = outslope;
+            break;
+        case Mid:
+            angle = (inslope + outslope) / 2;
+            break;
+        case End:
+            angle = inslope;
+    }
+
+    data.marker->draw(context, FloatRect(), data.origin.x(), data.origin.y(), data.strokeWidth, angle);
+}
+
+static inline void updateMarkerDataForElement(MarkerData& previousMarkerData, const PathElement* element)
+{
+    FloatPoint* points = element->points;
+    
+    switch (element->type) {
+    case PathElementAddQuadCurveToPoint:
+        // TODO
+        previousMarkerData.origin = points[1];
+        break;
+    case PathElementAddCurveToPoint:
+        previousMarkerData.inslopePoints[0] = points[1];
+        previousMarkerData.inslopePoints[1] = points[2];
+        previousMarkerData.origin = points[2];
+        break;
+    case PathElementMoveToPoint:
+        previousMarkerData.subpathStart = points[0];
+    case PathElementAddLineToPoint:
+        previousMarkerData.inslopePoints[0] = previousMarkerData.origin;
+        previousMarkerData.inslopePoints[1] = points[0];
+        previousMarkerData.origin = points[0];
+        break;
+    case PathElementCloseSubpath:
+        previousMarkerData.inslopePoints[0] = previousMarkerData.origin;
+        previousMarkerData.inslopePoints[1] = points[0];
+        previousMarkerData.origin = previousMarkerData.subpathStart;
+        previousMarkerData.subpathStart = FloatPoint();
+    }
+}
+
+static void drawStartAndMidMarkers(void* info, const PathElement* element)
+{
+    DrawMarkersData& data = *reinterpret_cast<DrawMarkersData*>(info);
+
+    int elementIndex = data.elementIndex;
+    MarkerData& previousMarkerData = data.previousMarkerData;
+
+    FloatPoint* points = element->points;
+
+    // First update the outslope for the previous element
+    previousMarkerData.outslopePoints[0] = previousMarkerData.origin;
+    previousMarkerData.outslopePoints[1] = points[0];
+
+    // Draw the marker for the previous element
+    if (elementIndex != 0)
+        drawMarkerWithData(data.context, previousMarkerData);
+
+    // Update our marker data for this element
+    updateMarkerDataForElement(previousMarkerData, element);
+
+    if (elementIndex == 1) {
+        // After drawing the start marker, switch to drawing mid markers
+        previousMarkerData.marker = data.midMarker;
+        previousMarkerData.type = Mid;
+    }
+
+    data.elementIndex++;
+}
+
+FloatRect RenderPath::drawMarkersIfNeeded(GraphicsContext* context, const FloatRect& rect, const Path& path) const
+{
+    Document* doc = document();
+
+    SVGElement* svgElement = static_cast<SVGElement*>(element());
+    ASSERT(svgElement && svgElement->document() && svgElement->isStyled());
+
+    SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
+    const SVGRenderStyle* svgStyle = style()->svgStyle();
+
+    AtomicString startMarkerId(svgStyle->startMarker());
+    AtomicString midMarkerId(svgStyle->midMarker());
+    AtomicString endMarkerId(svgStyle->endMarker());
+
+    SVGResourceMarker* startMarker = getMarkerById(doc, startMarkerId);
+    SVGResourceMarker* midMarker = getMarkerById(doc, midMarkerId);
+    SVGResourceMarker* endMarker = getMarkerById(doc, endMarkerId);
+
+    if (!startMarker && !startMarkerId.isEmpty())
+        svgElement->document()->accessSVGExtensions()->addPendingResource(startMarkerId, styledElement);
+    else if (startMarker)
+        startMarker->addClient(styledElement);
+
+    if (!midMarker && !midMarkerId.isEmpty())
+        svgElement->document()->accessSVGExtensions()->addPendingResource(midMarkerId, styledElement);
+    else if (midMarker)
+        midMarker->addClient(styledElement);
+
+    if (!endMarker && !endMarkerId.isEmpty())
+        svgElement->document()->accessSVGExtensions()->addPendingResource(endMarkerId, styledElement);
+    else if (endMarker)
+        endMarker->addClient(styledElement);
+
+    if (!startMarker && !midMarker && !endMarker)
+        return FloatRect();
+
+    double strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, svgStyle->strokeWidth(), 1.0f);
+    DrawMarkersData data(context, startMarker, midMarker, strokeWidth);
+
+    path.apply(&data, drawStartAndMidMarkers);
+
+    data.previousMarkerData.marker = endMarker;
+    data.previousMarkerData.type = End;
+    drawMarkerWithData(context, data.previousMarkerData);
+
+    // We know the marker boundaries, only after they're drawn!
+    // Otherwhise we'd need to do all the marker calculation twice
+    // once here (through paint()) and once in absoluteClippedOverflowRect().
+    FloatRect bounds;
+
+    if (startMarker)
+        bounds.unite(startMarker->cachedBounds());
+
+    if (midMarker)
+        bounds.unite(midMarker->cachedBounds());
+
+    if (endMarker)
+        bounds.unite(endMarker->cachedBounds());
+
+    return bounds;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderPath.h b/WebCore/rendering/RenderPath.h
new file mode 100644
index 0000000..ab966e4
--- /dev/null
+++ b/WebCore/rendering/RenderPath.h
@@ -0,0 +1,95 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005 Rob Buis <[email protected]>
+                  2005 Eric Seidel <[email protected]>
+                  2006 Apple Computer, Inc
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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
+    aint with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RenderPath_h
+#define RenderPath_h
+
+#if ENABLE(SVG)
+
+#include "AffineTransform.h"
+#include "FloatRect.h"
+
+#include "RenderObject.h"
+
+namespace WebCore {
+
+class FloatPoint;
+class Path;
+class RenderSVGContainer;
+class SVGStyledTransformableElement;
+
+class RenderPath : public RenderObject
+{
+public:
+    RenderPath(RenderStyle*, SVGStyledTransformableElement*);
+    virtual ~RenderPath();
+
+    // Hit-detection seperated for the fill and the stroke
+    virtual bool fillContains(const FloatPoint&, bool requiresFill = true) const;
+    virtual bool strokeContains(const FloatPoint&, bool requiresStroke = true) const;
+
+    // Returns an unscaled bounding box (not even including localTransform()) for this vector path
+    virtual FloatRect relativeBBox(bool includeStroke = true) const;
+
+    const Path& path() const;
+    void setPath(const Path& newPath);
+
+    virtual bool isRenderPath() const { return true; }
+    virtual const char* renderName() const { return "RenderPath"; }
+    
+    bool calculateLocalTransform();
+    virtual AffineTransform localTransform() const;
+    
+    virtual void layout();
+    virtual IntRect absoluteClippedOverflowRect();
+    virtual bool requiresLayer();
+    virtual int lineHeight(bool b, bool isRootLineBox = false) const;
+    virtual int baselinePosition(bool b, bool isRootLineBox = false) const;
+    virtual void paint(PaintInfo&, int parentX, int parentY);
+
+    virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
+    virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+    FloatRect drawMarkersIfNeeded(GraphicsContext*, const FloatRect&, const Path&) const;
+    virtual FloatRect strokeBBox() const;
+    
+private:
+    FloatPoint mapAbsolutePointToLocal(const FloatPoint&) const;
+
+    mutable Path m_path;
+    mutable FloatRect m_fillBBox;
+    mutable FloatRect m_strokeBbox;
+    FloatRect m_markerBounds;
+    AffineTransform m_localTransform;
+    IntRect m_absoluteBounds;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderReplaced.cpp b/WebCore/rendering/RenderReplaced.cpp
new file mode 100644
index 0000000..52267d5
--- /dev/null
+++ b/WebCore/rendering/RenderReplaced.cpp
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * Copyright (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderReplaced.h"
+
+#include "GraphicsContext.h"
+#include "RenderBlock.h"
+#include "RenderLayer.h"
+
+using namespace std;
+
+namespace WebCore {
+
+typedef WTF::HashMap<const RenderReplaced*, IntRect> OverflowRectMap;
+static OverflowRectMap* gOverflowRectMap = 0;
+
+const int cDefaultWidth = 300;
+const int cDefaultHeight = 150;
+
+RenderReplaced::RenderReplaced(Node* node)
+    : RenderBox(node)
+    , m_intrinsicSize(cDefaultWidth, cDefaultHeight)
+    , m_selectionState(SelectionNone)
+    , m_hasOverflow(false)
+{
+    setReplaced(true);
+}
+
+RenderReplaced::RenderReplaced(Node* node, const IntSize& intrinsicSize)
+    : RenderBox(node)
+    , m_intrinsicSize(intrinsicSize)
+    , m_selectionState(SelectionNone)
+    , m_hasOverflow(false)
+{
+    setReplaced(true);
+}
+
+RenderReplaced::~RenderReplaced()
+{
+    if (m_hasOverflow)
+        gOverflowRectMap->remove(this);
+}
+
+void RenderReplaced::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBox::styleDidChange(diff, oldStyle);
+
+    bool hadStyle = (oldStyle != 0);
+    float oldZoom = hadStyle ? oldStyle->effectiveZoom() : RenderStyle::initialZoom();
+    if (hadStyle && style() && style()->effectiveZoom() != oldZoom)
+        intrinsicSizeChanged();
+}
+
+void RenderReplaced::layout()
+{
+    ASSERT(needsLayout());
+    
+    IntRect oldBounds;
+    IntRect oldOutlineBox;
+    bool checkForRepaint = checkForRepaintDuringLayout();
+    if (checkForRepaint) {
+        oldBounds = absoluteClippedOverflowRect();
+        oldOutlineBox = absoluteOutlineBox();
+    }
+    
+    m_height = minimumReplacedHeight();
+    
+    calcWidth();
+    calcHeight();
+    adjustOverflowForBoxShadow();
+    
+    if (checkForRepaint)
+        repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+    
+    setNeedsLayout(false);
+}
+ 
+void RenderReplaced::intrinsicSizeChanged()
+{
+    int scaledWidth = static_cast<int>(cDefaultWidth * style()->effectiveZoom());
+    int scaledHeight = static_cast<int>(cDefaultHeight * style()->effectiveZoom());
+    m_intrinsicSize = IntSize(scaledWidth, scaledHeight);
+    setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+void RenderReplaced::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (!shouldPaint(paintInfo, tx, ty))
+        return;
+    
+    tx += m_x;
+    ty += m_y;
+    
+    if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) 
+        paintBoxDecorations(paintInfo, tx, ty);
+    
+    if (paintInfo.phase == PaintPhaseMask) {
+        paintMask(paintInfo, tx, ty);
+        return;
+    }
+
+    if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth())
+        paintOutline(paintInfo.context, tx, ty, width(), height(), style());
+    
+    if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection)
+        return;
+    
+    if (!shouldPaintWithinRoot(paintInfo))
+        return;
+    
+    bool drawSelectionTint = selectionState() != SelectionNone && !document()->printing();
+    if (paintInfo.phase == PaintPhaseSelection) {
+        if (selectionState() == SelectionNone)
+            return;
+        drawSelectionTint = false;
+    }
+
+    paintReplaced(paintInfo, tx, ty);
+    
+    if (drawSelectionTint)
+        paintInfo.context->fillRect(selectionRect(), selectionBackgroundColor());
+}
+
+bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, int& tx, int& ty)
+{
+    if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseOutline && paintInfo.phase != PaintPhaseSelfOutline 
+            && paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseMask)
+        return false;
+
+    if (!shouldPaintWithinRoot(paintInfo))
+        return false;
+        
+    // if we're invisible or haven't received a layout yet, then just bail.
+    if (style()->visibility() != VISIBLE)
+        return false;
+
+    int currentTX = tx + m_x;
+    int currentTY = ty + m_y;
+
+    // Early exit if the element touches the edges.
+    int top = currentTY + overflowTop();
+    int bottom = currentTY + overflowHeight();
+    if (isSelected() && m_inlineBoxWrapper) {
+        int selTop = ty + m_inlineBoxWrapper->root()->selectionTop();
+        int selBottom = ty + selTop + m_inlineBoxWrapper->root()->selectionHeight();
+        top = min(selTop, top);
+        bottom = max(selBottom, bottom);
+    }
+    
+    int os = 2 * maximalOutlineSize(paintInfo.phase);
+    if (currentTX + overflowLeft() >= paintInfo.rect.right() + os || currentTX + overflowWidth() <= paintInfo.rect.x() - os)
+        return false;
+    if (top >= paintInfo.rect.bottom() + os || bottom <= paintInfo.rect.y() - os)
+        return false;
+
+    return true;
+}
+
+void RenderReplaced::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+
+    int paddingAndBorders = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+    int width = calcReplacedWidth(false) + paddingAndBorders;
+
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength)
+        width = min(width, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? paddingAndBorders : 0));
+
+    if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent())) {
+        m_minPrefWidth = 0;
+        m_maxPrefWidth = width;
+    } else
+        m_minPrefWidth = m_maxPrefWidth = width;
+
+    setPrefWidthsDirty(false);
+}
+
+int RenderReplaced::lineHeight(bool, bool) const
+{
+    return height() + marginTop() + marginBottom();
+}
+
+int RenderReplaced::baselinePosition(bool, bool) const
+{
+    return height() + marginTop() + marginBottom();
+}
+
+unsigned RenderReplaced::caretMaxRenderedOffset() const
+{
+    return 1; 
+}
+
+VisiblePosition RenderReplaced::positionForCoordinates(int x, int y)
+{
+    InlineBox* box = inlineBoxWrapper();
+    if (!box)
+        return VisiblePosition(element(), 0, DOWNSTREAM);
+
+    // FIXME: This code is buggy if the replaced element is relative positioned.
+
+    RootInlineBox* root = box->root();
+
+    int top = root->topOverflow();
+    int bottom = root->nextRootBox() ? root->nextRootBox()->topOverflow() : root->bottomOverflow();
+
+    if (y + yPos() < top)
+        return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM); // coordinates are above
+    
+    if (y + yPos() >= bottom)
+        return VisiblePosition(element(), caretMaxOffset(), DOWNSTREAM); // coordinates are below
+    
+    if (element()) {
+        if (x <= width() / 2)
+            return VisiblePosition(element(), 0, DOWNSTREAM);
+        return VisiblePosition(element(), 1, DOWNSTREAM);
+    }
+
+    return RenderBox::positionForCoordinates(x, y);
+}
+
+IntRect RenderReplaced::selectionRect(bool clipToVisibleContent)
+{
+    ASSERT(!needsLayout());
+
+    if (!isSelected())
+        return IntRect();
+    if (!m_inlineBoxWrapper)
+        // We're a block-level replaced element.  Just return our own dimensions.
+        return absoluteBoundingBoxRect();
+
+    RenderBlock* cb =  containingBlock();
+    if (!cb)
+        return IntRect();
+    
+    RootInlineBox* root = m_inlineBoxWrapper->root();
+    IntRect rect(0, root->selectionTop() - yPos(), width(), root->selectionHeight());
+    
+    if (clipToVisibleContent)
+        computeAbsoluteRepaintRect(rect);
+    else {
+        int absx, absy;
+        absolutePositionForContent(absx, absy);
+        rect.move(absx, absy);
+    }
+    
+    return rect;
+}
+
+void RenderReplaced::setSelectionState(SelectionState s)
+{
+    m_selectionState = s;
+    if (m_inlineBoxWrapper) {
+        RootInlineBox* line = m_inlineBoxWrapper->root();
+        if (line)
+            line->setHasSelectedChildren(isSelected());
+    }
+    
+    containingBlock()->setSelectionState(s);
+}
+
+bool RenderReplaced::isSelected() const
+{
+    SelectionState s = selectionState();
+    if (s == SelectionNone)
+        return false;
+    if (s == SelectionInside)
+        return true;
+
+    int selectionStart, selectionEnd;
+    selectionStartEnd(selectionStart, selectionEnd);
+    if (s == SelectionStart)
+        return selectionStart == 0;
+        
+    int end = element()->hasChildNodes() ? element()->childNodeCount() : 1;
+    if (s == SelectionEnd)
+        return selectionEnd == end;
+    if (s == SelectionBoth)
+        return selectionStart == 0 && selectionEnd == end;
+        
+    ASSERT(0);
+    return false;
+}
+
+IntSize RenderReplaced::intrinsicSize() const
+{
+    return m_intrinsicSize;
+}
+
+void RenderReplaced::setIntrinsicSize(const IntSize& size)
+{
+    m_intrinsicSize = size;
+}
+
+void RenderReplaced::adjustOverflowForBoxShadow()
+{
+    IntRect overflow;
+    for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+        IntRect shadow = borderBox();
+        shadow.move(boxShadow->x, boxShadow->y);
+        shadow.inflate(boxShadow->blur);
+        overflow.unite(shadow);
+    }
+
+    if (!overflow.isEmpty()) {
+        if (!gOverflowRectMap)
+            gOverflowRectMap = new OverflowRectMap();
+        overflow.unite(borderBox());
+        gOverflowRectMap->set(this, overflow);
+        m_hasOverflow = true;
+    } else if (m_hasOverflow) {
+        gOverflowRectMap->remove(this);
+        m_hasOverflow = false;
+    }
+}
+
+int RenderReplaced::overflowHeight(bool includeInterior) const
+{
+    if (m_hasOverflow) {
+        IntRect *r = &gOverflowRectMap->find(this)->second;
+        return r->height() + r->y();
+    }
+
+    return height();
+}
+
+int RenderReplaced::overflowWidth(bool includeInterior) const
+{
+    if (m_hasOverflow) {
+        IntRect *r = &gOverflowRectMap->find(this)->second;
+        return r->width() + r->x();
+    }
+
+    return width();
+}
+
+int RenderReplaced::overflowLeft(bool includeInterior) const
+{
+    if (m_hasOverflow)
+        return gOverflowRectMap->get(this).x();
+
+    return 0;
+}
+
+int RenderReplaced::overflowTop(bool includeInterior) const
+{
+    if (m_hasOverflow)
+        return gOverflowRectMap->get(this).y();
+
+    return 0;
+}
+
+IntRect RenderReplaced::overflowRect(bool includeInterior) const
+{
+    if (m_hasOverflow)
+        return gOverflowRectMap->find(this)->second;
+
+    return borderBox();
+}
+
+}
diff --git a/WebCore/rendering/RenderReplaced.h b/WebCore/rendering/RenderReplaced.h
new file mode 100644
index 0000000..f1ee32b
--- /dev/null
+++ b/WebCore/rendering/RenderReplaced.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderReplaced_h
+#define RenderReplaced_h
+
+#include "RenderBox.h"
+
+namespace WebCore {
+
+class RenderReplaced : public RenderBox {
+public:
+    RenderReplaced(Node*);
+    RenderReplaced(Node*, const IntSize& intrinsicSize);
+    virtual ~RenderReplaced();
+
+    virtual const char* renderName() const { return "RenderReplaced"; }
+
+    virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
+    virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
+
+    virtual void calcPrefWidths();
+    
+    virtual void layout();
+    virtual int minimumReplacedHeight() const { return 0; }
+
+    virtual void paint(PaintInfo&, int tx, int ty);
+    virtual void paintReplaced(PaintInfo&, int tx, int ty) { }
+
+    virtual IntSize intrinsicSize() const;
+
+    virtual int overflowHeight(bool includeInterior = true) const;
+    virtual int overflowWidth(bool includeInterior = true) const;
+    virtual int overflowLeft(bool includeInterior = true) const;
+    virtual int overflowTop(bool includeInterior = true) const;
+    virtual IntRect overflowRect(bool includeInterior = true) const;
+
+    virtual unsigned caretMaxRenderedOffset() const;
+    virtual VisiblePosition positionForCoordinates(int x, int y);
+    
+    virtual bool canBeSelectionLeaf() const { return true; }
+    virtual SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState); }
+    virtual void setSelectionState(SelectionState);
+    virtual IntRect selectionRect(bool clipToVisibleContent = true);
+
+    bool isSelected() const;
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+    void setIntrinsicSize(const IntSize&);
+    virtual void intrinsicSizeChanged();
+
+    bool shouldPaint(PaintInfo&, int& tx, int& ty);
+    void adjustOverflowForBoxShadow();
+
+private:
+    IntSize m_intrinsicSize;
+    
+    unsigned m_selectionState : 3; // SelectionState
+    bool m_hasOverflow : 1;
+};
+
+}
+
+#endif
diff --git a/WebCore/rendering/RenderReplica.cpp b/WebCore/rendering/RenderReplica.cpp
new file mode 100644
index 0000000..be28171
--- /dev/null
+++ b/WebCore/rendering/RenderReplica.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderReplica.h"
+
+#include "RenderLayer.h"
+
+namespace WebCore {
+
+RenderReplica::RenderReplica(Node* n)
+: RenderBox(n)
+{}
+
+RenderReplica::~RenderReplica()
+{}
+    
+void RenderReplica::layout()
+{
+    IntRect box = parent()->borderBox();
+    m_x = box.x();
+    m_y = box.y();
+    m_width = box.width();
+    m_height = box.height();
+    setNeedsLayout(false);
+}
+
+void RenderReplica::calcPrefWidths()
+{
+    m_minPrefWidth = parent()->width();
+    m_maxPrefWidth = m_minPrefWidth;
+    setPrefWidthsDirty(false);
+}
+
+void RenderReplica::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseMask)
+        return;
+ 
+    tx += m_x;
+    ty += m_y;
+
+    if (paintInfo.phase == PaintPhaseForeground)
+        // Turn around and paint the parent layer.
+        layer()->parent()->paintLayer(layer()->transform() ? layer()->parent() : layer()->enclosingTransformedAncestor(), paintInfo.context, paintInfo.rect, true, PaintRestrictionNone, 0, true);
+    else if (paintInfo.phase == PaintPhaseMask)
+        paintMask(paintInfo, tx, ty);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderReplica.h b/WebCore/rendering/RenderReplica.h
new file mode 100644
index 0000000..d3a9026
--- /dev/null
+++ b/WebCore/rendering/RenderReplica.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RenderReplica_h
+#define RenderReplica_h
+
+#include "RenderBox.h"
+
+namespace WebCore {
+
+class RenderReplica : public RenderBox {
+public:
+    RenderReplica(Node*);
+    virtual ~RenderReplica();
+
+    virtual const char* renderName() const { return "RenderReplica"; }
+    
+    virtual bool requiresLayer() { return true; }
+
+    virtual void layout();
+    virtual void calcPrefWidths();
+    
+    virtual void paint(PaintInfo&, int tx, int ty);
+};
+
+} // namespace WebCore
+
+#endif // RenderReplica_h
diff --git a/WebCore/rendering/RenderSVGBlock.cpp b/WebCore/rendering/RenderSVGBlock.cpp
new file mode 100644
index 0000000..f065c44
--- /dev/null
+++ b/WebCore/rendering/RenderSVGBlock.cpp
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *           (C) 2007 Nikolas Zimmermann <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGBlock.h"
+
+#include "SVGElement.h"
+
+namespace WebCore {
+
+RenderSVGBlock::RenderSVGBlock(SVGElement* node) 
+    : RenderBlock(node)
+{
+}
+
+void RenderSVGBlock::setStyle(PassRefPtr<RenderStyle> style) 
+{
+    RefPtr<RenderStyle> useStyle = style;
+
+    // SVG text layout code expects us to be a block-level style element.   
+    if (useStyle->display() == NONE)
+        setChildrenInline(false);
+    else if (useStyle->isDisplayInlineType()) {
+        RefPtr<RenderStyle> newStyle = RenderStyle::create();
+        newStyle->inheritFrom(useStyle.get());
+        newStyle->setDisplay(BLOCK);
+        useStyle = newStyle.release();
+    }
+
+    RenderBlock::setStyle(useStyle.release());
+    setReplaced(false);
+
+    //FIXME: Once overflow rules are supported by SVG we should
+    //probably map the CSS overflow rules rather than just ignoring
+    //them
+    setHasOverflowClip(false);
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGBlock.h b/WebCore/rendering/RenderSVGBlock.h
new file mode 100644
index 0000000..d545fd0
--- /dev/null
+++ b/WebCore/rendering/RenderSVGBlock.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderSVGBlock_h
+#define RenderSVGBlock_h
+#if ENABLE(SVG)
+
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+class SVGElement;
+
+class RenderSVGBlock : public RenderBlock {
+public:
+    RenderSVGBlock(SVGElement*);
+    virtual void setStyle(PassRefPtr<RenderStyle>);
+};
+
+}
+#endif // ENABLE(SVG)
+#endif // !RenderSVGBlock_h
diff --git a/WebCore/rendering/RenderSVGContainer.cpp b/WebCore/rendering/RenderSVGContainer.cpp
new file mode 100644
index 0000000..c9c3cac
--- /dev/null
+++ b/WebCore/rendering/RenderSVGContainer.cpp
@@ -0,0 +1,433 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005, 2007, 2008 Rob Buis <[email protected]>
+                  2007 Eric Seidel <[email protected]>
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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
+    aint with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGContainer.h"
+
+#include "AXObjectCache.h"
+#include "GraphicsContext.h"
+#include "RenderView.h"
+#include "SVGRenderSupport.h"
+#include "SVGResourceFilter.h"
+#include "SVGStyledElement.h"
+#include "SVGURIReference.h"
+
+namespace WebCore {
+
+RenderSVGContainer::RenderSVGContainer(SVGStyledElement* node)
+    : RenderObject(node)
+    , m_firstChild(0)
+    , m_lastChild(0)
+    , m_width(0)
+    , m_height(0)
+    , m_drawsContents(true)
+{
+    setReplaced(true);
+}
+
+RenderSVGContainer::~RenderSVGContainer()
+{
+}
+
+bool RenderSVGContainer::canHaveChildren() const
+{
+    return true;
+}
+
+void RenderSVGContainer::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    insertChildNode(newChild, beforeChild);
+}
+
+void RenderSVGContainer::removeChild(RenderObject* oldChild)
+{
+    // We do this here instead of in removeChildNode, since the only extremely low-level uses of remove/appendChildNode
+    // cannot affect the positioned object list, and the floating object list is irrelevant (since the list gets cleared on
+    // layout anyway).
+    oldChild->removeFromObjectLists();
+
+    removeChildNode(oldChild);
+}
+
+void RenderSVGContainer::destroy()
+{
+    destroyLeftoverChildren();
+    RenderObject::destroy();
+}
+
+void RenderSVGContainer::destroyLeftoverChildren()
+{
+    while (m_firstChild) {
+        // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
+        if (m_firstChild->element())
+            m_firstChild->element()->setRenderer(0);
+
+        m_firstChild->destroy();
+    }
+}
+
+RenderObject* RenderSVGContainer::removeChildNode(RenderObject* oldChild, bool fullRemove)
+{
+    ASSERT(oldChild->parent() == this);
+
+    // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
+    // that a positioned child got yanked).  We also repaint, so that the area exposed when the child
+    // disappears gets repainted properly.
+    if (!documentBeingDestroyed() && fullRemove) {
+        oldChild->setNeedsLayoutAndPrefWidthsRecalc();
+        oldChild->repaint();
+    }
+
+    // If we have a line box wrapper, delete it.
+    oldChild->deleteLineBoxWrapper();
+
+    if (!documentBeingDestroyed() && fullRemove) {
+        // If oldChild is the start or end of the selection, then clear the selection to
+        // avoid problems of invalid pointers.
+        // FIXME: The SelectionController should be responsible for this when it
+        // is notified of DOM mutations.
+        if (oldChild->isSelectionBorder())
+            view()->clearSelection();
+    }
+
+    // remove the child
+    if (oldChild->previousSibling())
+        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
+    if (oldChild->nextSibling())
+        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
+
+    if (m_firstChild == oldChild)
+        m_firstChild = oldChild->nextSibling();
+    if (m_lastChild == oldChild)
+        m_lastChild = oldChild->previousSibling();
+
+    oldChild->setPreviousSibling(0);
+    oldChild->setNextSibling(0);
+    oldChild->setParent(0);
+
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->childrenChanged(this);
+
+    return oldChild;
+}
+
+void RenderSVGContainer::appendChildNode(RenderObject* newChild, bool)
+{
+    ASSERT(!newChild->parent());
+    ASSERT(newChild->element()->isSVGElement());
+
+    newChild->setParent(this);
+    RenderObject* lChild = m_lastChild;
+
+    if (lChild) {
+        newChild->setPreviousSibling(lChild);
+        lChild->setNextSibling(newChild);
+    } else
+        m_firstChild = newChild;
+
+    m_lastChild = newChild;
+
+    newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
+    if (!normalChildNeedsLayout())
+        setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->childrenChanged(this);
+}
+
+void RenderSVGContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild, bool)
+{
+    if (!beforeChild) {
+        appendChildNode(child);
+        return;
+    }
+
+    ASSERT(!child->parent());
+    ASSERT(beforeChild->parent() == this);
+    ASSERT(child->element()->isSVGElement());
+
+    if (beforeChild == m_firstChild)
+        m_firstChild = child;
+
+    RenderObject* prev = beforeChild->previousSibling();
+    child->setNextSibling(beforeChild);
+    beforeChild->setPreviousSibling(child);
+    if (prev)
+        prev->setNextSibling(child);
+    child->setPreviousSibling(prev);
+
+    child->setParent(this);
+
+    child->setNeedsLayoutAndPrefWidthsRecalc();
+    if (!normalChildNeedsLayout())
+        setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->childrenChanged(this);
+}
+
+bool RenderSVGContainer::drawsContents() const
+{
+    return m_drawsContents;
+}
+
+void RenderSVGContainer::setDrawsContents(bool drawsContents)
+{
+    m_drawsContents = drawsContents;
+}
+
+AffineTransform RenderSVGContainer::localTransform() const
+{
+    return m_localTransform;
+}
+
+bool RenderSVGContainer::requiresLayer()
+{
+    // Only allow an <svg> element to generate a layer when it's positioned in a non-SVG context
+    return false;
+}
+
+int RenderSVGContainer::lineHeight(bool b, bool isRootLineBox) const
+{
+    return height() + marginTop() + marginBottom();
+}
+
+int RenderSVGContainer::baselinePosition(bool b, bool isRootLineBox) const
+{
+    return height() + marginTop() + marginBottom();
+}
+
+bool RenderSVGContainer::calculateLocalTransform()
+{
+    // subclasses can override this to add transform support
+    return false;
+}
+
+void RenderSVGContainer::layout()
+{
+    ASSERT(needsLayout());
+
+    // Arbitrary affine transforms are incompatible with LayoutState.
+    view()->disableLayoutState();
+
+    IntRect oldBounds;
+    IntRect oldOutlineBox;
+    bool checkForRepaint = checkForRepaintDuringLayout() && selfWillPaint();
+    if (checkForRepaint) {
+        oldBounds = m_absoluteBounds;
+        oldOutlineBox = absoluteOutlineBox();
+    }
+    
+    calculateLocalTransform();
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        // Only force our kids to layout if we're being asked to relayout as a result of a parent changing
+        // FIXME: We should be able to skip relayout of non-relative kids when only bounds size has changed
+        // that's a possible future optimization using LayoutState
+        // http://bugs.webkit.org/show_bug.cgi?id=15391
+        if (selfNeedsLayout())
+            child->setNeedsLayout(true);
+
+        child->layoutIfNeeded();
+        ASSERT(!child->needsLayout());
+    }
+
+    calcBounds();
+
+    if (checkForRepaint)
+        repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+
+    view()->enableLayoutState();
+    setNeedsLayout(false);
+}
+
+int RenderSVGContainer::calcReplacedWidth() const
+{
+    switch (style()->width().type()) {
+    case Fixed:
+        return max(0, style()->width().value());
+    case Percent:
+    {
+        const int cw = containingBlockWidth();
+        return cw > 0 ? max(0, style()->width().calcMinValue(cw)) : 0;
+    }
+    default:
+        return 0;
+    }
+}
+
+int RenderSVGContainer::calcReplacedHeight() const
+{
+    switch (style()->height().type()) {
+    case Fixed:
+        return max(0, style()->height().value());
+    case Percent:
+    {
+        RenderBlock* cb = containingBlock();
+        return style()->height().calcValue(cb->availableHeight());
+    }
+    default:
+        return 0;
+    }
+}
+
+void RenderSVGContainer::applyContentTransforms(PaintInfo& paintInfo)
+{
+    if (!localTransform().isIdentity())
+        paintInfo.context->concatCTM(localTransform());
+}
+
+void RenderSVGContainer::applyAdditionalTransforms(PaintInfo& paintInfo)
+{
+    // no-op
+}
+
+void RenderSVGContainer::calcBounds()
+{
+    m_width = calcReplacedWidth();
+    m_height = calcReplacedHeight();
+    m_absoluteBounds = absoluteClippedOverflowRect();
+}
+
+bool RenderSVGContainer::selfWillPaint() const
+{
+#if ENABLE(SVG_FILTERS)
+    const SVGRenderStyle* svgStyle = style()->svgStyle();
+    SVGResourceFilter* filter = getFilterById(document(), svgStyle->filter());
+    if (filter)
+        return true;
+#endif
+    return false;
+}
+
+void RenderSVGContainer::paint(PaintInfo& paintInfo, int parentX, int parentY)
+{
+    if (paintInfo.context->paintingDisabled() || !drawsContents())
+        return;
+
+     // Spec: groups w/o children still may render filter content.
+    if (!firstChild() && !selfWillPaint())
+        return;
+    
+    paintInfo.context->save();
+    applyContentTransforms(paintInfo);
+
+    SVGResourceFilter* filter = 0;
+    PaintInfo savedInfo(paintInfo);
+
+    FloatRect boundingBox = relativeBBox(true);
+    if (paintInfo.phase == PaintPhaseForeground)
+        prepareToRenderSVGContent(this, paintInfo, boundingBox, filter); 
+
+    applyAdditionalTransforms(paintInfo);
+
+    // default implementation. Just pass paint through to the children
+    PaintInfo childInfo(paintInfo);
+    childInfo.paintingRoot = paintingRootForChildren(paintInfo);
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling())
+        child->paint(childInfo, 0, 0);
+
+    if (paintInfo.phase == PaintPhaseForeground)
+        finishRenderSVGContent(this, paintInfo, boundingBox, filter, savedInfo.context);
+
+    paintInfo.context->restore();
+    
+    if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE)
+        paintOutline(paintInfo.context, m_absoluteBounds.x(), m_absoluteBounds.y(), m_absoluteBounds.width(), m_absoluteBounds.height(), style());
+}
+
+AffineTransform RenderSVGContainer::viewportTransform() const
+{
+     return AffineTransform();
+}
+
+IntRect RenderSVGContainer::absoluteClippedOverflowRect()
+{
+    FloatRect repaintRect;
+
+    for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
+        repaintRect.unite(current->absoluteClippedOverflowRect());
+
+#if ENABLE(SVG_FILTERS)
+    // Filters can expand the bounding box
+    SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter());
+    if (filter)
+        repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect));
+#endif
+
+    if (!repaintRect.isEmpty())
+        repaintRect.inflate(1); // inflate 1 pixel for antialiasing
+
+    return enclosingIntRect(repaintRect);
+}
+
+void RenderSVGContainer::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
+{
+    graphicsContext->addFocusRingRect(m_absoluteBounds);
+}
+
+void RenderSVGContainer::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+{
+    rects.append(absoluteClippedOverflowRect());
+}
+
+FloatRect RenderSVGContainer::relativeBBox(bool includeStroke) const
+{
+    FloatRect rect;
+    
+    RenderObject* current = firstChild();
+    for (; current != 0; current = current->nextSibling()) {
+        FloatRect childBBox = current->relativeBBox(includeStroke);
+        FloatRect mappedBBox = current->localTransform().mapRect(childBBox);
+
+        // <svg> can have a viewBox contributing to the bbox
+        if (current->isSVGContainer())
+            mappedBBox = static_cast<RenderSVGContainer*>(current)->viewportTransform().mapRect(mappedBBox);
+
+        rect.unite(mappedBBox);
+    }
+
+    return rect;
+}
+
+bool RenderSVGContainer::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
+{
+    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+        if (child->nodeAtPoint(request, result, _x, _y, _tx, _ty, hitTestAction)) {
+            updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
+            return true;
+        }
+    }
+
+    // Spec: Only graphical elements can be targeted by the mouse, period.
+    // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
+    return false;
+}
+
+}
+
+#endif // ENABLE(SVG)
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderSVGContainer.h b/WebCore/rendering/RenderSVGContainer.h
new file mode 100644
index 0000000..06751a3
--- /dev/null
+++ b/WebCore/rendering/RenderSVGContainer.h
@@ -0,0 +1,121 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005, 2007 Rob Buis <[email protected]>
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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
+    aint with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RenderSVGContainer_h
+#define RenderSVGContainer_h
+
+#if ENABLE(SVG)
+
+#include "RenderPath.h"
+#include "SVGPreserveAspectRatio.h"
+
+namespace WebCore {
+
+class SVGElement;
+
+class RenderSVGContainer : public RenderObject {
+public:
+    RenderSVGContainer(SVGStyledElement*);
+    ~RenderSVGContainer();
+
+    virtual RenderObject* firstChild() const { return m_firstChild; }
+    virtual RenderObject* lastChild() const { return m_lastChild; }
+
+    virtual int width() const { return m_width; }
+    virtual int height() const { return m_height; }
+
+    virtual bool canHaveChildren() const;
+    virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject*);
+
+    virtual void destroy();
+    void destroyLeftoverChildren();
+
+    virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
+    virtual void appendChildNode(RenderObject*, bool fullAppend = true);
+    virtual void insertChildNode(RenderObject* child, RenderObject* before, bool fullInsert = true);
+
+    // Designed for speed.  Don't waste time doing a bunch of work like layer updating and repainting when we know that our
+    // change in parentage is not going to affect anything.
+    virtual void moveChildNode(RenderObject* child) { appendChildNode(child->parent()->removeChildNode(child, false), false); }
+
+    virtual void calcPrefWidths() { setPrefWidthsDirty(false); }
+
+    // Some containers do not want it's children
+    // to be drawn, because they may be 'referenced'
+    // Example: <marker> children in SVG
+    void setDrawsContents(bool);
+    bool drawsContents() const;
+
+    virtual bool isSVGContainer() const { return true; }
+    virtual const char* renderName() const { return "RenderSVGContainer"; }
+
+    virtual bool requiresLayer();
+    virtual int lineHeight(bool b, bool isRootLineBox = false) const;
+    virtual int baselinePosition(bool b, bool isRootLineBox = false) const;
+
+    virtual void layout();
+    virtual void paint(PaintInfo&, int parentX, int parentY);
+
+    virtual IntRect absoluteClippedOverflowRect();
+    virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel = true);
+    virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+
+    FloatRect relativeBBox(bool includeStroke = true) const;
+
+    virtual bool calculateLocalTransform();
+    virtual AffineTransform localTransform() const;
+    virtual AffineTransform viewportTransform() const;
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+protected:
+    virtual void applyContentTransforms(PaintInfo&);
+    virtual void applyAdditionalTransforms(PaintInfo&);
+
+    void calcBounds();
+
+private:
+    int calcReplacedWidth() const;
+    int calcReplacedHeight() const;
+
+    RenderObject* m_firstChild;
+    RenderObject* m_lastChild;
+
+    int m_width;
+    int m_height;
+    
+    bool selfWillPaint() const;
+
+    bool m_drawsContents : 1;
+    
+protected:    
+    IntRect m_absoluteBounds;
+    AffineTransform m_localTransform;
+};
+  
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGContainer_h
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderSVGGradientStop.cpp b/WebCore/rendering/RenderSVGGradientStop.cpp
new file mode 100644
index 0000000..d0dc881
--- /dev/null
+++ b/WebCore/rendering/RenderSVGGradientStop.cpp
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2007 Eric Seidel <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGGradientStop.h"
+
+#include "SVGGradientElement.h"
+#include "SVGNames.h"
+#include "SVGStopElement.h"
+
+namespace WebCore {
+    
+using namespace SVGNames;
+
+RenderSVGGradientStop::RenderSVGGradientStop(SVGStopElement* element)
+    : RenderObject(element)
+{
+}
+
+RenderSVGGradientStop::~RenderSVGGradientStop()
+{
+}
+
+void RenderSVGGradientStop::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderObject::styleDidChange(diff, oldStyle);
+
+    // <stop> elements should only be allowed to make renderers under gradient elements
+    // but I can imagine a few cases we might not be catching, so let's not crash if our parent isn't a gradient.
+    if (SVGGradientElement* gradient = gradientElement()) {
+        if (SVGResource* resource = gradient->canvasResource())
+            resource->invalidate();
+    }
+}
+
+void RenderSVGGradientStop::layout()
+{
+    setNeedsLayout(false);
+}
+
+SVGGradientElement* RenderSVGGradientStop::gradientElement() const
+{
+    Node* parentNode = element()->parent();
+    if (parentNode->hasTagName(linearGradientTag) || parentNode->hasTagName(radialGradientTag))
+        return static_cast<SVGGradientElement*>(parentNode);
+    return 0;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGGradientStop.h b/WebCore/rendering/RenderSVGGradientStop.h
new file mode 100644
index 0000000..86de6d0
--- /dev/null
+++ b/WebCore/rendering/RenderSVGGradientStop.h
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2007 Eric Seidel <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderSVGGradientStop_h
+#define RenderSVGGradientStop_h
+
+#if ENABLE(SVG)
+#include "RenderObject.h"
+
+namespace WebCore {
+    
+    class SVGGradientElement;
+    class SVGStopElement;
+    
+    // This class exists mostly so we can hear about gradient stop style changes
+    class RenderSVGGradientStop : public RenderObject {
+    public:
+        RenderSVGGradientStop(SVGStopElement*);
+        virtual ~RenderSVGGradientStop();
+
+        virtual const char* renderName() const { return "RenderSVGGradientStop"; }
+
+        virtual void layout();
+
+        // This override is needed to prevent crashing on <svg><stop /></svg>
+        // RenderObject's default impl asks the parent Object and RenderSVGRoot
+        // asks all child RenderObjects for overflow rects, thus infinite loop.
+        // https://bugs.webkit.org/show_bug.cgi?id=20400
+        virtual IntRect absoluteClippedOverflowRect() { return IntRect(); }
+    
+    protected:
+        virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+    private:
+        SVGGradientElement* gradientElement() const;
+    };
+}
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGGradientStop_h
diff --git a/WebCore/rendering/RenderSVGHiddenContainer.cpp b/WebCore/rendering/RenderSVGHiddenContainer.cpp
new file mode 100644
index 0000000..bc758e5
--- /dev/null
+++ b/WebCore/rendering/RenderSVGHiddenContainer.cpp
@@ -0,0 +1,111 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2007 Eric Seidel <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGHiddenContainer.h"
+
+#include "RenderPath.h"
+#include "SVGStyledElement.h"
+
+namespace WebCore {
+
+RenderSVGHiddenContainer::RenderSVGHiddenContainer(SVGStyledElement* element)
+    : RenderSVGContainer(element)
+{
+}
+
+RenderSVGHiddenContainer::~RenderSVGHiddenContainer()
+{
+}
+
+bool RenderSVGHiddenContainer::requiresLayer()
+{
+    return false;
+}
+
+int RenderSVGHiddenContainer::lineHeight(bool b, bool isRootLineBox) const
+{
+    return 0;
+}
+
+int RenderSVGHiddenContainer::baselinePosition(bool b, bool isRootLineBox) const
+{
+    return 0;
+}
+
+void RenderSVGHiddenContainer::layout()
+{
+    ASSERT(needsLayout());
+ 
+    // Layout our kids to prevent a kid from being marked as needing layout
+    // then never being asked to layout.
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (selfNeedsLayout())
+            child->setNeedsLayout(true);
+        
+        child->layoutIfNeeded();
+        ASSERT(!child->needsLayout());
+    }
+    
+    setNeedsLayout(false);    
+}
+
+void RenderSVGHiddenContainer::paint(PaintInfo&, int, int)
+{
+    // This subtree does not paint.
+}
+
+IntRect RenderSVGHiddenContainer::absoluteClippedOverflowRect()
+{
+    return IntRect();
+}
+
+void RenderSVGHiddenContainer::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+{
+    // This subtree does not take up space or paint
+}
+
+AffineTransform RenderSVGHiddenContainer::absoluteTransform() const
+{
+    return AffineTransform();
+}
+
+AffineTransform RenderSVGHiddenContainer::localTransform() const
+{
+    return AffineTransform();
+}
+
+bool RenderSVGHiddenContainer::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
+{
+    return false;
+}
+
+FloatRect RenderSVGHiddenContainer::relativeBBox(bool includeStroke) const
+{
+    return FloatRect();
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGHiddenContainer.h b/WebCore/rendering/RenderSVGHiddenContainer.h
new file mode 100644
index 0000000..c428a79
--- /dev/null
+++ b/WebCore/rendering/RenderSVGHiddenContainer.h
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2007 Eric Seidel <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderSVGHiddenContainer_h
+#define RenderSVGHiddenContainer_h
+
+#if ENABLE(SVG)
+
+#include "RenderSVGContainer.h"
+
+namespace WebCore {
+    
+    class SVGStyledElement;
+    
+    // This class is for containers which are never drawn, but do need to support style
+    // <defs>, <linearGradient>, <radialGradient> are all good examples
+    class RenderSVGHiddenContainer : public RenderSVGContainer {
+    public:
+        RenderSVGHiddenContainer(SVGStyledElement*);
+        virtual ~RenderSVGHiddenContainer();
+        
+        virtual bool isSVGContainer() const { return true; }
+        virtual bool isSVGHiddenContainer() const { return true; }
+
+        virtual const char* renderName() const { return "RenderSVGHiddenContainer"; }
+        
+        virtual bool requiresLayer();
+        
+        virtual int lineHeight(bool b, bool isRootLineBox = false) const;
+        virtual int baselinePosition(bool b, bool isRootLineBox = false) const;
+        
+        virtual void layout();
+        virtual void paint(PaintInfo&, int parentX, int parentY);
+        
+        virtual IntRect absoluteClippedOverflowRect();
+        virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel = true);
+        
+        virtual AffineTransform absoluteTransform() const;
+        virtual AffineTransform localTransform() const;
+
+        virtual FloatRect relativeBBox(bool includeStroke = true) const;
+        virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+    };
+}
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGHiddenContainer_h
diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp
new file mode 100644
index 0000000..345e79f
--- /dev/null
+++ b/WebCore/rendering/RenderSVGImage.cpp
@@ -0,0 +1,274 @@
+/*
+    Copyright (C) 2006 Alexander Kellett <[email protected]>
+    Copyright (C) 2006 Apple Computer, Inc.
+    Copyright (C) 2007 Nikolas Zimmermann <[email protected]>
+    Copyright (C) 2007, 2008 Rob Buis <[email protected]>
+
+    This file is part of the WebKit project
+
+    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, or (at your option) any later version.
+
+    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., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGImage.h"
+
+#include "Attr.h"
+#include "FloatConversion.h"
+#include "GraphicsContext.h"
+#include "PointerEventsHitRules.h"
+#include "SVGImageElement.h"
+#include "SVGLength.h"
+#include "SVGPreserveAspectRatio.h"
+#include "SVGRenderSupport.h"
+#include "SVGResourceClipper.h"
+#include "SVGResourceFilter.h"
+#include "SVGResourceMasker.h"
+
+namespace WebCore {
+
+RenderSVGImage::RenderSVGImage(SVGImageElement* impl)
+    : RenderImage(impl)
+{
+}
+
+RenderSVGImage::~RenderSVGImage()
+{
+}
+
+void RenderSVGImage::adjustRectsForAspectRatio(FloatRect& destRect, FloatRect& srcRect, SVGPreserveAspectRatio* aspectRatio)
+{
+    float origDestWidth = destRect.width();
+    float origDestHeight = destRect.height();
+    if (aspectRatio->meetOrSlice() == SVGPreserveAspectRatio::SVG_MEETORSLICE_MEET) {
+        float widthToHeightMultiplier = srcRect.height() / srcRect.width();
+        if (origDestHeight > (origDestWidth * widthToHeightMultiplier)) {
+            destRect.setHeight(origDestWidth * widthToHeightMultiplier);
+            switch(aspectRatio->align()) {
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMID:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID:
+                    destRect.setY(destRect.y() + origDestHeight / 2.0f - destRect.height() / 2.0f);
+                    break;
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMAX:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX:
+                    destRect.setY(destRect.y() + origDestHeight - destRect.height());
+                    break;
+            }
+        }
+        if (origDestWidth > (origDestHeight / widthToHeightMultiplier)) {
+            destRect.setWidth(origDestHeight / widthToHeightMultiplier);
+            switch(aspectRatio->align()) {
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMIN:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX:
+                    destRect.setX(destRect.x() + origDestWidth / 2.0f - destRect.width() / 2.0f);
+                    break;
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMIN:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX:
+                    destRect.setX(destRect.x() + origDestWidth - destRect.width());
+                    break;
+            }
+        }
+    } else if (aspectRatio->meetOrSlice() == SVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE) {
+        float widthToHeightMultiplier = srcRect.height() / srcRect.width();
+        // if the destination height is less than the height of the image we'll be drawing
+        if (origDestHeight < (origDestWidth * widthToHeightMultiplier)) {
+            float destToSrcMultiplier = srcRect.width() / destRect.width();
+            srcRect.setHeight(destRect.height() * destToSrcMultiplier);
+            switch(aspectRatio->align()) {
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMID:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID:
+                    srcRect.setY(destRect.y() + image()->height() / 2.0f - srcRect.height() / 2.0f);
+                    break;
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMAX:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX:
+                    srcRect.setY(destRect.y() + image()->height() - srcRect.height());
+                    break;
+            }
+        }
+        // if the destination width is less than the width of the image we'll be drawing
+        if (origDestWidth < (origDestHeight / widthToHeightMultiplier)) {
+            float destToSrcMultiplier = srcRect.height() / destRect.height();
+            srcRect.setWidth(destRect.width() * destToSrcMultiplier);
+            switch(aspectRatio->align()) {
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMIN:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX:
+                    srcRect.setX(destRect.x() + image()->width() / 2.0f - srcRect.width() / 2.0f);
+                    break;
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMIN:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID:
+                case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX:
+                    srcRect.setX(destRect.x() + image()->width() - srcRect.width());
+                    break;
+            }
+        }
+    }
+}
+
+bool RenderSVGImage::calculateLocalTransform()
+{
+    AffineTransform oldTransform = m_localTransform;
+    m_localTransform = static_cast<SVGStyledTransformableElement*>(element())->animatedLocalTransform();
+    return (m_localTransform != oldTransform);
+}
+
+void RenderSVGImage::layout()
+{
+    ASSERT(needsLayout());
+    
+    IntRect oldBounds;
+    IntRect oldOutlineBox;
+    bool checkForRepaint = checkForRepaintDuringLayout();
+    if (checkForRepaint) {
+        oldBounds = absoluteClippedOverflowRect();
+        oldOutlineBox = absoluteOutlineBox();
+    }
+    
+    calculateLocalTransform();
+    
+    // minimum height
+    m_height = errorOccurred() ? intrinsicSize().height() : 0;
+
+    calcWidth();
+    calcHeight();
+
+    SVGImageElement* image = static_cast<SVGImageElement*>(node());
+    m_localBounds = FloatRect(image->x().value(image), image->y().value(image), image->width().value(image), image->height().value(image));
+
+    calculateAbsoluteBounds();
+
+    if (checkForRepaint)
+        repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+
+    setNeedsLayout(false);
+}
+
+void RenderSVGImage::paint(PaintInfo& paintInfo, int, int)
+{
+    if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN)
+        return;
+
+    paintInfo.context->save();
+    paintInfo.context->concatCTM(localTransform());
+
+    if (paintInfo.phase == PaintPhaseForeground) {
+        SVGResourceFilter* filter = 0;
+
+        PaintInfo savedInfo(paintInfo);
+
+        prepareToRenderSVGContent(this, paintInfo, m_localBounds, filter);
+
+        FloatRect destRect = m_localBounds;
+        FloatRect srcRect(0, 0, image()->width(), image()->height());
+
+        SVGImageElement* imageElt = static_cast<SVGImageElement*>(node());
+        if (imageElt->preserveAspectRatio()->align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE)
+            adjustRectsForAspectRatio(destRect, srcRect, imageElt->preserveAspectRatio());
+
+        paintInfo.context->drawImage(image(), destRect, srcRect);
+
+        finishRenderSVGContent(this, paintInfo, m_localBounds, filter, savedInfo.context);
+    }
+    
+    paintInfo.context->restore();
+}
+
+bool RenderSVGImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int, int, HitTestAction hitTestAction)
+{
+    // We only draw in the forground phase, so we only hit-test then.
+    if (hitTestAction != HitTestForeground)
+        return false;
+
+    PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, style()->svgStyle()->pointerEvents());
+    
+    bool isVisible = (style()->visibility() == VISIBLE);
+    if (isVisible || !hitRules.requireVisible) {
+        double localX, localY;
+        absoluteTransform().inverse().map(_x, _y, &localX, &localY);
+
+        if (hitRules.canHitFill) {
+            if (m_localBounds.contains(narrowPrecisionToFloat(localX), narrowPrecisionToFloat(localY))) {
+                updateHitTestResult(result, IntPoint(_x, _y));
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+bool RenderSVGImage::requiresLayer()
+{
+    return false;
+}
+
+FloatRect RenderSVGImage::relativeBBox(bool) const
+{
+    return m_localBounds;
+}
+
+void RenderSVGImage::imageChanged(WrappedImagePtr image)
+{
+    RenderImage::imageChanged(image);
+
+    // We override to invalidate a larger rect, since SVG images can draw outside their "bounds"
+    repaintRectangle(absoluteClippedOverflowRect());
+}
+
+void RenderSVGImage::calculateAbsoluteBounds()
+{
+    FloatRect absoluteRect = absoluteTransform().mapRect(relativeBBox(true));
+
+#if ENABLE(SVG_FILTERS)
+    // Filters can expand the bounding box
+    SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter());
+    if (filter)
+        absoluteRect.unite(filter->filterBBoxForItemBBox(absoluteRect));
+#endif
+
+    if (!absoluteRect.isEmpty())
+        absoluteRect.inflate(1); // inflate 1 pixel for antialiasing
+
+    m_absoluteBounds = enclosingIntRect(absoluteRect);
+}
+
+IntRect RenderSVGImage::absoluteClippedOverflowRect()
+{
+    return m_absoluteBounds;
+}
+
+void RenderSVGImage::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
+{
+    // this is called from paint() after the localTransform has already been applied
+    IntRect contentRect = enclosingIntRect(relativeBBox());
+    graphicsContext->addFocusRingRect(contentRect);
+}
+
+void RenderSVGImage::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+{
+    rects.append(absoluteClippedOverflowRect());
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGImage.h b/WebCore/rendering/RenderSVGImage.h
new file mode 100644
index 0000000..4891306
--- /dev/null
+++ b/WebCore/rendering/RenderSVGImage.h
@@ -0,0 +1,74 @@
+/*
+    Copyright (C) 2006 Alexander Kellett <[email protected]>
+    Copyright (C) 2006 Apple Computer, Inc.
+    Copyright (C) 2007 Rob Buis <[email protected]>
+
+    This file is part of the WebKit project.
+
+    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, or (at your option) any later version.
+
+    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., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RenderSVGImage_h
+#define RenderSVGImage_h
+
+#if ENABLE(SVG)
+
+#include "AffineTransform.h"
+#include "FloatRect.h"
+#include "RenderImage.h"
+
+namespace WebCore {
+
+    class SVGImageElement;
+    class SVGPreserveAspectRatio;
+
+    class RenderSVGImage : public RenderImage {
+    public:
+        RenderSVGImage(SVGImageElement*);
+        virtual ~RenderSVGImage();
+        
+        virtual AffineTransform localTransform() const { return m_localTransform; }
+        
+        virtual FloatRect relativeBBox(bool includeStroke = true) const;
+        virtual IntRect absoluteClippedOverflowRect();
+        virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
+        virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+
+        virtual void imageChanged(WrappedImagePtr);
+        void adjustRectsForAspectRatio(FloatRect& destRect, FloatRect& srcRect, SVGPreserveAspectRatio*);
+        
+        virtual void layout();
+        virtual void paint(PaintInfo&, int parentX, int parentY);
+
+        bool requiresLayer();
+
+        virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int _x, int _y, int _tx, int _ty, HitTestAction);
+
+        bool calculateLocalTransform();
+
+    private:
+        void calculateAbsoluteBounds();
+        AffineTransform m_localTransform;
+        FloatRect m_localBounds;
+        IntRect m_absoluteBounds;
+    };
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGImage_h
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderSVGInline.cpp b/WebCore/rendering/RenderSVGInline.cpp
new file mode 100644
index 0000000..11da004
--- /dev/null
+++ b/WebCore/rendering/RenderSVGInline.cpp
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <[email protected]>
+ *           (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGInline.h"
+
+#include "SVGInlineFlowBox.h"
+
+namespace WebCore {
+    
+RenderSVGInline::RenderSVGInline(Node* n)
+    : RenderInline(n)
+{
+}
+
+InlineBox* RenderSVGInline::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun)
+{
+    ASSERT(!(!isRootLineBox && (isReplaced() || makePlaceHolderBox)));
+    ASSERT(isInlineFlow());
+
+    InlineFlowBox* flowBox = new (renderArena()) SVGInlineFlowBox(this);
+
+    if (!m_firstLineBox)
+        m_firstLineBox = m_lastLineBox = flowBox;
+    else {
+        m_lastLineBox->setNextLineBox(flowBox);
+        flowBox->setPreviousLineBox(m_lastLineBox);
+        m_lastLineBox = flowBox;
+    }
+        
+    return flowBox;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGInline.h b/WebCore/rendering/RenderSVGInline.h
new file mode 100644
index 0000000..42fdafc
--- /dev/null
+++ b/WebCore/rendering/RenderSVGInline.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <[email protected]>
+ *           (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderSVGInline_h
+#define RenderSVGInline_h
+
+#if ENABLE(SVG)
+#include "RenderInline.h"
+
+namespace WebCore {
+class RenderSVGInline : public RenderInline {
+public:
+        RenderSVGInline(Node*);
+        virtual const char* renderName() const { return "RenderSVGInline"; }
+        virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun = false);
+        virtual bool requiresLayer() { return false; }
+    };
+}
+
+#endif // ENABLE(SVG)
+#endif // !RenderSVGTSpan_H
diff --git a/WebCore/rendering/RenderSVGInlineText.cpp b/WebCore/rendering/RenderSVGInlineText.cpp
new file mode 100644
index 0000000..33a984c
--- /dev/null
+++ b/WebCore/rendering/RenderSVGInlineText.cpp
@@ -0,0 +1,174 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <[email protected]>
+ *           (C) 2006 Apple Computer Inc.
+ *           (C) 2007 Nikolas Zimmermann <[email protected]>
+ *           (C) 2008 Rob Buis <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGInlineText.h"
+
+#include "FloatConversion.h"
+#include "RenderBlock.h"
+#include "RenderSVGRoot.h"
+#include "SVGInlineTextBox.h"
+#include "SVGRootInlineBox.h"
+
+namespace WebCore {
+
+static inline bool isChildOfHiddenContainer(RenderObject* start)
+{
+    while (start) {
+        if (start->isSVGHiddenContainer())
+            return true;
+
+        start = start->parent();
+    }
+
+    return false;
+}
+
+RenderSVGInlineText::RenderSVGInlineText(Node* n, PassRefPtr<StringImpl> str) 
+    : RenderText(n, str)
+{
+}
+
+void RenderSVGInlineText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+{
+    rects.append(computeAbsoluteRectForRange(0, textLength()));
+}
+
+IntRect RenderSVGInlineText::selectionRect(bool)
+{
+    ASSERT(!needsLayout());
+
+    IntRect rect;
+    if (selectionState() == SelectionNone)
+        return rect;
+
+    // Early exit if we're ie. a <text> within a <defs> section.
+    if (isChildOfHiddenContainer(this))
+        return rect;
+
+    // Now calculate startPos and endPos for painting selection.
+    // We include a selection while endPos > 0
+    int startPos, endPos;
+    if (selectionState() == SelectionInside) {
+        // We are fully selected.
+        startPos = 0;
+        endPos = textLength();
+    } else {
+        selectionStartEnd(startPos, endPos);
+        if (selectionState() == SelectionStart)
+            endPos = textLength();
+        else if (selectionState() == SelectionEnd)
+            startPos = 0;
+    }
+
+    if (startPos == endPos)
+        return rect;
+
+    return computeAbsoluteRectForRange(startPos, endPos);
+}
+
+IntRect RenderSVGInlineText::computeAbsoluteRectForRange(int startPos, int endPos)
+{
+    IntRect rect;
+
+    RenderBlock* cb = containingBlock();
+    if (!cb || !cb->container())
+        return rect;
+
+    RenderSVGRoot* root = findSVGRootObject(parent());
+    if (!root)
+        return rect;
+
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+        rect.unite(box->selectionRect(0, 0, startPos, endPos));
+
+    // Mimic RenderBox::computeAbsoluteRepaintRect() functionality. But only the subset needed for SVG and respecting SVG transformations.
+    int x, y;
+    cb->container()->absolutePosition(x, y);
+
+    // Remove HTML parent translation offsets here! These need to be retrieved from the RenderSVGRoot object.
+    // But do take the containingBlocks's container position into account, ie. SVG text in scrollable <div>.
+    AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
+
+    FloatRect fixedRect(narrowPrecisionToFloat(rect.x() + x - xPos() - htmlParentCtm.e()), narrowPrecisionToFloat(rect.y() + y - yPos() - htmlParentCtm.f()), rect.width(), rect.height());
+    return enclosingIntRect(absoluteTransform().mapRect(fixedRect));
+}
+
+InlineTextBox* RenderSVGInlineText::createInlineTextBox()
+{
+    return new (renderArena()) SVGInlineTextBox(this);
+}
+
+IntRect RenderSVGInlineText::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
+{
+    // SVG doesn't have any editable content where a caret rect would be needed
+    return IntRect();
+}
+
+VisiblePosition RenderSVGInlineText::positionForCoordinates(int x, int y)
+{
+    SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(firstTextBox());
+
+    if (!textBox || textLength() == 0)
+        return VisiblePosition(element(), 0, DOWNSTREAM);
+
+    SVGRootInlineBox* rootBox = textBox->svgRootInlineBox();
+    RenderObject* object = rootBox ? rootBox->object() : 0;
+
+    if (!object)
+        return VisiblePosition(element(), 0, DOWNSTREAM);
+
+    int offset = 0;
+
+    for (SVGInlineTextBox* box = textBox; box; box = static_cast<SVGInlineTextBox*>(box->nextTextBox())) {
+        if (box->svgCharacterHitsPosition(x + object->xPos(), y + object->yPos(), offset)) {
+            // If we're not at the end/start of the box, stop looking for other selected boxes.
+            if (box->direction() == LTR) {
+                if (offset <= (int) box->end() + 1)
+                    break;
+            } else {
+                if (offset > (int) box->start())
+                    break;
+            }
+        }
+    }
+
+    return VisiblePosition(element(), offset, DOWNSTREAM);
+}
+
+void RenderSVGInlineText::destroy()
+{
+    if (!documentBeingDestroyed()) {
+        setNeedsLayoutAndPrefWidthsRecalc();
+        repaint();
+    }
+    RenderText::destroy();
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGInlineText.h b/WebCore/rendering/RenderSVGInlineText.h
new file mode 100644
index 0000000..786ba31
--- /dev/null
+++ b/WebCore/rendering/RenderSVGInlineText.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <[email protected]>
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *           (C) 2008 Rob Buis <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderSVGInlineText_h
+#define RenderSVGInlineText_h
+
+#if ENABLE(SVG)
+
+#include "RenderText.h"
+
+namespace WebCore {
+class RenderSVGInlineText : public RenderText {
+public:
+    RenderSVGInlineText(Node*, PassRefPtr<StringImpl>);
+    virtual const char* renderName() const { return "RenderSVGInlineText"; }
+    virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel = true);
+    virtual bool requiresLayer() { return false; }
+    virtual IntRect selectionRect(bool clipToVisibleContent = true);
+    virtual bool isSVGText() const { return true; }
+    virtual InlineTextBox* createInlineTextBox();
+
+    virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
+    virtual VisiblePosition positionForCoordinates(int x, int y);
+
+    virtual void destroy();
+
+private:
+    IntRect computeAbsoluteRectForRange(int startPos, int endPos);
+};
+
+}
+
+#endif // ENABLE(SVG)
+
+#endif // !RenderSVGInlineText_h
diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp
new file mode 100644
index 0000000..1c59450
--- /dev/null
+++ b/WebCore/rendering/RenderSVGRoot.cpp
@@ -0,0 +1,334 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005, 2007, 2008 Rob Buis <[email protected]>
+                  2007 Eric Seidel <[email protected]>
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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
+    aint with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGRoot.h"
+
+#include "GraphicsContext.h"
+#include "RenderPath.h"
+#include "RenderSVGContainer.h"
+#include "RenderView.h"
+#include "SVGLength.h"
+#include "SVGRenderSupport.h"
+#include "SVGResourceClipper.h"
+#include "SVGResourceFilter.h"
+#include "SVGResourceMasker.h"
+#include "SVGSVGElement.h"
+#include "SVGStyledElement.h"
+#include "SVGURIReference.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderSVGRoot::RenderSVGRoot(SVGStyledElement* node)
+    : RenderContainer(node)
+{
+    setReplaced(true);
+}
+
+RenderSVGRoot::~RenderSVGRoot()
+{
+}
+
+int RenderSVGRoot::lineHeight(bool b, bool isRootLineBox) const
+{
+    return height() + marginTop() + marginBottom();
+}
+
+int RenderSVGRoot::baselinePosition(bool b, bool isRootLineBox) const
+{
+    return height() + marginTop() + marginBottom();
+}
+
+void RenderSVGRoot::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+
+    int paddingAndBorders = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+    int width = calcReplacedWidth(false) + paddingAndBorders;
+
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength)
+        width = min(width, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? paddingAndBorders : 0));
+
+    if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent())) {
+        m_minPrefWidth = 0;
+        m_maxPrefWidth = width;
+    } else
+        m_minPrefWidth = m_maxPrefWidth = width;
+
+    setPrefWidthsDirty(false);
+}
+
+void RenderSVGRoot::layout()
+{
+    ASSERT(needsLayout());
+
+    calcViewport();
+
+    // Arbitrary affine transforms are incompatible with LayoutState.
+    view()->disableLayoutState();
+
+    IntRect oldBounds = m_absoluteBounds;
+    IntRect oldOutlineBox;
+    bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
+    if (checkForRepaint)
+        oldOutlineBox = absoluteOutlineBox();
+
+    calcWidth();
+    calcHeight();
+
+    m_absoluteBounds = absoluteClippedOverflowRect();
+    SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
+    m_width = static_cast<int>(m_width * svg->currentScale());
+    m_height = static_cast<int>(m_height * svg->currentScale());
+    
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (selfNeedsLayout()) // either bounds or transform changed, force kids to relayout
+            child->setNeedsLayout(true);
+        
+        child->layoutIfNeeded();
+        ASSERT(!child->needsLayout());
+    }
+
+    if (checkForRepaint)
+        repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+
+    view()->enableLayoutState();
+    setNeedsLayout(false);
+}
+
+void RenderSVGRoot::applyContentTransforms(PaintInfo& paintInfo, int parentX, int parentY)
+{
+    // Translate from parent offsets (html renderers) to a relative transform (svg renderers)
+    IntPoint origin;
+    origin.move(parentX, parentY);
+    origin.move(m_x, m_y);
+    origin.move(borderLeft(), borderTop());
+    origin.move(paddingLeft(), paddingTop());
+
+    if (origin.x() || origin.y()) {
+        paintInfo.context->concatCTM(AffineTransform().translate(origin.x(), origin.y()));
+        paintInfo.rect.move(-origin.x(), -origin.y());
+    }
+
+    // Respect scroll offset caused by html parents
+    AffineTransform ctm = RenderContainer::absoluteTransform();
+    paintInfo.rect.move(static_cast<int>(ctm.e()), static_cast<int>(ctm.f()));
+
+    SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
+    paintInfo.context->concatCTM(AffineTransform().scale(svg->currentScale()));
+
+    if (!viewport().isEmpty()) {
+        if (style()->overflowX() != OVISIBLE)
+            paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping
+        
+        paintInfo.context->concatCTM(AffineTransform().translate(viewport().x(), viewport().y()));
+    }
+
+    paintInfo.context->concatCTM(AffineTransform().translate(svg->currentTranslate().x(), svg->currentTranslate().y()));
+}
+
+void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY)
+{
+    if (paintInfo.context->paintingDisabled())
+        return;
+
+    calcViewport();
+
+    SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
+    // A value of zero disables rendering of the element. 
+    if (viewport().width() <= 0. || viewport().height() <= 0.)
+        return;
+
+    // This should only exist for <svg> renderers
+    if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) 
+        paintBoxDecorations(paintInfo, m_x + parentX, m_y + parentY);
+
+    if (!firstChild()) {
+#if ENABLE(SVG_FILTERS)
+        // Spec: groups w/o children still may render filter content.
+        const SVGRenderStyle* svgStyle = style()->svgStyle();
+        SVGResourceFilter* filter = getFilterById(document(), svgStyle->filter());
+        if (!filter)
+#endif
+            return;
+    }
+
+    RenderObject::PaintInfo childPaintInfo(paintInfo);
+    childPaintInfo.context->save();
+ 
+    applyContentTransforms(childPaintInfo, parentX, parentY);
+
+    SVGResourceFilter* filter = 0;
+
+    FloatRect boundingBox = relativeBBox(true);
+    if (childPaintInfo.phase == PaintPhaseForeground)
+        prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter);        
+
+    childPaintInfo.context->concatCTM(svg->viewBoxToViewTransform(width(), height()));
+    RenderContainer::paint(childPaintInfo, 0, 0);
+
+    if (childPaintInfo.phase == PaintPhaseForeground)
+        finishRenderSVGContent(this, childPaintInfo, boundingBox, filter, paintInfo.context);
+
+    childPaintInfo.context->restore();
+    
+    if ((childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE)
+        paintOutline(childPaintInfo.context, m_absoluteBounds.x(), m_absoluteBounds.y(), m_absoluteBounds.width(), m_absoluteBounds.height(), style());
+}
+
+FloatRect RenderSVGRoot::viewport() const
+{
+    return m_viewport;
+}
+
+void RenderSVGRoot::calcViewport()
+{
+    SVGElement* svgelem = static_cast<SVGElement*>(element());
+    if (svgelem->hasTagName(SVGNames::svgTag)) {
+        SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
+
+        if (!selfNeedsLayout() && !svg->hasRelativeValues())
+            return;
+
+        float w, h;
+        SVGLength width = svg->width();
+        if (width.unitType() == LengthTypePercentage && svg->hasSetContainerSize())
+            w = svg->relativeWidthValue();
+        else
+            w = width.value(svg);
+        
+        SVGLength height = svg->height();
+        if (height.unitType() == LengthTypePercentage && svg->hasSetContainerSize())
+            h = svg->relativeHeightValue();
+        else
+            h = height.value(svg);
+
+        m_viewport = FloatRect(0, 0, w, h);
+    }
+}
+
+IntRect RenderSVGRoot::absoluteClippedOverflowRect()
+{
+    IntRect repaintRect;
+
+    for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
+        repaintRect.unite(current->absoluteClippedOverflowRect());
+
+#if ENABLE(SVG_FILTERS)
+    // Filters can expand the bounding box
+    SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter());
+    if (filter)
+        repaintRect.unite(enclosingIntRect(filter->filterBBoxForItemBBox(repaintRect)));
+#endif
+
+    return repaintRect;
+}
+
+void RenderSVGRoot::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
+{
+    graphicsContext->addFocusRingRect(m_absoluteBounds);
+}
+
+void RenderSVGRoot::absoluteRects(Vector<IntRect>& rects, int, int)
+{
+    for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
+        current->absoluteRects(rects, 0, 0);
+}
+
+AffineTransform RenderSVGRoot::absoluteTransform() const
+{
+    AffineTransform ctm = RenderContainer::absoluteTransform();
+    ctm.translate(m_x, m_y);
+    SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
+    ctm.scale(svg->currentScale());
+    ctm.translate(svg->currentTranslate().x(), svg->currentTranslate().y());
+    ctm.translate(viewport().x(), viewport().y());
+    return svg->viewBoxToViewTransform(width(), height()) * ctm;
+}
+
+FloatRect RenderSVGRoot::relativeBBox(bool includeStroke) const
+{
+    FloatRect rect;
+    
+    RenderObject* current = firstChild();
+    for (; current != 0; current = current->nextSibling()) {
+        FloatRect childBBox = current->relativeBBox(includeStroke);
+        FloatRect mappedBBox = current->localTransform().mapRect(childBBox);
+        // <svg> can have a viewBox contributing to the bbox
+        if (current->isSVGContainer())
+            mappedBBox = static_cast<RenderSVGContainer*>(current)->viewportTransform().mapRect(mappedBBox);
+        rect.unite(mappedBBox);
+    }
+
+    return rect;
+}
+
+AffineTransform RenderSVGRoot::localTransform() const
+{
+    return AffineTransform();
+}
+
+bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
+{
+    AffineTransform ctm = RenderContainer::absoluteTransform();
+
+    int sx = (_tx - static_cast<int>(ctm.e())); // scroll offset
+    int sy = (_ty - static_cast<int>(ctm.f())); // scroll offset
+ 
+    if (!viewport().isEmpty()
+        && style()->overflowX() == OHIDDEN
+        && style()->overflowY() == OHIDDEN) {
+        int tx = m_x - _tx + sx;
+        int ty = m_y - _ty + sy;
+
+        // Check if we need to do anything at all.
+        IntRect overflowBox = overflowRect(false);
+        overflowBox.move(tx, ty);
+        ctm.translate(viewport().x(), viewport().y());
+        double localX, localY;
+        ctm.inverse().map(_x - _tx, _y - _ty, &localX, &localY);
+        if (!overflowBox.contains((int)localX, (int)localY))
+            return false;
+    }
+
+    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+        if (child->nodeAtPoint(request, result, _x - sx, _y - sy, 0, 0, hitTestAction)) {
+            updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
+            return true;
+        }
+    }
+    
+    // Spec: Only graphical elements can be targeted by the mouse, period.
+    // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
+    return false;
+}
+
+}
+
+#endif // ENABLE(SVG)
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderSVGRoot.h b/WebCore/rendering/RenderSVGRoot.h
new file mode 100644
index 0000000..58359fd
--- /dev/null
+++ b/WebCore/rendering/RenderSVGRoot.h
@@ -0,0 +1,79 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005, 2007 Rob Buis <[email protected]>
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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
+    aint with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RenderSVGRoot_h
+#define RenderSVGRoot_h
+
+#if ENABLE(SVG)
+#include "RenderContainer.h"
+#include "FloatRect.h"
+
+namespace WebCore {
+
+class SVGStyledElement;
+class AffineTransform;
+
+class RenderSVGRoot : public RenderContainer {
+public:
+    RenderSVGRoot(SVGStyledElement*);
+    ~RenderSVGRoot();
+
+    virtual bool isSVGRoot() const { return true; }
+    virtual const char* renderName() const { return "RenderSVGRoot"; }
+
+    virtual int lineHeight(bool b, bool isRootLineBox = false) const;
+    virtual int baselinePosition(bool b, bool isRootLineBox = false) const;
+    virtual void calcPrefWidths();
+    
+    virtual void layout();
+    virtual void paint(PaintInfo&, int parentX, int parentY);
+    
+    virtual IntRect absoluteClippedOverflowRect();
+    virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty);
+    virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+
+    virtual AffineTransform absoluteTransform() const;
+
+    bool fillContains(const FloatPoint&) const;
+    bool strokeContains(const FloatPoint&) const;
+    FloatRect relativeBBox(bool includeStroke = true) const;
+    
+    virtual AffineTransform localTransform() const;
+   
+    FloatRect viewport() const;
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+    
+private:
+    void calcViewport(); 
+    void applyContentTransforms(PaintInfo&, int parentX, int parentY);
+
+    FloatRect m_viewport;
+    IntRect m_absoluteBounds;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGRoot_h
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderSVGTSpan.cpp b/WebCore/rendering/RenderSVGTSpan.cpp
new file mode 100644
index 0000000..a8d6c57
--- /dev/null
+++ b/WebCore/rendering/RenderSVGTSpan.cpp
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <[email protected]>
+ *           (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGTSpan.h"
+
+#include "FloatRect.h"
+#include "SVGInlineTextBox.h"
+#include "SVGRootInlineBox.h"
+
+namespace WebCore {
+
+RenderSVGTSpan::RenderSVGTSpan(Node* n)
+    : RenderSVGInline(n)
+{
+}
+
+void RenderSVGTSpan::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+{
+    InlineRunBox* firstBox = firstLineBox();
+
+    SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0;
+    RenderObject* object = rootBox ? rootBox->object() : 0;
+
+    if (!object)
+        return;
+
+    int xRef = object->xPos() + xPos();
+    int yRef = object->yPos() + yPos();
+ 
+    for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
+        FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height());
+        rects.append(enclosingIntRect(absoluteTransform().mapRect(rect)));
+    }
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGTSpan.h b/WebCore/rendering/RenderSVGTSpan.h
new file mode 100644
index 0000000..cabf2ef
--- /dev/null
+++ b/WebCore/rendering/RenderSVGTSpan.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <[email protected]>
+ *           (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderSVGTSpan_h
+#define RenderSVGTSpan_h
+
+#if ENABLE(SVG)
+#include "RenderSVGInline.h"
+
+namespace WebCore {
+class RenderSVGTSpan : public RenderSVGInline {
+public:
+    RenderSVGTSpan(Node*);
+    virtual const char* renderName() const { return "RenderSVGTSpan"; }
+    virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel = true);
+};
+}
+
+#endif // ENABLE(SVG)
+#endif // !RenderSVGTSpan_h
diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp
new file mode 100644
index 0000000..2f0e2d6
--- /dev/null
+++ b/WebCore/rendering/RenderSVGText.cpp
@@ -0,0 +1,217 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *               2006 Alexander Kellett <[email protected]>
+ *               2006 Oliver Hunt <[email protected]>
+ *               2007 Nikolas Zimmermann <[email protected]>
+ *               2008 Rob Buis <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGText.h"
+
+#include "FloatConversion.h"
+#include "GraphicsContext.h"
+#include "PointerEventsHitRules.h"
+#include "RenderSVGRoot.h"
+#include "SimpleFontData.h"
+#include "SVGLengthList.h"
+#include "SVGResourceFilter.h"
+#include "SVGRootInlineBox.h"
+#include "SVGTextElement.h"
+#include "SVGTransformList.h"
+#include "SVGURIReference.h"
+
+namespace WebCore {
+
+RenderSVGText::RenderSVGText(SVGTextElement* node) 
+    : RenderSVGBlock(node)
+{
+}
+
+IntRect RenderSVGText::absoluteClippedOverflowRect()
+{
+    FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true));
+
+#if ENABLE(SVG_FILTERS)
+    // Filters can expand the bounding box
+    SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter());
+    if (filter)
+        repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect));
+#endif
+
+    if (!repaintRect.isEmpty())
+        repaintRect.inflate(1); // inflate 1 pixel for antialiasing
+
+    return enclosingIntRect(repaintRect);
+}
+
+bool RenderSVGText::requiresLayer()
+{
+    return false;
+}
+
+bool RenderSVGText::calculateLocalTransform()
+{
+    AffineTransform oldTransform = m_localTransform;
+    m_localTransform = static_cast<SVGTextElement*>(element())->animatedLocalTransform();
+    return (oldTransform != m_localTransform);
+}
+
+void RenderSVGText::layout()
+{
+    ASSERT(needsLayout());
+    
+    // FIXME: This is a hack to avoid the RenderBlock::layout() partial repainting code which is not (yet) SVG aware
+    setNeedsLayout(true);
+
+    IntRect oldBounds;
+    IntRect oldOutlineBox;
+    bool checkForRepaint = checkForRepaintDuringLayout();
+    if (checkForRepaint) {
+        oldBounds = m_absoluteBounds;
+        oldOutlineBox = absoluteOutlineBox();
+    }
+
+    // Best guess for a relative starting point
+    SVGTextElement* text = static_cast<SVGTextElement*>(element());
+    int xOffset = (int)(text->x()->getFirst().value(text));
+    int yOffset = (int)(text->y()->getFirst().value(text));
+    setPos(xOffset, yOffset);
+    
+    calculateLocalTransform();
+
+    RenderBlock::layout();
+
+    m_absoluteBounds = absoluteClippedOverflowRect();
+
+    bool repainted = false;
+    if (checkForRepaint)
+        repainted = repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+    
+    setNeedsLayout(false);
+}
+
+InlineBox* RenderSVGText::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun)
+{
+    ASSERT(!isInlineFlow());
+    InlineFlowBox* flowBox = new (renderArena()) SVGRootInlineBox(this);
+    
+    if (!m_firstLineBox)
+        m_firstLineBox = m_lastLineBox = flowBox;
+    else {
+        m_lastLineBox->setNextLineBox(flowBox);
+        flowBox->setPreviousLineBox(m_lastLineBox);
+        m_lastLineBox = flowBox;
+    }
+    
+    return flowBox;
+}
+
+bool RenderSVGText::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
+{
+    PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, style()->svgStyle()->pointerEvents());
+    bool isVisible = (style()->visibility() == VISIBLE);
+    if (isVisible || !hitRules.requireVisible) {
+        if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke))
+            || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill))) {
+            AffineTransform totalTransform = absoluteTransform();
+            double localX, localY;
+            totalTransform.inverse().map(_x, _y, &localX, &localY);
+            FloatPoint hitPoint(_x, _y);
+            return RenderBlock::nodeAtPoint(request, result, (int)localX, (int)localY, _tx, _ty, hitTestAction);
+        }
+    }
+
+    return false;
+}
+
+void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+{
+    RenderSVGRoot* root = findSVGRootObject(parent());
+    if (!root)
+        return;
+
+    int x, y;
+    absolutePosition(x, y);
+
+    AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
+ 
+    // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard
+    // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
+    for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
+        ASSERT(runBox->isInlineFlowBox());
+
+        InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
+        for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) {
+            FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height());
+            boxRect.move(narrowPrecisionToFloat(x - htmlParentCtm.e()), narrowPrecisionToFloat(y - htmlParentCtm.f()));
+            rects.append(enclosingIntRect(absoluteTransform().mapRect(boxRect)));
+        }
+    }
+}
+
+void RenderSVGText::paint(PaintInfo& paintInfo, int, int)
+{   
+    RenderObject::PaintInfo pi(paintInfo);
+    pi.rect = absoluteTransform().inverse().mapRect(pi.rect);
+    RenderBlock::paint(pi, 0, 0);
+}
+
+FloatRect RenderSVGText::relativeBBox(bool includeStroke) const
+{
+    FloatRect repaintRect;
+
+    for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
+        ASSERT(runBox->isInlineFlowBox());
+
+        InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
+        for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine())
+            repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height()));
+    }
+
+    // SVG needs to include the strokeWidth(), not the textStrokeWidth().
+    if (includeStroke && style()->svgStyle()->hasStroke()) {
+        float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0f);
+
+#if ENABLE(SVG_FONTS)
+        const Font& font = style()->font();
+        if (font.primaryFont()->isSVGFont()) {
+            float scale = font.unitsPerEm() > 0 ? font.size() / font.unitsPerEm() : 0.0f;
+
+            if (scale != 0.0f)
+                strokeWidth /= scale;
+        }
+#endif
+
+        repaintRect.inflate(strokeWidth);
+    }
+
+    repaintRect.move(xPos(), yPos());
+    return repaintRect;
+}
+
+}
+
+#endif // ENABLE(SVG)
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderSVGText.h b/WebCore/rendering/RenderSVGText.h
new file mode 100644
index 0000000..ceadc82
--- /dev/null
+++ b/WebCore/rendering/RenderSVGText.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *           (C) 2007 Nikolas Zimmermann <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderSVGText_h
+#define RenderSVGText_h
+
+#if ENABLE(SVG)
+
+#include "AffineTransform.h"
+#include "RenderSVGBlock.h"
+
+namespace WebCore {
+
+class SVGTextElement;
+
+class RenderSVGText : public RenderSVGBlock {
+public:
+    RenderSVGText(SVGTextElement* node);
+
+    virtual const char* renderName() const { return "RenderSVGText"; }
+    
+    virtual bool isSVGText() const { return true; }
+    
+    bool calculateLocalTransform();
+    virtual AffineTransform localTransform() const { return m_localTransform; }
+    
+    virtual void paint(PaintInfo&, int tx, int ty);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+    
+    virtual bool requiresLayer();
+    virtual void layout();
+    
+    virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
+    virtual IntRect absoluteClippedOverflowRect();
+    virtual FloatRect relativeBBox(bool includeStroke = true) const;
+    
+    virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun = false);
+
+private:
+    AffineTransform m_localTransform;
+    IntRect m_absoluteBounds;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderSVGTextPath.cpp b/WebCore/rendering/RenderSVGTextPath.cpp
new file mode 100644
index 0000000..53aa937
--- /dev/null
+++ b/WebCore/rendering/RenderSVGTextPath.cpp
@@ -0,0 +1,101 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2007 Nikolas Zimmermann <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGTextPath.h"
+
+#include "FloatRect.h"
+#include "SVGInlineTextBox.h"
+#include "SVGPathElement.h"
+#include "SVGRootInlineBox.h"
+#include "SVGTextPathElement.h"
+#include "SVGTransformList.h"
+
+namespace WebCore {
+
+RenderSVGTextPath::RenderSVGTextPath(Node* n)
+    : RenderSVGInline(n)
+    , m_startOffset(0.0f)
+    , m_exactAlignment(true)
+    , m_stretchMethod(false)
+{
+}
+
+Path RenderSVGTextPath::layoutPath() const
+{
+    SVGTextPathElement* textPathElement = static_cast<SVGTextPathElement*>(element());
+        String pathId = SVGURIReference::getTarget(textPathElement->href());
+    Element* targetElement = textPathElement->document()->getElementById(pathId);    
+    if (!targetElement || !targetElement->hasTagName(SVGNames::pathTag))
+        return Path();
+    
+    SVGPathElement* pathElement = static_cast<SVGPathElement*>(targetElement);
+    
+    Path pathData = pathElement->toPathData();
+    // Spec:  The transform attribute on the referenced 'path' element represents a
+    // supplemental transformation relative to the current user coordinate system for
+    // the current 'text' element, including any adjustments to the current user coordinate
+    // system due to a possible transform attribute on the current 'text' element.
+    // http://www.w3.org/TR/SVG/text.html#TextPathElement
+    pathData.transform(pathElement->animatedLocalTransform());
+    return pathData;
+}
+
+float RenderSVGTextPath::startOffset() const
+{
+    return static_cast<SVGTextPathElement*>(element())->startOffset().valueAsPercentage();
+}
+
+bool RenderSVGTextPath::exactAlignment() const
+{
+    return static_cast<SVGTextPathElement*>(element())->spacing() == SVG_TEXTPATH_SPACINGTYPE_EXACT;
+}
+
+bool RenderSVGTextPath::stretchMethod() const
+{
+    return static_cast<SVGTextPathElement*>(element())->method() == SVG_TEXTPATH_METHODTYPE_STRETCH;
+}
+
+void RenderSVGTextPath::absoluteRects(Vector<IntRect>& rects, int, int)
+{
+    InlineRunBox* firstBox = firstLineBox();
+
+    SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0;
+    RenderObject* object = rootBox ? rootBox->object() : 0;
+
+    if (!object)
+        return;
+
+    int xRef = object->xPos() + xPos();
+    int yRef = object->yPos() + yPos();
+
+    for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
+        FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height());
+        rects.append(enclosingIntRect(absoluteTransform().mapRect(rect)));
+    }
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGTextPath.h b/WebCore/rendering/RenderSVGTextPath.h
new file mode 100644
index 0000000..2a66f65
--- /dev/null
+++ b/WebCore/rendering/RenderSVGTextPath.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2007 Nikolas Zimmermann <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderSVGTextPath_h
+#define RenderSVGTextPath_h
+
+#if ENABLE(SVG)
+#include "RenderSVGInline.h"
+
+namespace WebCore {
+
+    class RenderSVGTextPath : public RenderSVGInline {
+    public:
+        RenderSVGTextPath(Node*);
+
+        Path layoutPath() const;
+        float startOffset() const;
+        bool exactAlignment() const;
+        bool stretchMethod() const;
+
+        virtual const char* renderName() const { return "RenderSVGTextPath"; }
+        virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty);
+
+    private:
+        float m_startOffset;
+
+        bool m_exactAlignment : 1;
+        bool m_stretchMethod : 1;
+
+        Path m_layoutPath;
+    };
+}
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGTextPath_h
diff --git a/WebCore/rendering/RenderSVGTransformableContainer.cpp b/WebCore/rendering/RenderSVGTransformableContainer.cpp
new file mode 100644
index 0000000..98eaab0
--- /dev/null
+++ b/WebCore/rendering/RenderSVGTransformableContainer.cpp
@@ -0,0 +1,47 @@
+/*
+    Copyright (C) 2004, 2005 Nikolas Zimmermann <[email protected]>
+    2004, 2005, 2006 Rob Buis <[email protected]>
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#if ENABLE(SVG)
+
+#include "RenderSVGTransformableContainer.h"
+
+#include "SVGStyledTransformableElement.h"
+#include "SVGTransformList.h"
+
+namespace WebCore {
+    
+RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGStyledTransformableElement* node)
+    : RenderSVGContainer(node)
+{
+}
+
+bool RenderSVGTransformableContainer::calculateLocalTransform()
+{
+    AffineTransform oldTransform = m_localTransform;
+    m_localTransform = static_cast<SVGStyledTransformableElement*>(element())->animatedLocalTransform();
+    return (m_localTransform != oldTransform);
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGTransformableContainer.h b/WebCore/rendering/RenderSVGTransformableContainer.h
new file mode 100644
index 0000000..897cc63
--- /dev/null
+++ b/WebCore/rendering/RenderSVGTransformableContainer.h
@@ -0,0 +1,39 @@
+/*
+    Copyright (C) 2007 Eric Seidel <[email protected]
+      
+    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, or (at your option) any later version.
+
+    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
+    aint with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef RenderSVGTransformableContainer_h
+#define RenderSVGTransformableContainer_h
+
+#if ENABLE(SVG)
+#include "RenderSVGContainer.h"
+
+namespace WebCore {
+    
+    class SVGStyledTransformableElement;
+    class RenderSVGTransformableContainer : public RenderSVGContainer {
+    public:
+        RenderSVGTransformableContainer(SVGStyledTransformableElement*);
+        
+        virtual bool calculateLocalTransform();
+    };
+}
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGTransformableContainer_h
diff --git a/WebCore/rendering/RenderSVGViewportContainer.cpp b/WebCore/rendering/RenderSVGViewportContainer.cpp
new file mode 100644
index 0000000..b6d527b
--- /dev/null
+++ b/WebCore/rendering/RenderSVGViewportContainer.cpp
@@ -0,0 +1,198 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005, 2007 Rob Buis <[email protected]>
+                  2007 Eric Seidel <[email protected]>
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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
+    aint with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGViewportContainer.h"
+
+#include "GraphicsContext.h"
+
+#include "RenderView.h"
+#include "SVGMarkerElement.h"
+#include "SVGSVGElement.h"
+
+namespace WebCore {
+
+RenderSVGViewportContainer::RenderSVGViewportContainer(SVGStyledElement* node)
+    : RenderSVGContainer(node)
+{
+    setReplaced(true);
+}
+
+RenderSVGViewportContainer::~RenderSVGViewportContainer()
+{
+}
+
+void RenderSVGViewportContainer::layout()
+{
+    ASSERT(needsLayout());
+    
+    calcViewport();
+    
+    // Arbitrary affine transforms are incompatible with LayoutState.
+    view()->disableLayoutState();
+    
+    IntRect oldBounds = m_absoluteBounds;
+    IntRect oldOutlineBox;
+    bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
+    if (checkForRepaint)
+        oldOutlineBox = absoluteOutlineBox();
+
+    calcBounds();    
+    
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (selfNeedsLayout())
+            child->setNeedsLayout(true);
+        
+        child->layoutIfNeeded();
+        ASSERT(!child->needsLayout());
+    }
+    
+    if (checkForRepaint)
+        repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+    
+    view()->enableLayoutState();
+    setNeedsLayout(false);
+}
+
+void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, int parentX, int parentY)
+{
+    // A value of zero disables rendering of the element. 
+    if (!viewport().isEmpty() && (viewport().width() <= 0. || viewport().height() <= 0.))
+        return;
+
+    RenderSVGContainer::paint(paintInfo, parentX, parentY);
+}
+
+void RenderSVGViewportContainer::applyContentTransforms(PaintInfo& paintInfo)
+{
+    if (!viewport().isEmpty()) {
+        if (style()->overflowX() != OVISIBLE)
+            paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping
+        
+        paintInfo.context->concatCTM(AffineTransform().translate(viewport().x(), viewport().y()));
+    }
+
+    RenderSVGContainer::applyContentTransforms(paintInfo);
+}
+
+void RenderSVGViewportContainer::applyAdditionalTransforms(PaintInfo& paintInfo)
+{
+    paintInfo.context->concatCTM(viewportTransform());
+    RenderSVGContainer::applyAdditionalTransforms(paintInfo);
+}
+
+FloatRect RenderSVGViewportContainer::viewport() const
+{
+    return m_viewport;
+}
+
+void RenderSVGViewportContainer::calcViewport()
+{
+    SVGElement* svgelem = static_cast<SVGElement*>(element());
+    if (svgelem->hasTagName(SVGNames::svgTag)) {
+        SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
+
+        if (!selfNeedsLayout() && !svg->hasRelativeValues())
+            return;
+
+        float x = svg->x().value(svg);
+        float y = svg->y().value(svg);
+        float w = svg->width().value(svg);
+        float h = svg->height().value(svg);
+        m_viewport = FloatRect(x, y, w, h);
+    } else if (svgelem->hasTagName(SVGNames::markerTag)) {
+        if (!selfNeedsLayout())
+            return;
+
+        SVGMarkerElement* svg = static_cast<SVGMarkerElement*>(element());
+        float w = svg->markerWidth().value(svg);
+        float h = svg->markerHeight().value(svg);
+        m_viewport = FloatRect(0, 0, w, h);
+    }
+}
+
+AffineTransform RenderSVGViewportContainer::viewportTransform() const
+{
+    if (element()->hasTagName(SVGNames::svgTag)) {
+        SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
+        return svg->viewBoxToViewTransform(viewport().width(), viewport().height());
+    } else if (element()->hasTagName(SVGNames::markerTag)) {
+        SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(element());
+        return marker->viewBoxToViewTransform(viewport().width(), viewport().height());
+    }
+ 
+     return AffineTransform();
+}
+
+AffineTransform RenderSVGViewportContainer::absoluteTransform() const
+{
+    AffineTransform ctm = RenderObject::absoluteTransform();
+    ctm.translate(viewport().x(), viewport().y());
+    return viewportTransform() * ctm;
+}
+
+bool RenderSVGViewportContainer::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
+{
+    if (!viewport().isEmpty()
+        && style()->overflowX() == OHIDDEN
+        && style()->overflowY() == OHIDDEN) {
+        // Check if we need to do anything at all.
+        IntRect overflowBox = overflowRect(false);
+        overflowBox.move(_tx, _ty);
+        AffineTransform ctm = RenderObject::absoluteTransform();
+        ctm.translate(viewport().x(), viewport().y());
+        double localX, localY;
+        ctm.inverse().map(_x - _tx, _y - _ty, &localX, &localY);
+        if (!overflowBox.contains((int)localX, (int)localY))
+            return false;
+    }
+
+    int sx = 0;
+    int sy = 0;
+
+    // Respect parent translation offset for non-outermost <svg> elements.
+    // Outermost <svg> element is handled by RenderSVGRoot.
+    if (element()->hasTagName(SVGNames::svgTag)) {
+        sx = _tx;
+        sy = _ty;
+    }
+
+    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+        if (child->nodeAtPoint(request, result, _x - sx, _y - sy, _tx, _ty, hitTestAction)) {
+            updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
+            return true;
+        }
+    }
+
+    // Spec: Only graphical elements can be targeted by the mouse, period.
+    // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
+    return false;
+}
+
+}
+
+#endif // ENABLE(SVG)
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderSVGViewportContainer.h b/WebCore/rendering/RenderSVGViewportContainer.h
new file mode 100644
index 0000000..23a885f
--- /dev/null
+++ b/WebCore/rendering/RenderSVGViewportContainer.h
@@ -0,0 +1,64 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005, 2007 Rob Buis <[email protected]>
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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
+    aint with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RenderSVGViewportContainer_h
+#define RenderSVGViewportContainer_h
+
+#if ENABLE(SVG)
+
+#include "RenderSVGContainer.h"
+
+namespace WebCore {
+
+class RenderSVGViewportContainer : public RenderSVGContainer {
+public:
+    RenderSVGViewportContainer(SVGStyledElement*);
+    ~RenderSVGViewportContainer();
+
+    virtual bool isSVGContainer() const { return true; }
+    virtual const char* renderName() const { return "RenderSVGViewportContainer"; }
+
+    virtual void layout();
+    virtual void paint(PaintInfo&, int parentX, int parentY);
+
+    virtual AffineTransform absoluteTransform() const;
+    virtual AffineTransform viewportTransform() const;
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+    FloatRect viewport() const;
+
+private:
+    void calcViewport(); 
+
+    virtual void applyContentTransforms(PaintInfo&);
+    virtual void applyAdditionalTransforms(PaintInfo&);
+    
+    FloatRect m_viewport;
+};
+  
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGViewportContainer_h
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderScrollbar.cpp b/WebCore/rendering/RenderScrollbar.cpp
new file mode 100644
index 0000000..b7045d6
--- /dev/null
+++ b/WebCore/rendering/RenderScrollbar.cpp
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "RenderScrollbar.h"
+#include "RenderScrollbarPart.h"
+#include "RenderScrollbarTheme.h"
+
+namespace WebCore {
+
+PassRefPtr<Scrollbar> RenderScrollbar::createCustomScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, RenderObject* renderer)
+{
+    return adoptRef(new RenderScrollbar(client, orientation, renderer));
+}
+
+RenderScrollbar::RenderScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, RenderObject* renderer)
+    : Scrollbar(client, orientation, RegularScrollbar, RenderScrollbarTheme::renderScrollbarTheme())
+    , m_owner(renderer)
+{
+}
+
+RenderScrollbar::~RenderScrollbar()
+{
+    ASSERT(m_parts.isEmpty());
+}
+
+void RenderScrollbar::setParent(ScrollView* parent)
+{
+    Scrollbar::setParent(parent);
+    if (!parent) {
+        // Destroy all of the scrollbar's RenderObjects.
+        updateScrollbarParts(true);
+    }
+}
+
+void RenderScrollbar::setEnabled(bool e)
+{
+    bool wasEnabled = enabled();
+    Scrollbar::setEnabled(e);
+    if (wasEnabled != e)
+        updateScrollbarParts();
+}
+
+void RenderScrollbar::styleChanged()
+{
+    updateScrollbarParts();
+}
+
+void RenderScrollbar::paint(GraphicsContext* context, const IntRect& damageRect)
+{
+    if (context->updatingControlTints()) {
+        updateScrollbarParts();
+        return;
+    }
+    Scrollbar::paint(context, damageRect);
+}
+
+void RenderScrollbar::setHoveredPart(ScrollbarPart part)
+{
+    if (part == m_hoveredPart)
+        return;
+
+    ScrollbarPart oldPart = m_hoveredPart;
+    m_hoveredPart = part;
+
+    updateScrollbarPart(oldPart);
+    updateScrollbarPart(m_hoveredPart);
+
+    updateScrollbarPart(ScrollbarBGPart);
+    updateScrollbarPart(TrackBGPart);
+}
+
+void RenderScrollbar::setPressedPart(ScrollbarPart part)
+{
+    ScrollbarPart oldPart = m_pressedPart;
+    Scrollbar::setPressedPart(part);
+    
+    updateScrollbarPart(oldPart);
+    updateScrollbarPart(part);
+    
+    updateScrollbarPart(ScrollbarBGPart);
+    updateScrollbarPart(TrackBGPart);
+}
+
+static ScrollbarPart s_styleResolvePart;
+static RenderScrollbar* s_styleResolveScrollbar;
+
+RenderScrollbar* RenderScrollbar::scrollbarForStyleResolve()
+{
+    return s_styleResolveScrollbar;
+}
+
+ScrollbarPart RenderScrollbar::partForStyleResolve()
+{
+    return s_styleResolvePart;
+}
+
+PassRefPtr<RenderStyle> RenderScrollbar::getScrollbarPseudoStyle(ScrollbarPart partType, RenderStyle::PseudoId pseudoId)
+{
+    s_styleResolvePart = partType;
+    s_styleResolveScrollbar = this;
+    RefPtr<RenderStyle> result = m_owner->getUncachedPseudoStyle(pseudoId, m_owner->style());
+    s_styleResolvePart = NoPart;
+    s_styleResolveScrollbar = 0;
+    return result;
+}
+
+void RenderScrollbar::updateScrollbarParts(bool destroy)
+{
+    updateScrollbarPart(ScrollbarBGPart, destroy);
+    updateScrollbarPart(BackButtonStartPart, destroy);
+    updateScrollbarPart(ForwardButtonStartPart, destroy);
+    updateScrollbarPart(BackTrackPart, destroy);
+    updateScrollbarPart(ThumbPart, destroy);
+    updateScrollbarPart(ForwardTrackPart, destroy);
+    updateScrollbarPart(BackButtonEndPart, destroy);
+    updateScrollbarPart(ForwardButtonEndPart, destroy);
+    updateScrollbarPart(TrackBGPart, destroy);
+    
+    if (destroy)
+        return;
+
+    // See if the scrollbar's thickness changed.  If so, we need to mark our owning object as needing a layout.
+    bool isHorizontal = orientation() == HorizontalScrollbar;    
+    int oldThickness = isHorizontal ? height() : width();
+    int newThickness = 0;
+    RenderScrollbarPart* part = m_parts.get(ScrollbarBGPart);
+    if (part) {
+        part->layout();
+        newThickness = isHorizontal ? part->height() : part->width();
+    }
+    
+    if (newThickness != oldThickness) {
+        setFrameRect(IntRect(x(), y(), isHorizontal ? width() : newThickness, isHorizontal ? newThickness : height()));
+        m_owner->setChildNeedsLayout(true);
+    }
+}
+
+static RenderStyle::PseudoId pseudoForScrollbarPart(ScrollbarPart part)
+{
+    switch (part) {
+        case BackButtonStartPart:
+        case ForwardButtonStartPart:
+        case BackButtonEndPart:
+        case ForwardButtonEndPart:
+            return RenderStyle::SCROLLBAR_BUTTON;
+        case BackTrackPart:
+        case ForwardTrackPart:
+            return RenderStyle::SCROLLBAR_TRACK_PIECE;
+        case ThumbPart:
+            return RenderStyle::SCROLLBAR_THUMB;
+        case TrackBGPart:
+            return RenderStyle::SCROLLBAR_TRACK;
+        default:
+            return RenderStyle::SCROLLBAR;
+    }
+}
+
+void RenderScrollbar::updateScrollbarPart(ScrollbarPart partType, bool destroy)
+{
+    if (partType == NoPart)
+        return;
+
+    RefPtr<RenderStyle> partStyle = !destroy ? getScrollbarPseudoStyle(partType,  pseudoForScrollbarPart(partType)) : 0;
+    
+    bool needRenderer = !destroy && partStyle && partStyle->display() != NONE && partStyle->visibility() == VISIBLE;
+    
+    if (needRenderer && partStyle->display() != BLOCK) {
+        // See if we are a button that should not be visible according to OS settings.
+        ScrollbarButtonsPlacement buttonsPlacement = theme()->buttonsPlacement();
+        switch (partType) {
+            case BackButtonStartPart:
+                needRenderer = (buttonsPlacement == ScrollbarButtonsSingle || buttonsPlacement == ScrollbarButtonsDoubleStart ||
+                                buttonsPlacement == ScrollbarButtonsDoubleBoth);
+                break;
+            case ForwardButtonStartPart:
+                needRenderer = (buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth);
+                break;
+            case BackButtonEndPart:
+                needRenderer = (buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth);
+                break;
+            case ForwardButtonEndPart:
+                needRenderer = (buttonsPlacement == ScrollbarButtonsSingle || buttonsPlacement == ScrollbarButtonsDoubleEnd ||
+                                buttonsPlacement == ScrollbarButtonsDoubleBoth);
+                break;
+            default:
+                break;
+        }
+    }
+    
+    RenderScrollbarPart* partRenderer = m_parts.get(partType);
+    if (!partRenderer && needRenderer) {
+        partRenderer = new (m_owner->renderArena()) RenderScrollbarPart(m_owner->document(), this, partType);
+        m_parts.set(partType, partRenderer);
+    } else if (partRenderer && !needRenderer) {
+        m_parts.remove(partType);
+        partRenderer->destroy();
+        partRenderer = 0;
+    }
+    
+    if (partRenderer)
+        partRenderer->setStyle(partStyle.release());
+}
+
+void RenderScrollbar::paintPart(GraphicsContext* graphicsContext, ScrollbarPart partType, const IntRect& rect)
+{
+    RenderScrollbarPart* partRenderer = m_parts.get(partType);
+    if (!partRenderer)
+        return;
+    partRenderer->paintIntoRect(graphicsContext, x(), y(), rect);
+}
+
+IntRect RenderScrollbar::buttonRect(ScrollbarPart partType)
+{
+    RenderScrollbarPart* partRenderer = m_parts.get(partType);
+    if (!partRenderer)
+        return IntRect();
+        
+    partRenderer->layout();
+    
+    bool isHorizontal = orientation() == HorizontalScrollbar;
+    if (partType == BackButtonStartPart)
+        return IntRect(x(), y(), isHorizontal ? partRenderer->width() : width(), isHorizontal ? height() : partRenderer->height());
+    if (partType == ForwardButtonEndPart)
+        return IntRect(isHorizontal ? x() + width() - partRenderer->width() : x(),
+        
+                       isHorizontal ? y() : y() + height() - partRenderer->height(),
+                       isHorizontal ? partRenderer->width() : width(),
+                       isHorizontal ? height() : partRenderer->height());
+    
+    if (partType == ForwardButtonStartPart) {
+        IntRect previousButton = buttonRect(BackButtonStartPart);
+        return IntRect(isHorizontal ? x() + previousButton.width() : x(),
+                       isHorizontal ? y() : y() + previousButton.height(),
+                       isHorizontal ? partRenderer->width() : width(),
+                       isHorizontal ? height() : partRenderer->height());
+    }
+    
+    IntRect followingButton = buttonRect(ForwardButtonEndPart);
+    return IntRect(isHorizontal ? x() + width() - followingButton.width() - partRenderer->width() : x(),
+                   isHorizontal ? y() : y() + height() - followingButton.height() - partRenderer->height(),
+                   isHorizontal ? partRenderer->width() : width(),
+                   isHorizontal ? height() : partRenderer->height());
+}
+
+IntRect RenderScrollbar::trackRect(int startLength, int endLength)
+{
+    RenderScrollbarPart* part = m_parts.get(TrackBGPart);
+    if (part)
+        part->layout();
+
+    if (orientation() == HorizontalScrollbar) {
+        int marginLeft = part ? part->marginLeft() : 0;
+        int marginRight = part ? part->marginRight() : 0;
+        startLength += marginLeft;
+        endLength += marginRight;
+        int totalLength = startLength + endLength;
+        return IntRect(x() + startLength, y(), width() - totalLength, height());
+    }
+    
+    int marginTop = part ? part->marginTop() : 0;
+    int marginBottom = part ? part->marginBottom() : 0;
+    startLength += marginTop;
+    endLength += marginBottom;
+    int totalLength = startLength + endLength;
+
+    return IntRect(x(), y() + startLength, width(), height() - totalLength);
+}
+
+IntRect RenderScrollbar::trackPieceRectWithMargins(ScrollbarPart partType, const IntRect& oldRect)
+{
+    RenderScrollbarPart* partRenderer = m_parts.get(partType);
+    if (!partRenderer)
+        return oldRect;
+    
+    partRenderer->layout();
+    
+    IntRect rect = oldRect;
+    if (orientation() == HorizontalScrollbar) {
+        rect.setX(rect.x() + partRenderer->marginLeft());
+        rect.setWidth(rect.width() - (partRenderer->marginLeft() + partRenderer->marginRight()));
+    } else {
+        rect.setY(rect.y() + partRenderer->marginTop());
+        rect.setHeight(rect.height() - (partRenderer->marginTop() + partRenderer->marginBottom()));
+    }
+    return rect;
+}
+
+int RenderScrollbar::minimumThumbLength()
+{
+    RenderScrollbarPart* partRenderer = m_parts.get(ThumbPart);
+    if (!partRenderer)
+        return 0;    
+    partRenderer->layout();
+    return orientation() == HorizontalScrollbar ? partRenderer->width() : partRenderer->height();
+}
+
+}
diff --git a/WebCore/rendering/RenderScrollbar.h b/WebCore/rendering/RenderScrollbar.h
new file mode 100644
index 0000000..ad97001
--- /dev/null
+++ b/WebCore/rendering/RenderScrollbar.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RenderScrollbar_h
+#define RenderScrollbar_h
+
+#include "Scrollbar.h"
+#include "RenderStyle.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class RenderObject;
+class RenderScrollbarPart;
+class RenderStyle;
+
+class RenderScrollbar : public Scrollbar {
+protected:
+    RenderScrollbar(ScrollbarClient*, ScrollbarOrientation, RenderObject*);
+
+public:
+    friend class Scrollbar;
+    static PassRefPtr<Scrollbar> createCustomScrollbar(ScrollbarClient*, ScrollbarOrientation, RenderObject*);
+    virtual ~RenderScrollbar();
+
+    virtual void setParent(ScrollView*);
+    virtual void setEnabled(bool);
+
+    virtual void paint(GraphicsContext*, const IntRect& damageRect);
+
+    virtual void setHoveredPart(ScrollbarPart);
+    virtual void setPressedPart(ScrollbarPart);
+
+    void updateScrollbarParts(bool destroy = false);
+
+    static ScrollbarPart partForStyleResolve();
+    static RenderScrollbar* scrollbarForStyleResolve();
+
+    virtual void styleChanged();
+
+    RenderObject* owningRenderer() const { return m_owner; }
+
+    void paintPart(GraphicsContext*, ScrollbarPart, const IntRect&);
+
+    IntRect buttonRect(ScrollbarPart);
+    IntRect trackRect(int startLength, int endLength);
+    IntRect trackPieceRectWithMargins(ScrollbarPart, const IntRect&);
+
+    int minimumThumbLength();
+
+private:
+    PassRefPtr<RenderStyle> getScrollbarPseudoStyle(ScrollbarPart, RenderStyle::PseudoId);
+    void updateScrollbarPart(ScrollbarPart, bool destroy = false);
+
+    RenderObject* m_owner;
+    HashMap<unsigned, RenderScrollbarPart*> m_parts;
+};
+
+} // namespace WebCore
+
+#endif // RenderScrollbar_h
diff --git a/WebCore/rendering/RenderScrollbarPart.cpp b/WebCore/rendering/RenderScrollbarPart.cpp
new file mode 100644
index 0000000..d5e72e9
--- /dev/null
+++ b/WebCore/rendering/RenderScrollbarPart.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "RenderScrollbarPart.h"
+#include "RenderScrollbar.h"
+#include "RenderScrollbarTheme.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderScrollbarPart::RenderScrollbarPart(Node* node, RenderScrollbar* scrollbar, ScrollbarPart part)
+    : RenderBlock(node)
+    , m_scrollbar(scrollbar)
+    , m_part(part)
+{
+}
+
+RenderScrollbarPart::~RenderScrollbarPart()
+{
+}
+
+void RenderScrollbarPart::layout()
+{
+    setPos(0, 0); // We don't worry about positioning ourselves.  We're just determining our minimum width/height.
+    if (m_scrollbar->orientation() == HorizontalScrollbar)
+        layoutHorizontalPart();
+    else
+        layoutVerticalPart();
+
+    m_overflowWidth = max(m_width, m_overflowWidth);
+    m_overflowHeight = max(m_height, m_overflowHeight);
+    
+    setNeedsLayout(false);
+}
+
+void RenderScrollbarPart::layoutHorizontalPart()
+{
+    if (m_part == ScrollbarBGPart) {
+        m_width = m_scrollbar->width();
+        computeScrollbarHeight();
+    } else {
+        computeScrollbarWidth();
+        m_height = m_scrollbar->height();
+    }
+}
+
+void RenderScrollbarPart::layoutVerticalPart()
+{
+    if (m_part == ScrollbarBGPart) {
+        computeScrollbarWidth();
+        m_height = m_scrollbar->height();
+    } else {
+        m_width = m_scrollbar->width();
+        computeScrollbarHeight();
+    } 
+}
+
+static int calcScrollbarThicknessUsing(const Length& l, int containingLength)
+{
+    if (l.isIntrinsicOrAuto())
+        return ScrollbarTheme::nativeTheme()->scrollbarThickness();
+    return l.calcMinValue(containingLength);
+}
+
+void RenderScrollbarPart::computeScrollbarWidth()
+{
+    int visibleSize = m_scrollbar->owningRenderer()->width() - m_scrollbar->owningRenderer()->borderLeft() - m_scrollbar->owningRenderer()->borderRight();
+    int width = calcScrollbarThicknessUsing(style()->width(), visibleSize);
+    int minWidth = calcScrollbarThicknessUsing(style()->minWidth(), visibleSize);
+    int maxWidth = style()->maxWidth().isUndefined() ? width : calcScrollbarThicknessUsing(style()->maxWidth(), visibleSize);
+    m_width = max(minWidth, min(maxWidth, width));
+    
+    // Buttons and track pieces can all have margins along the axis of the scrollbar. 
+    m_marginLeft = style()->marginLeft().calcMinValue(visibleSize);
+    m_marginRight = style()->marginRight().calcMinValue(visibleSize);
+}
+
+void RenderScrollbarPart::computeScrollbarHeight()
+{
+    int visibleSize = m_scrollbar->owningRenderer()->height() -  m_scrollbar->owningRenderer()->borderTop() - m_scrollbar->owningRenderer()->borderBottom();
+    int height = calcScrollbarThicknessUsing(style()->height(), visibleSize);
+    int minHeight = calcScrollbarThicknessUsing(style()->minHeight(), visibleSize);
+    int maxHeight = style()->maxHeight().isUndefined() ? height : calcScrollbarThicknessUsing(style()->maxHeight(), visibleSize);
+    m_height = max(minHeight, min(maxHeight, height));
+
+    // Buttons and track pieces can all have margins along the axis of the scrollbar. 
+    m_marginTop = style()->marginTop().calcMinValue(visibleSize);
+    m_marginBottom = style()->marginBottom().calcMinValue(visibleSize);
+}
+
+void RenderScrollbarPart::calcPrefWidths()
+{
+    if (!prefWidthsDirty())
+        return;
+    
+    m_minPrefWidth = m_maxPrefWidth = 0;
+
+    setPrefWidthsDirty(false);
+}
+
+void RenderScrollbarPart::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    setInline(false);
+    setPositioned(false);
+    setFloating(false);
+    setHasOverflowClip(false);
+    if (oldStyle && m_scrollbar && m_part != NoPart && diff >= RenderStyle::Repaint)
+        m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
+}
+
+void RenderScrollbarPart::imageChanged(WrappedImagePtr image)
+{
+    if (m_scrollbar && m_part != NoPart)
+        m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
+    else
+        RenderBlock::imageChanged(image);
+}
+
+void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, int tx, int ty, const IntRect& rect)
+{
+    // Make sure our dimensions match the rect.
+    setPos(rect.x() - tx, rect.y() - ty);
+    setWidth(rect.width());
+    setHeight(rect.height());
+    setOverflowWidth(max(rect.width(), overflowWidth()));
+    setOverflowHeight(max(rect.height(), overflowHeight()));
+
+    if (graphicsContext->paintingDisabled())
+        return;
+
+    // Now do the paint.
+    RenderObject::PaintInfo paintInfo(graphicsContext, rect, PaintPhaseBlockBackground, false, 0, 0);
+    paint(paintInfo, tx, ty);
+    paintInfo.phase = PaintPhaseChildBlockBackgrounds;
+    paint(paintInfo, tx, ty);
+    paintInfo.phase = PaintPhaseFloat;
+    paint(paintInfo, tx, ty);
+    paintInfo.phase = PaintPhaseForeground;
+    paint(paintInfo, tx, ty);
+    paintInfo.phase = PaintPhaseOutline;
+    paint(paintInfo, tx, ty);
+}
+
+}
diff --git a/WebCore/rendering/RenderScrollbarPart.h b/WebCore/rendering/RenderScrollbarPart.h
new file mode 100644
index 0000000..fa13774
--- /dev/null
+++ b/WebCore/rendering/RenderScrollbarPart.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RenderScrollbarPart_h
+#define RenderScrollbarPart_h
+
+#include "RenderBlock.h"
+#include "ScrollTypes.h"
+
+namespace WebCore {
+
+class RenderScrollbar;
+
+class RenderScrollbarPart : public RenderBlock {
+public:
+    RenderScrollbarPart(Node*, RenderScrollbar* = 0, ScrollbarPart = NoPart);
+    virtual ~RenderScrollbarPart();
+
+    virtual const char* renderName() const { return "RenderScrollbarPart"; }
+    
+    virtual bool requiresLayer() { return false; }
+
+    virtual void layout();
+    virtual void calcPrefWidths();
+    
+    void paintIntoRect(GraphicsContext*, int tx, int ty, const IntRect&);
+    
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+    virtual void imageChanged(WrappedImagePtr);
+
+private:
+    void layoutHorizontalPart();
+    void layoutVerticalPart();
+
+    void computeScrollbarWidth();
+    void computeScrollbarHeight();
+    
+    RenderScrollbar* m_scrollbar;
+    ScrollbarPart m_part;
+};
+
+} // namespace WebCore
+
+#endif // RenderScrollbarPart_h
diff --git a/WebCore/rendering/RenderScrollbarTheme.cpp b/WebCore/rendering/RenderScrollbarTheme.cpp
new file mode 100644
index 0000000..2b375d0
--- /dev/null
+++ b/WebCore/rendering/RenderScrollbarTheme.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "RenderScrollbarTheme.h"
+#include "RenderScrollbar.h"
+
+namespace WebCore {
+
+RenderScrollbarTheme* RenderScrollbarTheme::renderScrollbarTheme()
+{
+    static RenderScrollbarTheme theme;
+    return &theme;
+}
+
+void RenderScrollbarTheme::buttonSizesAlongTrackAxis(Scrollbar* scrollbar, int& beforeSize, int& afterSize)
+{
+    IntRect firstButton = backButtonRect(scrollbar, BackButtonStartPart);
+    IntRect secondButton = forwardButtonRect(scrollbar, ForwardButtonStartPart);
+    IntRect thirdButton = backButtonRect(scrollbar, BackButtonEndPart);
+    IntRect fourthButton = forwardButtonRect(scrollbar, ForwardButtonEndPart);
+    if (scrollbar->orientation() == HorizontalScrollbar) {
+        beforeSize = firstButton.width() + secondButton.width();
+        afterSize = thirdButton.width() + fourthButton.width();
+    } else {
+        beforeSize = firstButton.height() + secondButton.height();
+        afterSize = thirdButton.height() + fourthButton.height();
+    }
+}
+
+bool RenderScrollbarTheme::hasButtons(Scrollbar* scrollbar)
+{
+    int startSize;
+    int endSize;
+    buttonSizesAlongTrackAxis(scrollbar, startSize, endSize);
+    return (startSize + endSize) <= (scrollbar->orientation() == HorizontalScrollbar ? scrollbar->width() : scrollbar->height());
+}
+
+bool RenderScrollbarTheme::hasThumb(Scrollbar* scrollbar)
+{
+    return trackLength(scrollbar) - thumbLength(scrollbar) >= 0;
+}
+
+int RenderScrollbarTheme::minimumThumbLength(Scrollbar* scrollbar)
+{
+    return static_cast<RenderScrollbar*>(scrollbar)->minimumThumbLength();
+}
+
+IntRect RenderScrollbarTheme::backButtonRect(Scrollbar* scrollbar, ScrollbarPart partType, bool)
+{
+    return static_cast<RenderScrollbar*>(scrollbar)->buttonRect(partType);
+}
+
+IntRect RenderScrollbarTheme::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart partType, bool)
+{
+    return static_cast<RenderScrollbar*>(scrollbar)->buttonRect(partType);
+}
+
+IntRect RenderScrollbarTheme::trackRect(Scrollbar* scrollbar, bool)
+{
+    if (!hasButtons(scrollbar))
+        return scrollbar->frameRect();
+    
+    int startLength;
+    int endLength;
+    buttonSizesAlongTrackAxis(scrollbar, startLength, endLength);
+    
+    return static_cast<RenderScrollbar*>(scrollbar)->trackRect(startLength, endLength);
+}
+
+IntRect RenderScrollbarTheme::constrainTrackRectToTrackPieces(Scrollbar* scrollbar, const IntRect& rect)
+{ 
+    IntRect backRect = static_cast<RenderScrollbar*>(scrollbar)->trackPieceRectWithMargins(BackTrackPart, rect);
+    IntRect forwardRect = static_cast<RenderScrollbar*>(scrollbar)->trackPieceRectWithMargins(ForwardTrackPart, rect);
+    IntRect result = rect;
+    if (scrollbar->orientation() == HorizontalScrollbar) {
+        result.setX(backRect.x());
+        result.setWidth(forwardRect.right() - backRect.x());
+    } else {
+        result.setY(backRect.y());
+        result.setHeight(forwardRect.bottom() - backRect.y());
+    }
+    return result;
+}
+
+void RenderScrollbarTheme::paintScrollCorner(ScrollView*, GraphicsContext* context, const IntRect& cornerRect)
+{
+    // FIXME: Implement.
+    context->fillRect(cornerRect, Color::white);
+}
+
+void RenderScrollbarTheme::paintScrollbarBackground(GraphicsContext* context, Scrollbar* scrollbar)
+{
+    static_cast<RenderScrollbar*>(scrollbar)->paintPart(context, ScrollbarBGPart, scrollbar->frameRect());
+}
+
+void RenderScrollbarTheme::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+{
+    static_cast<RenderScrollbar*>(scrollbar)->paintPart(context, TrackBGPart, rect);
+}
+
+void RenderScrollbarTheme::paintTrackPiece(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
+{
+    static_cast<RenderScrollbar*>(scrollbar)->paintPart(context, part, rect);
+}
+
+void RenderScrollbarTheme::paintButton(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
+{
+    static_cast<RenderScrollbar*>(scrollbar)->paintPart(context, part, rect);
+}
+
+void RenderScrollbarTheme::paintThumb(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+{
+    static_cast<RenderScrollbar*>(scrollbar)->paintPart(context, ThumbPart, rect);
+}
+
+}
diff --git a/WebCore/rendering/RenderScrollbarTheme.h b/WebCore/rendering/RenderScrollbarTheme.h
new file mode 100644
index 0000000..9b8b2c1
--- /dev/null
+++ b/WebCore/rendering/RenderScrollbarTheme.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RenderScrollbarTheme_h
+#define RenderScrollbarTheme_h
+
+#include "ScrollbarThemeComposite.h"
+
+namespace WebCore {
+
+class PlatformMouseEvent;
+class Scrollbar;
+class ScrollView;
+
+class RenderScrollbarTheme : public ScrollbarThemeComposite {
+public:
+    virtual ~RenderScrollbarTheme() {};
+    
+    virtual int scrollbarThickness(ScrollbarControlSize controlSize) { return ScrollbarTheme::nativeTheme()->scrollbarThickness(controlSize); }
+
+    virtual ScrollbarButtonsPlacement buttonsPlacement() const { return ScrollbarTheme::nativeTheme()->buttonsPlacement(); }
+
+    virtual bool supportsControlTints() const { return true; }
+
+    virtual void paintScrollCorner(ScrollView*, GraphicsContext* context, const IntRect& cornerRect);
+
+    virtual bool shouldCenterOnThumb(Scrollbar* scrollbar, const PlatformMouseEvent& event) { return ScrollbarTheme::nativeTheme()->shouldCenterOnThumb(scrollbar, event); }
+    
+    virtual double initialAutoscrollTimerDelay() { return ScrollbarTheme::nativeTheme()->initialAutoscrollTimerDelay(); }
+    virtual double autoscrollTimerDelay() { return ScrollbarTheme::nativeTheme()->autoscrollTimerDelay(); }
+
+    virtual void registerScrollbar(Scrollbar* scrollbar) { return ScrollbarTheme::nativeTheme()->registerScrollbar(scrollbar); }
+    virtual void unregisterScrollbar(Scrollbar* scrollbar) { return ScrollbarTheme::nativeTheme()->unregisterScrollbar(scrollbar); }
+
+    virtual int minimumThumbLength(Scrollbar*);
+
+    void buttonSizesAlongTrackAxis(Scrollbar* scrollbar, int& beforeSize, int& afterSize);
+    
+    static RenderScrollbarTheme* renderScrollbarTheme();
+
+protected:
+    virtual bool hasButtons(Scrollbar*);
+    virtual bool hasThumb(Scrollbar*);
+
+    virtual IntRect backButtonRect(Scrollbar*, ScrollbarPart, bool painting = false);
+    virtual IntRect forwardButtonRect(Scrollbar*, ScrollbarPart, bool painting = false);
+    virtual IntRect trackRect(Scrollbar*, bool painting = false);
+    
+    virtual void paintScrollbarBackground(GraphicsContext*, Scrollbar*);    
+    virtual void paintTrackBackground(GraphicsContext*, Scrollbar*, const IntRect&);
+    virtual void paintTrackPiece(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
+    virtual void paintButton(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
+    virtual void paintThumb(GraphicsContext*, Scrollbar*, const IntRect&);
+
+    virtual IntRect constrainTrackRectToTrackPieces(Scrollbar*, const IntRect&);
+};
+
+} // namespace WebCore
+
+#endif // RenderScrollbarTheme_h
diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp
new file mode 100644
index 0000000..221b0a2
--- /dev/null
+++ b/WebCore/rendering/RenderSlider.cpp
@@ -0,0 +1,414 @@
+/**
+ *
+ * Copyright (C) 2006, 2007, 2008 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderSlider.h"
+
+#include "CSSPropertyNames.h"
+#include "Document.h"
+#include "Event.h"
+#include "EventHandler.h"
+#include "EventNames.h"
+#include "Frame.h"
+#include "HTMLInputElement.h"
+#include "HTMLDivElement.h"
+#include "HTMLNames.h"
+#include "MouseEvent.h"
+#include "RenderTheme.h"
+#include <wtf/MathExtras.h>
+
+#ifdef ANDROID_LAYOUT
+#include "Settings.h"
+#endif
+
+using std::min;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+const int defaultTrackLength = 129;
+
+class HTMLSliderThumbElement : public HTMLDivElement {
+public:
+    HTMLSliderThumbElement(Document*, Node* shadowParent = 0);
+        
+    virtual void defaultEventHandler(Event*);
+    virtual bool isShadowNode() const { return true; }
+    virtual Node* shadowParentNode() { return m_shadowParent; }
+    
+    bool inDragMode() const { return m_inDragMode; }
+private:
+    Node* m_shadowParent;
+    IntPoint m_initialClickPoint;
+    int m_initialPosition;
+    bool m_inDragMode;
+};
+
+HTMLSliderThumbElement::HTMLSliderThumbElement(Document* doc, Node* shadowParent)
+    : HTMLDivElement(doc)
+    , m_shadowParent(shadowParent)
+    , m_initialClickPoint(IntPoint())
+    , m_initialPosition(0)
+    , m_inDragMode(false)
+{
+}
+
+void HTMLSliderThumbElement::defaultEventHandler(Event* event)
+{
+    const AtomicString& eventType = event->type();
+    if (eventType == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
+        MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
+        if (document()->frame() && renderer() && renderer()->parent()
+                && static_cast<RenderSlider*>(renderer()->parent())->mouseEventIsInThumb(mouseEvent)) {
+            // Cache the initial point where the mouse down occurred.
+            m_initialClickPoint = IntPoint(mouseEvent->pageX(), mouseEvent->pageY());
+            // Cache the initial position of the thumb.
+            m_initialPosition = static_cast<RenderSlider*>(renderer()->parent())->currentPosition();
+            m_inDragMode = true;
+            
+            document()->frame()->eventHandler()->setCapturingMouseEventsNode(m_shadowParent);
+            
+            event->setDefaultHandled();
+            return;
+        }
+    } else if (eventType == eventNames().mouseupEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
+        if (m_inDragMode) {
+            if (Frame* frame = document()->frame())
+                frame->eventHandler()->setCapturingMouseEventsNode(0);      
+            m_inDragMode = false;
+            event->setDefaultHandled();
+            return;
+        }
+    } else if (eventType == eventNames().mousemoveEvent && event->isMouseEvent()) {
+        if (m_inDragMode && renderer() && renderer()->parent()) {
+            // Move the slider
+            MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
+            RenderSlider* slider = static_cast<RenderSlider*>(renderer()->parent());
+            int newPosition = slider->positionForOffset(
+                IntPoint(m_initialPosition + mouseEvent->pageX() - m_initialClickPoint.x()
+                        + (renderer()->width() / 2), 
+                    m_initialPosition + mouseEvent->pageY() - m_initialClickPoint.y()
+                        + (renderer()->height() / 2)));
+            if (slider->currentPosition() != newPosition) {
+                slider->setCurrentPosition(newPosition);
+                slider->valueChanged();
+            }
+            event->setDefaultHandled();
+            return;
+        }
+    }
+
+    HTMLDivElement::defaultEventHandler(event);
+}
+
+RenderSlider::RenderSlider(HTMLInputElement* element)
+    : RenderBlock(element)
+    , m_thumb(0)
+{
+}
+
+RenderSlider::~RenderSlider()
+{
+    if (m_thumb)
+        m_thumb->detach();
+}
+
+int RenderSlider::baselinePosition(bool b, bool isRootLineBox) const
+{
+    return height() + marginTop();
+}
+
+void RenderSlider::calcPrefWidths()
+{
+    m_minPrefWidth = 0;
+    m_maxPrefWidth = 0;
+
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
+    else
+        m_maxPrefWidth = defaultTrackLength * style()->effectiveZoom();
+
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+        m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+    } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
+        m_minPrefWidth = 0;
+    else
+        m_minPrefWidth = m_maxPrefWidth;
+    
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
+        m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+        m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+    }
+
+    int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+    m_minPrefWidth += toAdd;
+    m_maxPrefWidth += toAdd;
+
+    setPrefWidthsDirty(false); 
+}
+
+void RenderSlider::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    
+    if (m_thumb)
+        m_thumb->renderer()->setStyle(createThumbStyle(style(), m_thumb->renderer()->style()));
+        
+    setReplaced(isInline());
+}
+
+PassRefPtr<RenderStyle> RenderSlider::createThumbStyle(const RenderStyle* parentStyle, const RenderStyle* oldStyle)
+{
+    RefPtr<RenderStyle> style;
+    RenderStyle* pseudoStyle = getCachedPseudoStyle(RenderStyle::SLIDER_THUMB);
+    if (pseudoStyle)
+        // We may be sharing style with another slider, but we must not share the thumb style.
+        style = RenderStyle::clone(pseudoStyle);
+    else
+        style = RenderStyle::create();
+
+    if (parentStyle)
+        style->inheritFrom(parentStyle);
+
+    style->setDisplay(BLOCK);
+    style->setPosition(RelativePosition);
+    if (oldStyle) {
+        style->setLeft(oldStyle->left());
+        style->setTop(oldStyle->top());
+    }
+
+    if (parentStyle->appearance() == SliderVerticalPart)
+       style->setAppearance(SliderThumbVerticalPart);
+    else if (parentStyle->appearance() == SliderHorizontalPart)
+       style->setAppearance(SliderThumbHorizontalPart);
+    else if (parentStyle->appearance() == MediaSliderPart)
+        style->setAppearance(MediaSliderThumbPart);
+
+    return style.release();
+}
+
+void RenderSlider::layout()
+{    
+    bool relayoutChildren = false;
+    
+    if (m_thumb && m_thumb->renderer()) {
+            
+#ifdef ANDROID_LAYOUT
+        int oldVisibleWidth = m_visibleWidth;
+#endif
+        
+        int oldWidth = m_width;
+        calcWidth();
+        int oldHeight = m_height;
+        calcHeight();
+        
+        if (oldWidth != m_width || oldHeight != m_height)
+            relayoutChildren = true;  
+
+#ifdef ANDROID_LAYOUT
+        const Settings* settings = document()->settings();
+        ASSERT(settings);
+        if (oldVisibleWidth != m_visibleWidth
+                && settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
+            relayoutChildren = true;
+#endif
+    
+        // Allow the theme to set the size of the thumb
+        if (m_thumb->renderer()->style()->hasAppearance())
+            theme()->adjustSliderThumbSize(m_thumb->renderer());
+
+        if (style()->appearance() == SliderVerticalPart) {
+            // FIXME: Handle percentage widths correctly. See http://bugs.webkit.org/show_bug.cgi?id=12104
+            m_thumb->renderer()->style()->setLeft(Length(contentWidth() / 2 - m_thumb->renderer()->style()->width().value() / 2, Fixed));
+        } else {
+            // FIXME: Handle percentage heights correctly. See http://bugs.webkit.org/show_bug.cgi?id=12104
+            m_thumb->renderer()->style()->setTop(Length(contentHeight() / 2 - m_thumb->renderer()->style()->height().value() / 2, Fixed));
+        }
+
+        if (relayoutChildren)
+            setPositionFromValue(true);
+    }
+
+    RenderBlock::layoutBlock(relayoutChildren);
+}
+
+void RenderSlider::updateFromElement()
+{
+    if (!m_thumb) {
+        m_thumb = new HTMLSliderThumbElement(document(), node());
+        RefPtr<RenderStyle> thumbStyle = createThumbStyle(style());
+        m_thumb->setRenderer(m_thumb->createRenderer(renderArena(), thumbStyle.get()));
+        m_thumb->renderer()->setStyle(thumbStyle.release());
+        m_thumb->setAttached();
+        m_thumb->setInDocument(true);
+        addChild(m_thumb->renderer());
+    }
+    setPositionFromValue();
+    setNeedsLayout(true);
+}
+
+bool RenderSlider::mouseEventIsInThumb(MouseEvent* evt)
+{
+    if (!m_thumb || !m_thumb->renderer())
+        return false;
+ 
+    IntRect thumbBounds = m_thumb->renderer()->absoluteBoundingBoxRect();
+    return thumbBounds.contains(evt->pageX(), evt->pageY());
+}
+
+void RenderSlider::setValueForPosition(int position)
+{
+    if (!m_thumb || !m_thumb->renderer())
+        return;
+    
+    const AtomicString& minStr = static_cast<HTMLInputElement*>(node())->getAttribute(minAttr);
+    const AtomicString& maxStr = static_cast<HTMLInputElement*>(node())->getAttribute(maxAttr);
+    const AtomicString& precision = static_cast<HTMLInputElement*>(node())->getAttribute(precisionAttr);
+    
+    double minVal = minStr.isNull() ? 0.0 : minStr.toDouble();
+    double maxVal = maxStr.isNull() ? 100.0 : maxStr.toDouble();
+    minVal = min(minVal, maxVal); // Make sure the range is sane.
+    
+    // Calculate the new value based on the position
+    double factor = (double)position / (double)trackSize();
+    if (style()->appearance() == SliderVerticalPart)
+        factor = 1.0 - factor;
+    double val = minVal + factor * (maxVal - minVal);
+            
+    val = max(minVal, min(val, maxVal)); // Make sure val is within min/max.
+
+    // Force integer value if not float.
+    if (!equalIgnoringCase(precision, "float"))
+        val = lround(val);
+
+    static_cast<HTMLInputElement*>(node())->setValueFromRenderer(String::number(val));
+    
+    if (position != currentPosition()) {
+        setCurrentPosition(position);
+        static_cast<HTMLInputElement*>(node())->onChange();
+    }
+}
+
+double RenderSlider::setPositionFromValue(bool inLayout)
+{
+    if (!m_thumb || !m_thumb->renderer())
+        return 0;
+    
+    if (!inLayout)
+        document()->updateLayout();
+        
+    String value = static_cast<HTMLInputElement*>(node())->value();
+    const AtomicString& minStr = static_cast<HTMLInputElement*>(node())->getAttribute(minAttr);
+    const AtomicString& maxStr = static_cast<HTMLInputElement*>(node())->getAttribute(maxAttr);
+    const AtomicString& precision = static_cast<HTMLInputElement*>(node())->getAttribute(precisionAttr);
+    
+    double minVal = minStr.isNull() ? 0.0 : minStr.toDouble();
+    double maxVal = maxStr.isNull() ? 100.0 : maxStr.toDouble();
+    minVal = min(minVal, maxVal); // Make sure the range is sane.
+    
+    double oldVal = value.isNull() ? (maxVal + minVal)/2.0 : value.toDouble();
+    double val = max(minVal, min(oldVal, maxVal)); // Make sure val is within min/max.
+        
+    // Force integer value if not float.
+    if (!equalIgnoringCase(precision, "float"))
+        val = lround(val);
+
+    // Calculate the new position based on the value
+    double factor = (val - minVal) / (maxVal - minVal);
+    if (style()->appearance() == SliderVerticalPart)
+        factor = 1.0 - factor;
+
+    setCurrentPosition((int)(factor * trackSize()));
+    
+    if (value.isNull() || val != oldVal)
+        static_cast<HTMLInputElement*>(node())->setValueFromRenderer(String::number(val));
+    
+    return val;
+}
+
+int RenderSlider::positionForOffset(const IntPoint& p)
+{
+    if (!m_thumb || !m_thumb->renderer())
+        return 0;
+   
+    int position;
+    if (style()->appearance() == SliderVerticalPart)
+        position = p.y() - m_thumb->renderer()->height() / 2;
+    else
+        position = p.x() - m_thumb->renderer()->width() / 2;
+    
+    return max(0, min(position, trackSize()));
+}
+
+void RenderSlider::valueChanged()
+{
+    setValueForPosition(currentPosition());
+    static_cast<HTMLInputElement*>(node())->onChange();
+}
+
+int RenderSlider::currentPosition()
+{
+    if (!m_thumb || !m_thumb->renderer())
+        return 0;
+
+    if (style()->appearance() == SliderVerticalPart)
+        return m_thumb->renderer()->style()->top().value();
+    return m_thumb->renderer()->style()->left().value();
+}
+
+void RenderSlider::setCurrentPosition(int pos)
+{
+    if (!m_thumb || !m_thumb->renderer())
+        return;
+
+    if (style()->appearance() == SliderVerticalPart)
+        m_thumb->renderer()->style()->setTop(Length(pos, Fixed));
+    else
+        m_thumb->renderer()->style()->setLeft(Length(pos, Fixed));
+
+    m_thumb->renderer()->layer()->updateLayerPosition();
+    repaint();
+    m_thumb->renderer()->repaint();
+}
+
+int RenderSlider::trackSize()
+{
+    if (!m_thumb || !m_thumb->renderer())
+        return 0;
+
+    if (style()->appearance() == SliderVerticalPart)
+        return contentHeight() - m_thumb->renderer()->height();
+    return contentWidth() - m_thumb->renderer()->width();
+}
+
+void RenderSlider::forwardEvent(Event* evt)
+{
+    m_thumb->defaultEventHandler(evt);
+}
+
+bool RenderSlider::inDragMode() const
+{
+    return m_thumb->inDragMode();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderSlider.h b/WebCore/rendering/RenderSlider.h
new file mode 100644
index 0000000..2667672
--- /dev/null
+++ b/WebCore/rendering/RenderSlider.h
@@ -0,0 +1,73 @@
+/**
+ *
+ * Copyright (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderSlider_h
+#define RenderSlider_h
+
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+    class HTMLDivElement;
+    class HTMLInputElement;
+    class HTMLSliderThumbElement;
+    class MouseEvent;
+    
+    class RenderSlider : public RenderBlock {
+    public:
+        RenderSlider(HTMLInputElement*);
+        ~RenderSlider();
+
+        virtual const char* renderName() const { return "RenderSlider"; }
+        virtual bool isSlider() const { return true; }
+
+        virtual int baselinePosition( bool, bool ) const;
+        virtual void calcPrefWidths();
+        virtual void layout();
+        virtual void updateFromElement();
+        
+        bool mouseEventIsInThumb(MouseEvent*);
+
+        void setValueForPosition(int position);
+        double setPositionFromValue(bool inLayout = false);
+        int positionForOffset(const IntPoint&);
+
+        void valueChanged();
+        
+        int currentPosition();
+        void setCurrentPosition(int pos);        
+        
+        void forwardEvent(Event*);
+        bool inDragMode() const;
+
+    protected:
+        virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+    
+    private:
+        PassRefPtr<RenderStyle> createThumbStyle(const RenderStyle* parentStyle, const RenderStyle* oldStyle = 0);
+        int trackSize();
+
+        RefPtr<HTMLSliderThumbElement> m_thumb;
+};
+
+} // namespace WebCore
+
+#endif // RenderSlider_h
diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp
new file mode 100644
index 0000000..b18ee3e
--- /dev/null
+++ b/WebCore/rendering/RenderTable.cpp
@@ -0,0 +1,1205 @@
+/*
+ * Copyright (C) 1997 Martin Jones ([email protected])
+ *           (C) 1997 Torben Weis ([email protected])
+ *           (C) 1998 Waldo Bastian ([email protected])
+ *           (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RenderTable.h"
+
+#include "AutoTableLayout.h"
+#include "DeleteButtonController.h"
+#include "Document.h"
+#include "FixedTableLayout.h"
+#include "FrameView.h"
+#include "HTMLNames.h"
+#include "RenderLayer.h"
+#include "RenderTableCell.h"
+#include "RenderTableCol.h"
+#include "RenderTableSection.h"
+#ifdef ANDROID_LAYOUT
+#include "Settings.h"
+#endif
+#include "RenderView.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderTable::RenderTable(Node* node)
+    : RenderBlock(node)
+    , m_caption(0)
+    , m_head(0)
+    , m_foot(0)
+    , m_firstBody(0)
+    , m_tableLayout(0)
+    , m_currentBorder(0)
+    , m_frame(Void)
+    , m_rules(None)
+    , m_hasColElements(false)
+    , m_needsSectionRecalc(0)
+    , m_hSpacing(0)
+    , m_vSpacing(0)
+    , m_borderLeft(0)
+    , m_borderRight(0)
+{
+#ifdef ANDROID_LAYOUT
+    m_singleColumn = false;    
+#endif    
+    m_columnPos.fill(0, 2);
+    m_columns.fill(ColumnStruct(), 1);
+}
+
+RenderTable::~RenderTable()
+{
+    delete m_tableLayout;
+}
+
+void RenderTable::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+
+    ETableLayout oldTableLayout = oldStyle ? oldStyle->tableLayout() : TAUTO;
+
+    // In the collapsed border model, there is no cell spacing.
+    m_hSpacing = collapseBorders() ? 0 : style()->horizontalBorderSpacing();
+    m_vSpacing = collapseBorders() ? 0 : style()->verticalBorderSpacing();
+    m_columnPos[0] = m_hSpacing;
+
+    if (!m_tableLayout || style()->tableLayout() != oldTableLayout) {
+        delete m_tableLayout;
+
+        // According to the CSS2 spec, you only use fixed table layout if an
+        // explicit width is specified on the table.  Auto width implies auto table layout.
+        if (style()->tableLayout() == TFIXED && !style()->width().isAuto())
+            m_tableLayout = new FixedTableLayout(this);
+        else
+            m_tableLayout = new AutoTableLayout(this);
+    }
+}
+
+static inline void resetSectionPointerIfNotBefore(RenderTableSection*& ptr, RenderObject* before)
+{
+    if (!before || !ptr)
+        return;
+    RenderObject* o = before->previousSibling();
+    while (o && o != ptr)
+        o = o->previousSibling();
+    if (!o)
+        ptr = 0;
+}
+
+void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    // Make sure we don't append things after :after-generated content if we have it.
+    if (!beforeChild && isAfterContent(lastChild()))
+        beforeChild = lastChild();
+
+    bool wrapInAnonymousSection = true;
+    bool isTableElement = element() && element()->hasTagName(tableTag);
+
+    if (child->isRenderBlock() && child->style()->display() == TABLE_CAPTION) {
+        // First caption wins.
+        if (beforeChild && m_caption) {
+            RenderObject* o = beforeChild->previousSibling();
+            while (o && o != m_caption)
+                o = o->previousSibling();
+            if (!o)
+                m_caption = 0;
+        }
+        if (!m_caption)
+            m_caption = static_cast<RenderBlock*>(child);
+        wrapInAnonymousSection = false;
+    } else if (child->isTableCol()) {
+        m_hasColElements = true;
+        wrapInAnonymousSection = false;
+    } else if (child->isTableSection()) {
+        switch (child->style()->display()) {
+            case TABLE_HEADER_GROUP:
+                if (child->isTableSection()) {
+                    resetSectionPointerIfNotBefore(m_head, beforeChild);
+                    if (!m_head) {
+                        m_head = static_cast<RenderTableSection*>(child);
+                    } else {
+                        resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
+                        if (!m_firstBody) 
+                            m_firstBody = static_cast<RenderTableSection*>(child);
+                    }
+                }
+                wrapInAnonymousSection = false;
+                break;
+            case TABLE_FOOTER_GROUP:
+                if (child->isTableSection()) {
+                    resetSectionPointerIfNotBefore(m_foot, beforeChild);
+                    if (!m_foot) {
+                        m_foot = static_cast<RenderTableSection*>(child);
+                        wrapInAnonymousSection = false;
+                        break;
+                    }
+                }
+                // Fall through.
+            case TABLE_ROW_GROUP:
+                if (child->isTableSection()) {
+                    resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
+                    if (!m_firstBody)
+                        m_firstBody = static_cast<RenderTableSection*>(child);
+                }
+                wrapInAnonymousSection = false;
+                break;
+            default:
+                ASSERT_NOT_REACHED();
+        }
+    } else if (child->isTableCell() || child->isTableRow()) {
+        wrapInAnonymousSection = true;
+    } else {
+        // Allow a form to just sit at the top level.
+        wrapInAnonymousSection = !isTableElement || !child->element() || !(child->element()->hasTagName(formTag) && document()->isHTMLDocument());
+
+        // FIXME: Allow the delete button container element to sit at the top level. This is needed until http://bugs.webkit.org/show_bug.cgi?id=11363 is fixed.
+        if (wrapInAnonymousSection && child->element() && child->element()->isHTMLElement() && static_cast<HTMLElement*>(child->element())->id() == DeleteButtonController::containerElementIdentifier)
+            wrapInAnonymousSection = false;
+    }
+
+    if (!wrapInAnonymousSection) {
+        // If the next renderer is actually wrapped in an anonymous table section, we need to go up and find that.
+        while (beforeChild && !beforeChild->isTableSection() && !beforeChild->isTableCol() && beforeChild->style()->display() != TABLE_CAPTION)
+            beforeChild = beforeChild->parent();
+
+        RenderContainer::addChild(child, beforeChild);
+        return;
+    }
+
+    if (!beforeChild && lastChild() && lastChild()->isTableSection() && lastChild()->isAnonymous()) {
+        lastChild()->addChild(child);
+        return;
+    }
+
+    RenderObject* lastBox = beforeChild;
+    while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION && lastBox->style()->display() != TABLE_COLUMN_GROUP)
+        lastBox = lastBox->parent();
+    if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox)) {
+        lastBox->addChild(child, beforeChild);
+        return;
+    }
+
+    if (beforeChild && !beforeChild->isTableSection() && beforeChild->style()->display() != TABLE_CAPTION && beforeChild->style()->display() != TABLE_COLUMN_GROUP)
+        beforeChild = 0;
+    RenderTableSection* section = new (renderArena()) RenderTableSection(document() /* anonymous */);
+    RefPtr<RenderStyle> newStyle = RenderStyle::create();
+    newStyle->inheritFrom(style());
+    newStyle->setDisplay(TABLE_ROW_GROUP);
+    section->setStyle(newStyle.release());
+    addChild(section, beforeChild);
+    section->addChild(child);
+}
+
+void RenderTable::calcWidth()
+{
+#ifdef ANDROID_LAYOUT
+    if (view()->frameView()) {
+        const Settings* settings = document()->settings();
+        ASSERT(settings);
+        if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) {
+            m_visibleWidth = view()->frameView()->screenWidth();
+        }
+    }
+#endif
+    
+    if (isPositioned())
+        calcAbsoluteHorizontal();
+
+    RenderBlock* cb = containingBlock();
+    int availableWidth = cb->availableWidth();
+
+    LengthType widthType = style()->width().type();
+    if (widthType > Relative && style()->width().isPositive()) {
+        // Percent or fixed table
+        m_width = style()->width().calcMinValue(availableWidth);
+        m_width = max(minPrefWidth(), m_width);
+    } else {
+        // An auto width table should shrink to fit within the line width if necessary in order to 
+        // avoid overlapping floats.
+        availableWidth = cb->lineWidth(m_y);
+        
+        // Subtract out any fixed margins from our available width for auto width tables.
+        int marginTotal = 0;
+        if (!style()->marginLeft().isAuto())
+            marginTotal += style()->marginLeft().calcValue(availableWidth);
+        if (!style()->marginRight().isAuto())
+            marginTotal += style()->marginRight().calcValue(availableWidth);
+            
+        // Subtract out our margins to get the available content width.
+        int availContentWidth = max(0, availableWidth - marginTotal);
+        
+        // Ensure we aren't bigger than our max width or smaller than our min width.
+        m_width = min(availContentWidth, maxPrefWidth());
+    }
+    
+    m_width = max(m_width, minPrefWidth());
+
+    // Finally, with our true width determined, compute our margins for real.
+    m_marginRight = 0;
+    m_marginLeft = 0;
+#ifdef ANDROID_LAYOUT
+    // in SSR mode, we ignore left/right margin for table
+    if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR)
+        return;
+#endif    
+    calcHorizontalMargins(style()->marginLeft(), style()->marginRight(), availableWidth);
+}
+
+void RenderTable::layout()
+{
+    ASSERT(needsLayout());
+
+    if (layoutOnlyPositionedObjects())
+        return;
+
+    recalcSectionsIfNeeded();
+        
+    IntRect oldBounds;
+    IntRect oldOutlineBox;
+    bool checkForRepaint = checkForRepaintDuringLayout();
+    if (checkForRepaint) {
+        oldBounds = absoluteClippedOverflowRect();
+        oldOutlineBox = absoluteOutlineBox();
+    }
+    
+    view()->pushLayoutState(this, IntSize(m_x, m_y));
+
+    m_height = 0;
+    m_overflowHeight = 0;
+    m_overflowTop = 0;
+    initMaxMarginValues();
+    
+#ifdef ANDROID_LAYOUT
+    bool relayoutChildren = false;
+    int oldVisibleWidth = m_visibleWidth;
+#endif
+    
+    int oldWidth = m_width;
+    calcWidth();
+
+#ifdef ANDROID_LAYOUT
+    if (oldVisibleWidth != m_visibleWidth
+            && document()->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
+        relayoutChildren = true;
+    else if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) {
+        // if the width of a table is wider than its container width, or it has a nested table,
+        // we will render it with single column.
+        int cw = containingBlockWidth();
+        if (m_width > cw || hasChildTable()) {
+            m_singleColumn = true; 
+            if (m_width > cw)
+	            m_width = cw;
+            if (m_minPrefWidth > cw)
+	            m_minPrefWidth = cw;
+    		if (m_maxPrefWidth > cw)
+	            m_maxPrefWidth = cw;
+        }
+    }    
+#endif
+    if (m_caption && m_width != oldWidth)
+        m_caption->setNeedsLayout(true, false);
+
+    // FIXME: The optimisation below doesn't work since the internal table
+    // layout could have changed.  we need to add a flag to the table
+    // layout that tells us if something has changed in the min max
+    // calculations to do it correctly.
+//     if ( oldWidth != m_width || columns.size() + 1 != columnPos.size() )
+    m_tableLayout->layout();
+
+    setCellWidths();
+
+    // layout child objects
+    int calculatedHeight = 0;
+    int oldTableTop = m_caption ? m_caption->height() + m_caption->marginTop() + m_caption->marginBottom() : 0;
+
+    bool collapsing = collapseBorders();
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        // FIXME: What about a form that has a display value that makes it a table section?
+#ifdef ANDROID_LAYOUT
+        if ((relayoutChildren || child->needsLayout()) &&
+                !(child->element() && child->element()->hasTagName(formTag))) {
+            child->setNeedsLayout(true);
+            child->layout();
+        }
+#else
+        if (child->needsLayout() && !(child->element() && child->element()->hasTagName(formTag)))
+            child->layout();
+#endif
+        if (child->isTableSection()) {
+            RenderTableSection* section = static_cast<RenderTableSection*>(child);
+            calculatedHeight += section->calcRowHeight();
+            if (collapsing)
+                section->recalcOuterBorder();
+        }
+    }
+
+    m_overflowWidth = m_width + (collapsing ? outerBorderRight() - borderRight() : 0);
+    m_overflowLeft = collapsing ? borderLeft() - outerBorderLeft() : 0;
+
+    // If any table section moved vertically, we will just repaint everything from that
+    // section down (it is quite unlikely that any of the following sections
+    // did not shift).
+    bool sectionMoved = false;
+    int movedSectionTop = 0;
+
+    // FIXME: Collapse caption margin.
+    if (m_caption && m_caption->style()->captionSide() != CAPBOTTOM) {
+        IntRect captionRect(m_caption->xPos(), m_caption->yPos(), m_caption->width(), m_caption->height());
+
+        m_caption->setPos(m_caption->marginLeft(), m_height);
+        if (!selfNeedsLayout() && m_caption->checkForRepaintDuringLayout())
+            m_caption->repaintDuringLayoutIfMoved(captionRect);
+
+        m_height += m_caption->height() + m_caption->marginTop() + m_caption->marginBottom();
+        m_overflowLeft = min(m_overflowLeft, m_caption->xPos() + m_caption->overflowLeft(false));
+        m_overflowWidth = max(m_overflowWidth, m_caption->xPos() + m_caption->overflowWidth(false));
+        m_overflowTop = min(m_overflowTop, m_caption->yPos() + m_caption->overflowTop(false));
+        m_overflowHeight = max(m_overflowHeight, m_caption->yPos() + m_caption->overflowHeight(false));
+
+        if (m_height != oldTableTop) {
+            sectionMoved = true;
+            movedSectionTop = min(m_height, oldTableTop);
+        }
+    }
+
+    int bpTop = borderTop() + (collapsing ? 0 : paddingTop());
+    int bpBottom = borderBottom() + (collapsing ? 0 : paddingBottom());
+    
+    m_height += bpTop;
+
+    if (!isPositioned())
+        calcHeight();
+
+    Length h = style()->height();
+    int th = 0;
+    if (h.isFixed())
+        // Tables size as though CSS height includes border/padding.
+        th = h.value() - (bpTop + bpBottom);
+    else if (h.isPercent())
+        th = calcPercentageHeight(h);
+    th = max(0, th);
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (!child->isTableSection())
+            continue;
+        // FIXME: Distribute extra height between all table body sections instead of giving it all to the first one.
+        static_cast<RenderTableSection*>(child)->layoutRows(child == m_firstBody ? max(0, th - calculatedHeight) : 0);
+    }
+
+    if (!m_firstBody && th > calculatedHeight && !style()->htmlHacks()) {
+        // Completely empty tables (with no sections or anything) should at least honor specified height
+        // in strict mode.
+        m_height += th;
+    }
+    
+    int bl = borderLeft();
+    if (!collapsing)
+        bl += paddingLeft();
+
+    // position the table sections
+    RenderTableSection* section = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
+    while (section) {
+        if (!sectionMoved && section->yPos() != m_height) {
+            sectionMoved = true;
+            movedSectionTop = min(m_height, section->yPos()) + section->overflowTop(false);
+        }
+        section->setPos(bl, m_height);
+
+        m_height += section->height();
+        m_overflowLeft = min(m_overflowLeft, section->xPos() + section->overflowLeft(false));
+        m_overflowWidth = max(m_overflowWidth, section->xPos() + section->overflowWidth(false));
+        m_overflowTop = min(m_overflowTop, section->yPos() + section->overflowTop(false));
+        m_overflowHeight = max(m_overflowHeight, section->yPos() + section->overflowHeight(false));
+        section = sectionBelow(section);
+    }
+
+    m_height += bpBottom;
+
+    if (m_caption && m_caption->style()->captionSide() == CAPBOTTOM) {
+        IntRect captionRect(m_caption->xPos(), m_caption->yPos(), m_caption->width(), m_caption->height());
+
+        m_caption->setPos(m_caption->marginLeft(), m_height);
+        if (!selfNeedsLayout() && m_caption->checkForRepaintDuringLayout())
+            m_caption->repaintDuringLayoutIfMoved(captionRect);
+
+        m_height += m_caption->height() + m_caption->marginTop() + m_caption->marginBottom();
+        m_overflowLeft = min(m_overflowLeft, m_caption->xPos() + m_caption->overflowLeft(false));
+        m_overflowWidth = max(m_overflowWidth, m_caption->xPos() + m_caption->overflowWidth(false));
+    }
+
+    if (isPositioned())
+        calcHeight();
+
+    m_overflowHeight = max(m_overflowHeight, m_height);
+
+    // table can be containing block of positioned elements.
+    // FIXME: Only pass true if width or height changed.
+    layoutPositionedObjects(true);
+
+    if (!hasOverflowClip()) {
+        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+            m_overflowLeft = min(m_overflowLeft, boxShadow->x - boxShadow->blur);
+            m_overflowWidth = max(m_overflowWidth, m_width + boxShadow->x + boxShadow->blur);
+            m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur);
+            m_overflowHeight = max(m_overflowHeight, m_height + boxShadow->y + boxShadow->blur);
+        }
+        
+        if (hasReflection()) {
+            IntRect reflection(reflectionBox());
+            m_overflowTop = min(m_overflowTop, reflection.y());
+            m_overflowHeight = max(m_overflowHeight, reflection.bottom());
+            m_overflowLeft = min(m_overflowLeft, reflection.x());
+            m_overflowHeight = max(m_overflowWidth, reflection.right());
+        }
+    }
+
+    view()->popLayoutState();
+
+    bool didFullRepaint = true;
+    // Repaint with our new bounds if they are different from our old bounds.
+    if (checkForRepaint)
+        didFullRepaint = repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+    if (!didFullRepaint && sectionMoved)
+        repaintRectangle(IntRect(m_overflowLeft, movedSectionTop, m_overflowWidth - m_overflowLeft, m_overflowHeight - movedSectionTop));
+    
+    setNeedsLayout(false);
+}
+
+void RenderTable::setCellWidths()
+{
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isTableSection())
+            static_cast<RenderTableSection*>(child)->setCellWidths();
+    }
+}
+
+void RenderTable::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    tx += xPos();
+    ty += yPos();
+
+    PaintPhase paintPhase = paintInfo.phase;
+
+    int os = 2 * maximalOutlineSize(paintPhase);
+    if (ty + overflowTop(false) >= paintInfo.rect.bottom() + os || ty + overflowHeight(false) <= paintInfo.rect.y() - os)
+        return;
+    if (tx + overflowLeft(false) >= paintInfo.rect.right() + os || tx + overflowWidth(false) <= paintInfo.rect.x() - os)
+        return;
+
+    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style()->visibility() == VISIBLE)
+        paintBoxDecorations(paintInfo, tx, ty);
+
+    if (paintPhase == PaintPhaseMask) {
+        paintMask(paintInfo, tx, ty);
+        return;
+    }
+
+    // We're done.  We don't bother painting any children.
+    if (paintPhase == PaintPhaseBlockBackground)
+        return;
+
+    // We don't paint our own background, but we do let the kids paint their backgrounds.
+    if (paintPhase == PaintPhaseChildBlockBackgrounds)
+        paintPhase = PaintPhaseChildBlockBackground;
+    PaintInfo info(paintInfo);
+    info.phase = paintPhase;
+    info.paintingRoot = paintingRootForChildren(paintInfo);
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (!child->hasLayer() && (child->isTableSection() || child == m_caption))
+            child->paint(info, tx, ty);
+    }
+
+    if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
+        // Collect all the unique border styles that we want to paint in a sorted list.  Once we
+        // have all the styles sorted, we then do individual passes, painting each style of border
+        // from lowest precedence to highest precedence.
+        info.phase = PaintPhaseCollapsedTableBorders;
+        RenderTableCell::CollapsedBorderStyles borderStyles;
+        RenderObject* stop = nextInPreOrderAfterChildren();
+        for (RenderObject* o = firstChild(); o && o != stop; o = o->nextInPreOrder())
+            if (o->isTableCell())
+                static_cast<RenderTableCell*>(o)->collectBorderStyles(borderStyles);
+        RenderTableCell::sortBorderStyles(borderStyles);
+        size_t count = borderStyles.size();
+        for (size_t i = 0; i < count; ++i) {
+            m_currentBorder = &borderStyles[i];
+            for (RenderObject* child = firstChild(); child; child = child->nextSibling())
+                if (child->isTableSection())
+                    child->paint(info, tx, ty);
+        }
+        m_currentBorder = 0;
+    }
+}
+
+void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
+{
+    int w = width();
+    int h = height();
+
+    // Account for the caption.
+    if (m_caption) {
+        int captionHeight = (m_caption->height() + m_caption->marginBottom() +  m_caption->marginTop());
+        h -= captionHeight;
+        if (m_caption->style()->captionSide() != CAPBOTTOM)
+            ty += captionHeight;
+    }
+
+    int my = max(ty, paintInfo.rect.y());
+    int mh;
+    if (ty < paintInfo.rect.y())
+        mh = max(0, h - (paintInfo.rect.y() - ty));
+    else
+        mh = min(paintInfo.rect.height(), h);
+
+    paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
+    
+    paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), my, mh, tx, ty, w, h);
+
+    if (style()->hasBorder() && !collapseBorders())
+        paintBorder(paintInfo.context, tx, ty, w, h, style());
+}
+
+void RenderTable::paintMask(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+        return;
+
+    int w = width();
+    int h = height();
+
+    // Account for the caption.
+    if (m_caption) {
+        int captionHeight = (m_caption->height() + m_caption->marginBottom() +  m_caption->marginTop());
+        h -= captionHeight;
+        if (m_caption->style()->captionSide() != CAPBOTTOM)
+            ty += captionHeight;
+    }
+
+    int my = max(ty, paintInfo.rect.y());
+    int mh;
+    if (ty < paintInfo.rect.y())
+        mh = max(0, h - (paintInfo.rect.y() - ty));
+    else
+        mh = min(paintInfo.rect.height(), h);
+    
+    paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+}
+
+void RenderTable::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+
+    recalcSectionsIfNeeded();
+    recalcHorizontalBorders();
+
+    m_tableLayout->calcPrefWidths(m_minPrefWidth, m_maxPrefWidth);
+
+    if (m_caption)
+        m_minPrefWidth = max(m_minPrefWidth, m_caption->minPrefWidth());
+
+    setPrefWidthsDirty(false);
+}
+
+void RenderTable::splitColumn(int pos, int firstSpan)
+{
+    // we need to add a new columnStruct
+    int oldSize = m_columns.size();
+    m_columns.grow(oldSize + 1);
+    int oldSpan = m_columns[pos].span;
+    ASSERT(oldSpan > firstSpan);
+    m_columns[pos].span = firstSpan;
+    memmove(m_columns.data() + pos + 1, m_columns.data() + pos, (oldSize - pos) * sizeof(ColumnStruct));
+    m_columns[pos + 1].span = oldSpan - firstSpan;
+
+    // change width of all rows.
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isTableSection())
+            static_cast<RenderTableSection*>(child)->splitColumn(pos, oldSize + 1);
+    }
+
+    m_columnPos.grow(numEffCols() + 1);
+    setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+void RenderTable::appendColumn(int span)
+{
+    // easy case.
+    int pos = m_columns.size();
+    int newSize = pos + 1;
+    m_columns.grow(newSize);
+    m_columns[pos].span = span;
+
+    // change width of all rows.
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isTableSection())
+            static_cast<RenderTableSection*>(child)->appendColumn(pos);
+    }
+
+    m_columnPos.grow(numEffCols() + 1);
+    setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+RenderTableCol* RenderTable::colElement(int col, bool* startEdge, bool* endEdge) const
+{
+    if (!m_hasColElements)
+        return 0;
+    RenderObject* child = firstChild();
+    int cCol = 0;
+
+    while (child) {
+        if (child->isTableCol()) {
+            RenderTableCol* colElem = static_cast<RenderTableCol*>(child);
+            int span = colElem->span();
+            if (!colElem->firstChild()) {
+                int startCol = cCol;
+                int endCol = cCol + span - 1;
+                cCol += span;
+                if (cCol > col) {
+                    if (startEdge)
+                        *startEdge = startCol == col;
+                    if (endEdge)
+                        *endEdge = endCol == col;
+                    return colElem;
+                }
+            }
+
+            RenderObject* next = child->firstChild();
+            if (!next)
+                next = child->nextSibling();
+            if (!next && child->parent()->isTableCol())
+                next = child->parent()->nextSibling();
+            child = next;
+        } else if (child == m_caption)
+            child = child->nextSibling();
+        else
+            break;
+    }
+
+    return 0;
+}
+
+void RenderTable::recalcSections() const
+{
+    m_caption = 0;
+    m_head = 0;
+    m_foot = 0;
+    m_firstBody = 0;
+    m_hasColElements = false;
+
+    // We need to get valid pointers to caption, head, foot and first body again
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        switch (child->style()->display()) {
+            case TABLE_CAPTION:
+                if (!m_caption && child->isRenderBlock()) {
+                    m_caption = static_cast<RenderBlock*>(child);
+                    m_caption->setNeedsLayout(true);
+                }
+                break;
+            case TABLE_COLUMN:
+            case TABLE_COLUMN_GROUP:
+                m_hasColElements = true;
+                break;
+            case TABLE_HEADER_GROUP:
+                if (child->isTableSection()) {
+                    RenderTableSection* section = static_cast<RenderTableSection*>(child);
+                    if (!m_head)
+                        m_head = section;
+                    else if (!m_firstBody)
+                        m_firstBody = section;
+                    section->recalcCellsIfNeeded();
+                }
+                break;
+            case TABLE_FOOTER_GROUP:
+                if (child->isTableSection()) {
+                    RenderTableSection* section = static_cast<RenderTableSection*>(child);
+                    if (!m_foot)
+                        m_foot = section;
+                    else if (!m_firstBody)
+                        m_firstBody = section;
+                    section->recalcCellsIfNeeded();
+                }
+                break;
+            case TABLE_ROW_GROUP:
+                if (child->isTableSection()) {
+                    RenderTableSection* section = static_cast<RenderTableSection*>(child);
+                    if (!m_firstBody)
+                        m_firstBody = section;
+                    section->recalcCellsIfNeeded();
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    // repair column count (addChild can grow it too much, because it always adds elements to the last row of a section)
+    int maxCols = 0;
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isTableSection()) {
+            RenderTableSection* section = static_cast<RenderTableSection*>(child);
+            int sectionCols = section->numColumns();
+            if (sectionCols > maxCols)
+                maxCols = sectionCols;
+        }
+    }
+    
+    m_columns.resize(maxCols);
+    m_columnPos.resize(maxCols + 1);
+
+    ASSERT(selfNeedsLayout());
+
+    m_needsSectionRecalc = false;
+}
+
+RenderObject* RenderTable::removeChildNode(RenderObject* child, bool fullRemove)
+{
+    setNeedsSectionRecalc();
+    return RenderContainer::removeChildNode(child, fullRemove);
+}
+
+int RenderTable::calcBorderLeft() const
+{
+    if (collapseBorders()) {
+        // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2.
+        if (!numEffCols())
+            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)
+                borderWidth = max(borderWidth, static_cast<unsigned>(gb.width));
+        }
+        
+        RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
+        if (firstNonEmptySection && !firstNonEmptySection->numRows())
+            firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
+        
+        if (firstNonEmptySection) {
+            const BorderValue& sb = firstNonEmptySection->style()->borderLeft();
+            if (sb.style() == BHIDDEN)
+                return 0;
+
+            if (sb.style() > BHIDDEN)
+                borderWidth = max(borderWidth, static_cast<unsigned>(sb.width));
+
+            const RenderTableSection::CellStruct& cs = firstNonEmptySection->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)
+                    borderWidth = max(borderWidth, static_cast<unsigned>(cb.width));
+                if (rb.style() > BHIDDEN)
+                    borderWidth = max(borderWidth, static_cast<unsigned>(rb.width));
+            }
+        }
+        return borderWidth / 2;
+    }
+    return RenderBlock::borderLeft();
+}
+    
+int RenderTable::calcBorderRight() const
+{
+    if (collapseBorders()) {
+        // Determined by the last cell of the first row. See the CSS 2.1 spec, section 17.6.2.
+        if (!numEffCols())
+            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)
+                borderWidth = max(borderWidth, static_cast<unsigned>(gb.width));
+        }
+        
+        RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
+        if (firstNonEmptySection && !firstNonEmptySection->numRows())
+            firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
+        
+        if (firstNonEmptySection) {
+            const BorderValue& sb = firstNonEmptySection->style()->borderRight();
+            if (sb.style() == BHIDDEN)
+                return 0;
+
+            if (sb.style() > BHIDDEN)
+                borderWidth = max(borderWidth, static_cast<unsigned>(sb.width));
+
+            const RenderTableSection::CellStruct& cs = firstNonEmptySection->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)
+                    borderWidth = max(borderWidth, static_cast<unsigned>(cb.width));
+                if (rb.style() > BHIDDEN)
+                    borderWidth = max(borderWidth, static_cast<unsigned>(rb.width));
+            }
+        }
+        return (borderWidth + 1) / 2;
+    }
+    return RenderBlock::borderRight();
+}
+
+void RenderTable::recalcHorizontalBorders()
+{
+    m_borderLeft = calcBorderLeft();
+    m_borderRight = calcBorderRight();
+}
+
+int RenderTable::borderTop() const
+{
+    if (collapseBorders())
+        return outerBorderTop();
+    return RenderBlock::borderTop();
+}
+
+int RenderTable::borderBottom() const
+{
+    if (collapseBorders())
+        return outerBorderBottom();
+    return RenderBlock::borderBottom();
+}
+
+int RenderTable::outerBorderTop() const
+{
+    if (!collapseBorders())
+        return 0;
+    int borderWidth = 0;
+    RenderTableSection* topSection;
+    if (m_head)
+        topSection = m_head;
+    else if (m_firstBody)
+        topSection = m_firstBody;
+    else if (m_foot)
+        topSection = m_foot;
+    else
+        topSection = 0;
+    if (topSection) {
+        borderWidth = topSection->outerBorderTop();
+        if (borderWidth == -1)
+            return 0;   // Overridden by hidden
+    }
+    const BorderValue& tb = style()->borderTop();
+    if (tb.style() == BHIDDEN)
+        return 0;
+    if (tb.style() > BHIDDEN)
+        borderWidth = max(borderWidth, static_cast<int>(tb.width / 2));
+    return borderWidth;
+}
+
+int RenderTable::outerBorderBottom() const
+{
+    if (!collapseBorders())
+        return 0;
+    int borderWidth = 0;
+    RenderTableSection* bottomSection;
+    if (m_foot)
+        bottomSection = m_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)
+        borderWidth = max(borderWidth, static_cast<int>((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;
+}
+
+RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section, bool skipEmptySections) const
+{
+    recalcSectionsIfNeeded();
+
+    if (section == m_head)
+        return 0;
+
+    RenderObject* prevSection = section == m_foot ? lastChild() : section->previousSibling();
+    while (prevSection) {
+        if (prevSection->isTableSection() && prevSection != m_head && prevSection != m_foot && (!skipEmptySections || static_cast<RenderTableSection*>(prevSection)->numRows()))
+            break;
+        prevSection = prevSection->previousSibling();
+    }
+    if (!prevSection && m_head && (!skipEmptySections || m_head->numRows()))
+        prevSection = m_head;
+    return static_cast<RenderTableSection*>(prevSection);
+}
+
+RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, bool skipEmptySections) const
+{
+    recalcSectionsIfNeeded();
+
+    if (section == m_foot)
+        return 0;
+
+    RenderObject* nextSection = section == m_head ? firstChild() : section->nextSibling();
+    while (nextSection) {
+        if (nextSection->isTableSection() && nextSection != m_head && nextSection != m_foot && (!skipEmptySections || static_cast<RenderTableSection*>(nextSection)->numRows()))
+            break;
+        nextSection = nextSection->nextSibling();
+    }
+    if (!nextSection && m_foot && (!skipEmptySections || m_foot->numRows()))
+        nextSection = m_foot;
+    return static_cast<RenderTableSection*>(nextSection);
+}
+
+RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
+{
+    recalcSectionsIfNeeded();
+
+    // Find the section and row to look in
+    int r = cell->row();
+    RenderTableSection* section = 0;
+    int rAbove = 0;
+    if (r > 0) {
+        // cell is not in the first row, so use the above row in its own section
+        section = cell->section();
+        rAbove = r - 1;
+    } else {
+        section = sectionAbove(cell->section(), true);
+        if (section)
+            rAbove = section->numRows() - 1;
+    }
+
+    // Look up the cell in the section's grid, which requires effective col index
+    if (section) {
+        int effCol = colToEffCol(cell->col());
+        RenderTableSection::CellStruct aboveCell;
+        // If we hit a span back up to a real cell.
+        do {
+            aboveCell = section->cellAt(rAbove, effCol);
+            effCol--;
+        } while (!aboveCell.cell && aboveCell.inColSpan && effCol >= 0);
+        return aboveCell.cell;
+    } else
+        return 0;
+}
+
+RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
+{
+    recalcSectionsIfNeeded();
+
+    // Find the section and row to look in
+    int r = cell->row() + cell->rowSpan() - 1;
+    RenderTableSection* section = 0;
+    int rBelow = 0;
+    if (r < cell->section()->numRows() - 1) {
+        // The cell is not in the last row, so use the next row in the section.
+        section = cell->section();
+        rBelow = r + 1;
+    } else {
+        section = sectionBelow(cell->section(), true);
+        if (section)
+            rBelow = 0;
+    }
+
+    // Look up the cell in the section's grid, which requires effective col index
+    if (section) {
+        int effCol = colToEffCol(cell->col());
+        RenderTableSection::CellStruct belowCell;
+        // If we hit a colspan back up to a real cell.
+        do {
+            belowCell = section->cellAt(rBelow, effCol);
+            effCol--;
+        } while (!belowCell.cell && belowCell.inColSpan && effCol >= 0);
+        return belowCell.cell;
+    } else
+        return 0;
+}
+
+RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
+{
+    recalcSectionsIfNeeded();
+
+    RenderTableSection* section = cell->section();
+    int effCol = colToEffCol(cell->col());
+    if (!effCol)
+        return 0;
+    
+    // If we hit a colspan back up to a real cell.
+    RenderTableSection::CellStruct prevCell;
+    do {
+        prevCell = section->cellAt(cell->row(), effCol - 1);
+        effCol--;
+    } while (!prevCell.cell && prevCell.inColSpan && effCol >= 0);
+    return prevCell.cell;
+}
+
+RenderTableCell* RenderTable::cellAfter(const RenderTableCell* cell) const
+{
+    recalcSectionsIfNeeded();
+
+    int effCol = colToEffCol(cell->col() + cell->colSpan());
+    if (effCol >= numEffCols())
+        return 0;
+    return cell->section()->cellAt(cell->row(), effCol).cell;
+}
+
+RenderBlock* RenderTable::firstLineBlock() const
+{
+    return 0;
+}
+
+void RenderTable::updateFirstLetter()
+{
+}
+
+int RenderTable::getBaselineOfFirstLineBox() const
+{
+    RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
+    if (firstNonEmptySection && !firstNonEmptySection->numRows())
+        firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
+
+    if (!firstNonEmptySection)
+        return -1;
+
+    return firstNonEmptySection->yPos() + firstNonEmptySection->getBaselineOfFirstLineBox();
+}
+
+IntRect RenderTable::getOverflowClipRect(int tx, int ty)
+{
+    IntRect rect = RenderBlock::getOverflowClipRect(tx, ty);
+    
+    // If we have a caption, expand the clip to include the caption.
+    // FIXME: Technically this is wrong, but it's virtually impossible to fix this
+    // for real until captions have been re-written.
+    // FIXME: This code assumes (like all our other caption code) that only top/bottom are
+    // supported.  When we actually support left/right and stop mapping them to top/bottom,
+    // we might have to hack this code first (depending on what order we do these bug fixes in).
+    if (m_caption) {
+        rect.setHeight(height());
+        rect.setY(ty);
+    }
+
+    return rect;
+}
+
+}
diff --git a/WebCore/rendering/RenderTable.h b/WebCore/rendering/RenderTable.h
new file mode 100644
index 0000000..e3168cb
--- /dev/null
+++ b/WebCore/rendering/RenderTable.h
@@ -0,0 +1,234 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1997 Martin Jones ([email protected])
+ *           (C) 1997 Torben Weis ([email protected])
+ *           (C) 1998 Waldo Bastian ([email protected])
+ *           (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RenderTable_h
+#define RenderTable_h
+
+#include "RenderBlock.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderTableCol;
+class RenderTableCell;
+class RenderTableSection;
+class TableLayout;
+
+class RenderTable : public RenderBlock {
+public:
+    enum Rules {
+        None    = 0x00,
+        RGroups = 0x01,
+        CGroups = 0x02,
+        Groups  = 0x03,
+        Rows    = 0x05,
+        Cols    = 0x0a,
+        All     = 0x0f
+    };
+    enum Frame {
+        Void   = 0x00,
+        Above  = 0x01,
+        Below  = 0x02,
+        Lhs    = 0x04,
+        Rhs    = 0x08,
+        Hsides = 0x03,
+        Vsides = 0x0c,
+        Box    = 0x0f
+    };
+
+    RenderTable(Node*);
+    ~RenderTable();
+
+    virtual const char* renderName() const { return "RenderTable"; }
+
+    virtual bool isTable() const { return true; }
+
+    virtual bool avoidsFloats() const { return true; }
+
+    int getColumnPos(int col) const { return m_columnPos[col]; }
+
+    int hBorderSpacing() const { return m_hSpacing; }
+    int vBorderSpacing() const { return m_vSpacing; }
+    
+    bool collapseBorders() const { return style()->borderCollapse(); }
+    int borderLeft() const { return m_borderLeft; }
+    int borderRight() const { return m_borderRight; }
+    int borderTop() const;
+    int borderBottom() const;
+    
+    Rules getRules() const { return static_cast<Rules>(m_rules); }
+
+    const Color& bgColor() const { return style()->backgroundColor(); }
+
+    int outerBorderTop() const;
+    int outerBorderBottom() const;
+    int outerBorderLeft() const;
+    int outerBorderRight() const;
+    
+    int calcBorderLeft() const;
+    int calcBorderRight() const;
+    void recalcHorizontalBorders();
+
+    // overrides
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    virtual void paint(PaintInfo&, int tx, int ty);
+    virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
+    virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
+    virtual void layout();
+    virtual void calcPrefWidths();
+
+    virtual int getBaselineOfFirstLineBox() const;
+
+    virtual RenderBlock* firstLineBlock() const;
+    virtual void updateFirstLetter();
+    
+    virtual void setCellWidths();
+
+    virtual void calcWidth();
+
+    struct ColumnStruct {
+        enum {
+            WidthUndefined = 0xffff
+        };
+
+        ColumnStruct()
+            : span(1)
+            , width(WidthUndefined)
+        {
+        }
+
+        unsigned short span;
+        unsigned width; // the calculated position of the column
+    };
+
+    Vector<ColumnStruct>& columns() { return m_columns; }
+    Vector<int>& columnPositions() { return m_columnPos; }
+    RenderTableSection* header() const { return m_head; }
+    RenderTableSection* footer() const { return m_foot; }
+    RenderTableSection* firstBody() const { return m_firstBody; }
+
+    void splitColumn(int pos, int firstSpan);
+    void appendColumn(int span);
+    int numEffCols() const { return m_columns.size(); }
+    int spanOfEffCol(int effCol) const { return m_columns[effCol].span; }
+    
+    int colToEffCol(int col) const
+    {
+        int i = 0;
+        int effCol = numEffCols();
+        for (int c = 0; c < col && i < effCol; ++i)
+            c += m_columns[i].span;
+        return i;
+    }
+    
+    int effColToCol(int effCol) const
+    {
+        int c = 0;
+        for (int i = 0; i < effCol; i++)
+            c += m_columns[i].span;
+        return c;
+    }
+
+    int bordersPaddingAndSpacing() const
+    {
+        return borderLeft() + borderRight() +
+               (collapseBorders() ? 0 : (paddingLeft() + paddingRight() + (numEffCols() + 1) * hBorderSpacing()));
+    }
+
+    RenderTableCol* colElement(int col, bool* startEdge = 0, bool* endEdge = 0) const;
+
+    bool needsSectionRecalc() const { return m_needsSectionRecalc; }
+    void setNeedsSectionRecalc()
+    {
+        if (documentBeingDestroyed())
+            return;
+        m_needsSectionRecalc = true;
+        setNeedsLayout(true);
+    }
+
+    virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
+
+    RenderTableSection* sectionAbove(const RenderTableSection*, bool skipEmptySections = false) const;
+    RenderTableSection* sectionBelow(const RenderTableSection*, bool skipEmptySections = false) const;
+
+    RenderTableCell* cellAbove(const RenderTableCell*) const;
+    RenderTableCell* cellBelow(const RenderTableCell*) const;
+    RenderTableCell* cellBefore(const RenderTableCell*) const;
+    RenderTableCell* cellAfter(const RenderTableCell*) const;
+ 
+    const CollapsedBorderValue* currentBorderStyle() const { return m_currentBorder; }
+    
+    bool hasSections() const { return m_head || m_foot || m_firstBody; }
+
+    virtual IntRect getOverflowClipRect(int tx, int ty);
+
+    void recalcSectionsIfNeeded() const
+    {
+        if (m_needsSectionRecalc)
+            recalcSections();
+    }
+
+#ifdef ANDROID_LAYOUT
+    void clearSingleColumn() { m_singleColumn = false; }
+    bool isSingleColumn() const { return m_singleColumn; }
+#endif
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+private:
+    void recalcSections() const;
+
+    mutable Vector<int> m_columnPos;
+    mutable Vector<ColumnStruct> m_columns;
+
+    mutable RenderBlock* m_caption;
+    mutable RenderTableSection* m_head;
+    mutable RenderTableSection* m_foot;
+    mutable RenderTableSection* m_firstBody;
+
+    TableLayout* m_tableLayout;
+
+    const CollapsedBorderValue* m_currentBorder;
+    
+    unsigned m_frame : 4; // Frame
+    unsigned m_rules : 4; // Rules
+
+    mutable bool m_hasColElements : 1;
+    mutable bool m_needsSectionRecalc : 1;
+    
+#ifdef ANDROID_LAYOUT
+    bool m_singleColumn;        // BS(Grace): should I use compact version?
+#endif
+    short m_hSpacing;
+    short m_vSpacing;
+    int m_borderLeft;
+    int m_borderRight;
+};
+
+} // namespace WebCore
+
+#endif // RenderTable_h
diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp
new file mode 100644
index 0000000..f8043ee
--- /dev/null
+++ b/WebCore/rendering/RenderTableCell.cpp
@@ -0,0 +1,890 @@
+/**
+ * Copyright (C) 1997 Martin Jones ([email protected])
+ *           (C) 1997 Torben Weis ([email protected])
+ *           (C) 1998 Waldo Bastian ([email protected])
+ *           (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RenderTableCell.h"
+
+#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "HTMLTableCellElement.h"
+#include "RenderTableCol.h"
+#include "RenderView.h"
+
+#ifdef ANDROID_LAYOUT
+#include "Document.h"
+#include "Settings.h"
+#endif
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderTableCell::RenderTableCell(Node* node)
+    : RenderBlock(node)
+    , m_row(-1)
+    , m_column(-1)
+    , m_rowSpan(1)
+    , m_columnSpan(1)
+    , m_topExtra(0)
+    , m_bottomExtra(0)
+    , m_widthChanged(false)
+    , m_percentageHeight(0)
+{
+    updateFromElement();
+}
+
+void RenderTableCell::destroy()
+{
+    RenderTableSection* recalcSection = parent() ? section() : 0;
+
+    RenderBlock::destroy();
+
+    if (recalcSection)
+        recalcSection->setNeedsCellRecalc();
+}
+
+void RenderTableCell::updateFromElement()
+{
+    Node* node = element();
+    if (node && (node->hasTagName(tdTag) || node->hasTagName(thTag))) {
+        HTMLTableCellElement* tc = static_cast<HTMLTableCellElement*>(node);
+        int oldRSpan = m_rowSpan;
+        int oldCSpan = m_columnSpan;
+
+        m_columnSpan = tc->colSpan();
+        m_rowSpan = tc->rowSpan();
+        if ((oldRSpan != m_rowSpan || oldCSpan != m_columnSpan) && style() && parent()) {
+            setNeedsLayoutAndPrefWidthsRecalc();
+            if (section())
+                section()->setNeedsCellRecalc();
+        }
+    }
+}
+
+Length RenderTableCell::styleOrColWidth() const
+{
+    Length w = style()->width();
+    if (colSpan() > 1 || !w.isAuto())
+        return w;
+    RenderTableCol* tableCol = table()->colElement(col());
+    if (tableCol) {
+        w = tableCol->style()->width();
+        
+        // Column widths specified on <col> apply to the border box of the cell.
+        // Percentages don't need to be handled since they're always treated this way (even when specified on the cells).
+        // See Bugzilla bug 8126 for details.
+        if (w.isFixed() && w.value() > 0)
+            w = Length(max(0, w.value() - borderLeft() - borderRight() - paddingLeft() - paddingRight()), Fixed);
+    }
+    return w;
+}
+
+void RenderTableCell::calcPrefWidths()
+{
+    // The child cells rely on the grids up in the sections to do their calcPrefWidths work.  Normally the sections are set up early, as table
+    // cells are added, but relayout can cause the cells to be freed, leaving stale pointers in the sections'
+    // grids.  We must refresh those grids before the child cells try to use them.
+    table()->recalcSectionsIfNeeded();
+
+    RenderBlock::calcPrefWidths();
+    if (element() && style()->autoWrap()) {
+        // See if nowrap was set.
+        Length w = styleOrColWidth();
+        String nowrap = static_cast<Element*>(element())->getAttribute(nowrapAttr);
+        if (!nowrap.isNull() && w.isFixed())
+            // Nowrap is set, but we didn't actually use it because of the
+            // fixed width set on the cell.  Even so, it is a WinIE/Moz trait
+            // to make the minwidth of the cell into the fixed width.  They do this
+            // even in strict mode, so do not make this a quirk.  Affected the top
+            // of hiptop.com.
+            m_minPrefWidth = max(w.value(), m_minPrefWidth);
+    }
+}
+
+void RenderTableCell::calcWidth()
+{
+#ifdef ANDROID_LAYOUT
+    if (view()->frameView()) {
+        const Settings* settings = document()->settings();
+        ASSERT(settings);
+        if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) {
+            m_visibleWidth = view()->frameView()->screenWidth();
+        }
+    }
+#endif
+}
+
+void RenderTableCell::setWidth(int width)
+{
+    if (width != m_width) {
+        m_width = width;
+        m_widthChanged = true;
+    }
+}
+
+void RenderTableCell::layout()
+{
+    layoutBlock(m_widthChanged);
+    m_widthChanged = false;
+}
+
+IntRect RenderTableCell::absoluteClippedOverflowRect()
+{
+    // If the table grid is dirty, we cannot get reliable information about adjoining cells,
+    // so we ignore outside borders. This should not be a problem because it means that
+    // the table is going to recalculate the grid, relayout and repaint its current rect, which
+    // includes any outside borders of this cell.
+    if (!table()->collapseBorders() || table()->needsSectionRecalc())
+        return RenderBlock::absoluteClippedOverflowRect();
+
+    bool rtl = table()->style()->direction() == RTL;
+    int outlineSize = style()->outlineSize();
+    int left = max(borderHalfLeft(true), outlineSize);
+    int right = max(borderHalfRight(true), outlineSize);
+    int top = max(borderHalfTop(true), outlineSize);
+    int bottom = max(borderHalfBottom(true), outlineSize);
+    if (left && !rtl || right && rtl) {
+        if (RenderTableCell* before = table()->cellBefore(this)) {
+            top = max(top, before->borderHalfTop(true));
+            bottom = max(bottom, before->borderHalfBottom(true));
+        }
+    }
+    if (left && rtl || right && !rtl) {
+        if (RenderTableCell* after = table()->cellAfter(this)) {
+            top = max(top, after->borderHalfTop(true));
+            bottom = max(bottom, after->borderHalfBottom(true));
+        }
+    }
+    if (top) {
+        if (RenderTableCell* above = table()->cellAbove(this)) {
+            left = max(left, above->borderHalfLeft(true));
+            right = max(right, above->borderHalfRight(true));
+        }
+    }
+    if (bottom) {
+        if (RenderTableCell* below = table()->cellBelow(this)) {
+            left = max(left, below->borderHalfLeft(true));
+            right = max(right, below->borderHalfRight(true));
+        }
+    }
+    left = max(left, -overflowLeft(false));
+    top = max(top, -overflowTop(false) - borderTopExtra());
+    IntRect r(-left, -borderTopExtra() - top, left + max(width() + right, overflowWidth(false)), borderTopExtra() + top + max(height() + bottom + borderBottomExtra(), overflowHeight(false)));
+
+    if (RenderView* v = view())
+        r.move(v->layoutDelta());
+
+    computeAbsoluteRepaintRect(r);
+    return r;
+}
+
+void RenderTableCell::computeAbsoluteRepaintRect(IntRect& r, bool fixed)
+{
+    r.setY(r.y() + m_topExtra);
+    RenderView* v = view();
+    if ((!v || !v->layoutState()) && parent())
+        r.move(-parent()->xPos(), -parent()->yPos()); // Rows are in the same coordinate space, so don't add their offset in.
+    RenderBlock::computeAbsoluteRepaintRect(r, fixed);
+}
+
+bool RenderTableCell::absolutePosition(int& xPos, int& yPos, bool fixed) const
+{
+    bool result = RenderBlock::absolutePosition(xPos, yPos, fixed);
+    RenderView* v = view();
+    if ((!v || !v->layoutState()) && parent()) {
+        xPos -= parent()->xPos(); // Rows are in the same coordinate space, so don't add their offset in.
+        yPos -= parent()->yPos();
+    }
+    return result;
+}
+
+int RenderTableCell::baselinePosition(bool /*firstLine*/, bool /*isRootLineBox*/) const
+{
+    // <http://www.w3.org/TR/2007/CR-CSS21-20070719/tables.html#height-layout>: The baseline of a cell is the baseline of
+    // the first in-flow line box in the cell, or the first in-flow table-row in the cell, whichever comes first. If there
+    // is no such line box or table-row, the baseline is the bottom of content edge of the cell box.
+
+    int firstLineBaseline = getBaselineOfFirstLineBox();
+    if (firstLineBaseline != -1)
+        return firstLineBaseline;
+
+    return paddingTop() + borderTop() + contentHeight();
+}
+
+void RenderTableCell::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+{
+    if (parent() && section() && style() && style()->height() != newStyle->height())
+        section()->setNeedsCellRecalc();
+
+    ASSERT(newStyle->display() == TABLE_CELL);
+
+    RenderBlock::styleWillChange(diff, newStyle);
+}
+
+void RenderTableCell::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    setHasBoxDecorations(true);
+}
+
+bool RenderTableCell::requiresLayer()
+{
+    return isPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection();
+}
+
+// The following rules apply for resolving conflicts and figuring out which border
+// to use.
+// (1) Borders with the 'border-style' of 'hidden' take precedence over all other conflicting 
+// borders. Any border with this value suppresses all borders at this location.
+// (2) Borders with a style of 'none' have the lowest priority. Only if the border properties of all 
+// the elements meeting at this edge are 'none' will the border be omitted (but note that 'none' is 
+// the default value for the border style.)
+// (3) If none of the styles are 'hidden' and at least one of them is not 'none', then narrow borders 
+// are discarded in favor of wider ones. If several have the same 'border-width' then styles are preferred 
+// in this order: 'double', 'solid', 'dashed', 'dotted', 'ridge', 'outset', 'groove', and the lowest: 'inset'.
+// (4) If border styles differ only in color, then a style set on a cell wins over one on a row, 
+// which wins over a row group, column, column group and, lastly, table. It is undefined which color 
+// is used when two elements of the same type disagree.
+static CollapsedBorderValue compareBorders(const CollapsedBorderValue& border1, const CollapsedBorderValue& border2)
+{
+    // Sanity check the values passed in.  If either is null, return the other.
+    if (!border2.exists())
+        return border1;
+    if (!border1.exists())
+        return border2;
+
+    // Rule #1 above.
+    if (border1.style() == BHIDDEN || border2.style() == BHIDDEN)
+        return CollapsedBorderValue(); // No border should exist at this location.
+    
+    // Rule #2 above.  A style of 'none' has lowest priority and always loses to any other border.
+    if (border2.style() == BNONE)
+        return border1;
+    if (border1.style() == BNONE)
+        return border2;
+
+    // The first part of rule #3 above. Wider borders win.
+    if (border1.width() != border2.width())
+        return border1.width() > border2.width() ? border1 : border2;
+    
+    // The borders have equal width.  Sort by border style.
+    if (border1.style() != border2.style())
+        return border1.style() > border2.style() ? border1 : border2;
+    
+    // The border have the same width and style.  Rely on precedence (cell over row over row group, etc.)
+    return border1.precedence >= border2.precedence ? border1 : border2;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedLeftBorder(bool rtl) const
+{
+    RenderTable* tableElt = table();
+    bool leftmostColumn;
+    if (!rtl)
+        leftmostColumn = col() == 0;
+    else {
+        int effCol = tableElt->colToEffCol(col() + colSpan() - 1);
+        leftmostColumn = effCol == tableElt->numEffCols() - 1;
+    }
+    
+    // For border left, we need to check, in order of precedence:
+    // (1) Our left border.
+    CollapsedBorderValue result(&style()->borderLeft(), BCELL);
+    
+    // (2) The right border of the cell to the left.
+    RenderTableCell* prevCell = rtl ? tableElt->cellAfter(this) : tableElt->cellBefore(this);
+    if (prevCell) {
+        result = rtl ? compareBorders(result, CollapsedBorderValue(&prevCell->style()->borderRight(), BCELL)) : compareBorders(CollapsedBorderValue(&prevCell->style()->borderRight(), BCELL), result);
+        if (!result.exists())
+            return result;
+    } else if (leftmostColumn) {
+        // (3) Our row's left border.
+        result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderLeft(), BROW));
+        if (!result.exists())
+            return result;
+        
+        // (4) Our row group's left border.
+        result = compareBorders(result, CollapsedBorderValue(&section()->style()->borderLeft(), BROWGROUP));
+        if (!result.exists())
+            return result;
+    }
+    
+    // (5) Our column and column group's left borders.
+    bool startColEdge;
+    bool endColEdge;
+    RenderTableCol* colElt = tableElt->colElement(col() + (rtl ? colSpan() - 1 : 0), &startColEdge, &endColEdge);
+    if (colElt && (!rtl ? startColEdge : endColEdge)) {
+        result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL));
+        if (!result.exists())
+            return result;
+        if (colElt->parent()->isTableCol() && (!rtl ? !colElt->previousSibling() : !colElt->nextSibling())) {
+            result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderLeft(), BCOLGROUP));
+            if (!result.exists())
+                return result;
+        }
+    }
+    
+    // (6) The right border of the column to the left.
+    if (!leftmostColumn) {
+        colElt = tableElt->colElement(col() + (rtl ? colSpan() : -1), &startColEdge, &endColEdge);
+        if (colElt && (!rtl ? endColEdge : startColEdge)) {
+            result = rtl ? compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL)) : compareBorders(CollapsedBorderValue(&colElt->style()->borderRight(), BCOL), result);
+            if (!result.exists())
+                return result;
+        }
+    } else {
+        // (7) The table's left border.
+        result = compareBorders(result, CollapsedBorderValue(&tableElt->style()->borderLeft(), BTABLE));
+        if (!result.exists())
+            return result;
+    }
+    
+    return result;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedRightBorder(bool rtl) const
+{
+    RenderTable* tableElt = table();
+    bool rightmostColumn;
+    if (rtl)
+        rightmostColumn = col() == 0;
+    else {
+        int effCol = tableElt->colToEffCol(col() + colSpan() - 1);
+        rightmostColumn = effCol == tableElt->numEffCols() - 1;
+    }
+    
+    // For border right, we need to check, in order of precedence:
+    // (1) Our right border.
+    CollapsedBorderValue result = CollapsedBorderValue(&style()->borderRight(), BCELL);
+    
+    // (2) The left border of the cell to the right.
+    if (!rightmostColumn) {
+        RenderTableCell* nextCell = rtl ? tableElt->cellBefore(this) : tableElt->cellAfter(this);
+        if (nextCell && nextCell->style()) {
+            result = rtl ? compareBorders(CollapsedBorderValue(&nextCell->style()->borderLeft(), BCELL), result) : compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderLeft(), BCELL));
+            if (!result.exists())
+                return result;
+        }
+    } else {
+        // (3) Our row's right border.
+        result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderRight(), BROW));
+        if (!result.exists())
+            return result;
+        
+        // (4) Our row group's right border.
+        result = compareBorders(result, CollapsedBorderValue(&section()->style()->borderRight(), BROWGROUP));
+        if (!result.exists())
+            return result;
+    }
+    
+    // (5) Our column and column group's right borders.
+    bool startColEdge;
+    bool endColEdge;
+    RenderTableCol* colElt = tableElt->colElement(col() + (rtl ? 0 : colSpan() - 1), &startColEdge, &endColEdge);
+    if (colElt && (!rtl ? endColEdge : startColEdge)) {
+        result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL));
+        if (!result.exists())
+            return result;
+        if (colElt->parent()->isTableCol() && (!rtl ? !colElt->nextSibling() : !colElt->previousSibling())) {
+            result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderRight(), BCOLGROUP));
+            if (!result.exists())
+                return result;
+        }
+    }
+    
+    // (6) The left border of the column to the right.
+    if (!rightmostColumn) {
+        colElt = tableElt->colElement(col() + (rtl ? -1 : colSpan()), &startColEdge, &endColEdge);
+        if (colElt && (!rtl ? startColEdge : endColEdge)) {
+            result = rtl ? compareBorders(CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL), result) : compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL));
+            if (!result.exists())
+                return result;
+        }
+    } else {
+        // (7) The table's right border.
+        result = compareBorders(result, CollapsedBorderValue(&tableElt->style()->borderRight(), BTABLE));
+        if (!result.exists())
+            return result;
+    }
+    
+    return result;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedTopBorder() const
+{
+    // For border top, we need to check, in order of precedence:
+    // (1) Our top border.
+    CollapsedBorderValue result = CollapsedBorderValue(&style()->borderTop(), BCELL);
+    
+    RenderTableCell* prevCell = table()->cellAbove(this);
+    if (prevCell) {
+        // (2) A previous cell's bottom border.
+        result = compareBorders(CollapsedBorderValue(&prevCell->style()->borderBottom(), BCELL), result);
+        if (!result.exists()) 
+            return result;
+    }
+    
+    // (3) Our row's top border.
+    result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderTop(), BROW));
+    if (!result.exists())
+        return result;
+    
+    // (4) The previous row's bottom border.
+    if (prevCell) {
+        RenderObject* prevRow = 0;
+        if (prevCell->section() == section())
+            prevRow = parent()->previousSibling();
+        else
+            prevRow = prevCell->section()->lastChild();
+    
+        if (prevRow) {
+            result = compareBorders(CollapsedBorderValue(&prevRow->style()->borderBottom(), BROW), result);
+            if (!result.exists())
+                return result;
+        }
+    }
+    
+    // Now check row groups.
+    RenderTableSection* currSection = section();
+    if (!row()) {
+        // (5) Our row group's top border.
+        result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), BROWGROUP));
+        if (!result.exists())
+            return result;
+        
+        // (6) Previous row group's bottom border.
+        currSection = table()->sectionAbove(currSection);
+        if (currSection) {
+            result = compareBorders(CollapsedBorderValue(&currSection->style()->borderBottom(), BROWGROUP), result);
+            if (!result.exists())
+                return result;
+        }
+    }
+    
+    if (!currSection) {
+        // (8) Our column and column group's top borders.
+        RenderTableCol* colElt = table()->colElement(col());
+        if (colElt) {
+            result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderTop(), BCOL));
+            if (!result.exists())
+                return result;
+            if (colElt->parent()->isTableCol()) {
+                result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderTop(), BCOLGROUP));
+                if (!result.exists())
+                    return result;
+            }
+        }
+        
+        // (9) The table's top border.
+        result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderTop(), BTABLE));
+        if (!result.exists())
+            return result;
+    }
+    
+    return result;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedBottomBorder() const
+{
+    // For border top, we need to check, in order of precedence:
+    // (1) Our bottom border.
+    CollapsedBorderValue result = CollapsedBorderValue(&style()->borderBottom(), BCELL);
+    
+    RenderTableCell* nextCell = table()->cellBelow(this);
+    if (nextCell) {
+        // (2) A following cell's top border.
+        result = compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderTop(), BCELL));
+        if (!result.exists())
+            return result;
+    }
+    
+    // (3) Our row's bottom border. (FIXME: Deal with rowspan!)
+    result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderBottom(), BROW));
+    if (!result.exists())
+        return result;
+    
+    // (4) The next row's top border.
+    if (nextCell) {
+        result = compareBorders(result, CollapsedBorderValue(&nextCell->parent()->style()->borderTop(), BROW));
+        if (!result.exists())
+            return result;
+    }
+    
+    // Now check row groups.
+    RenderTableSection* currSection = section();
+    if (row() + rowSpan() >= static_cast<RenderTableSection*>(currSection)->numRows()) {
+        // (5) Our row group's bottom border.
+        result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderBottom(), BROWGROUP));
+        if (!result.exists())
+            return result;
+        
+        // (6) Following row group's top border.
+        currSection = table()->sectionBelow(currSection);
+        if (currSection) {
+            result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), BROWGROUP));
+            if (!result.exists())
+                return result;
+        }
+    }
+    
+    if (!currSection) {
+        // (8) Our column and column group's bottom borders.
+        RenderTableCol* colElt = table()->colElement(col());
+        if (colElt) {
+            result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderBottom(), BCOL));
+            if (!result.exists()) return result;
+            if (colElt->parent()->isTableCol()) {
+                result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderBottom(), BCOLGROUP));
+                if (!result.exists())
+                    return result;
+            }
+        }
+        
+        // (9) The table's bottom border.
+        result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderBottom(), BTABLE));
+        if (!result.exists())
+            return result;
+    }
+    
+    return result;    
+}
+
+int RenderTableCell::borderLeft() const
+{
+    return table()->collapseBorders() ? borderHalfLeft(false) : RenderBlock::borderLeft();
+}
+
+int RenderTableCell::borderRight() const
+{
+    return table()->collapseBorders() ? borderHalfRight(false) : RenderBlock::borderRight();
+}
+
+int RenderTableCell::borderTop() const
+{
+    return table()->collapseBorders() ? borderHalfTop(false) : RenderBlock::borderTop();
+}
+
+int RenderTableCell::borderBottom() const
+{
+    return table()->collapseBorders() ? borderHalfBottom(false) : RenderBlock::borderBottom();
+}
+
+int RenderTableCell::borderHalfLeft(bool outer) const
+{
+    CollapsedBorderValue border = collapsedLeftBorder(table()->style()->direction() == RTL);
+    if (border.exists())
+        return (border.width() + (outer ? 0 : 1)) / 2; // Give the extra pixel to top and left.
+    return 0;
+}
+    
+int RenderTableCell::borderHalfRight(bool outer) const
+{
+    CollapsedBorderValue border = collapsedRightBorder(table()->style()->direction() == RTL);
+    if (border.exists())
+        return (border.width() + (outer ? 1 : 0)) / 2;
+    return 0;
+}
+
+int RenderTableCell::borderHalfTop(bool outer) const
+{
+    CollapsedBorderValue border = collapsedTopBorder();
+    if (border.exists())
+        return (border.width() + (outer ? 0 : 1)) / 2; // Give the extra pixel to top and left.
+    return 0;
+}
+
+int RenderTableCell::borderHalfBottom(bool outer) const
+{
+    CollapsedBorderValue border = collapsedBottomBorder();
+    if (border.exists())
+        return (border.width() + (outer ? 1 : 0)) / 2;
+    return 0;
+}
+
+void RenderTableCell::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    tx += m_x;
+    ty += m_y;
+
+    // check if we need to do anything at all...
+    int os = 2 * maximalOutlineSize(paintInfo.phase);
+
+    if (paintInfo.phase == PaintPhaseCollapsedTableBorders && style()->visibility() == VISIBLE) {
+        if (ty - table()->outerBorderTop() >= paintInfo.rect.bottom() + os ||
+                ty + m_topExtra + m_height + m_bottomExtra + table()->outerBorderBottom() <= paintInfo.rect.y() - os)
+            return;
+        int w = width();
+        int h = height() + borderTopExtra() + borderBottomExtra();
+        paintCollapsedBorder(paintInfo.context, tx, ty, w, h);
+    } else {
+        if (ty + overflowTop(false) >= paintInfo.rect.bottom() + os || ty + m_topExtra + overflowHeight(false) + m_bottomExtra <= paintInfo.rect.y() - os)
+            return;
+        RenderBlock::paintObject(paintInfo, tx, ty + m_topExtra);
+    }
+}
+
+static EBorderStyle collapsedBorderStyle(EBorderStyle style)
+{
+    if (style == OUTSET)
+        return GROOVE;
+    if (style == INSET)
+        return RIDGE;
+    return style;
+}
+
+struct CollapsedBorder {
+    CollapsedBorderValue borderValue;
+    RenderObject::BorderSide side;
+    bool shouldPaint;
+    int x1;
+    int y1;
+    int x2;
+    int y2;
+    EBorderStyle style;
+};
+
+class CollapsedBorders {
+public:
+    CollapsedBorders()
+        : m_count(0)
+    {
+    }
+    
+    void addBorder(const CollapsedBorderValue& borderValue, RenderObject::BorderSide borderSide, bool shouldPaint,
+                   int x1, int y1, int x2, int y2, EBorderStyle borderStyle)
+    {
+        if (borderValue.exists() && shouldPaint) {
+            m_borders[m_count].borderValue = borderValue;
+            m_borders[m_count].side = borderSide;
+            m_borders[m_count].shouldPaint = shouldPaint;
+            m_borders[m_count].x1 = x1;
+            m_borders[m_count].x2 = x2;
+            m_borders[m_count].y1 = y1;
+            m_borders[m_count].y2 = y2;
+            m_borders[m_count].style = borderStyle;
+            m_count++;
+        }
+    }
+
+    CollapsedBorder* nextBorder()
+    {
+        for (int i = 0; i < m_count; i++) {
+            if (m_borders[i].borderValue.exists() && m_borders[i].shouldPaint) {
+                m_borders[i].shouldPaint = false;
+                return &m_borders[i];
+            }
+        }
+        
+        return 0;
+    }
+    
+    CollapsedBorder m_borders[4];
+    int m_count;
+};
+
+static void addBorderStyle(RenderTableCell::CollapsedBorderStyles& borderStyles, CollapsedBorderValue borderValue)
+{
+    if (!borderValue.exists())
+        return;
+    size_t count = borderStyles.size();
+    for (size_t i = 0; i < count; ++i)
+        if (borderStyles[i] == borderValue)
+            return;
+    borderStyles.append(borderValue);
+}
+
+void RenderTableCell::collectBorderStyles(CollapsedBorderStyles& borderStyles) const
+{
+    bool rtl = table()->style()->direction() == RTL;
+    addBorderStyle(borderStyles, collapsedLeftBorder(rtl));
+    addBorderStyle(borderStyles, collapsedRightBorder(rtl));
+    addBorderStyle(borderStyles, collapsedTopBorder());
+    addBorderStyle(borderStyles, collapsedBottomBorder());
+}
+
+static int compareBorderStylesForQSort(const void* pa, const void* pb)
+{
+    const CollapsedBorderValue* a = static_cast<const CollapsedBorderValue*>(pa);
+    const CollapsedBorderValue* b = static_cast<const CollapsedBorderValue*>(pb);
+    if (*a == *b)
+        return 0;
+    CollapsedBorderValue borderWithHigherPrecedence = compareBorders(*a, *b);
+#ifdef ANDROID_FIX
+    if (*a == borderWithHigherPrecedence) {
+        // klibc uses a combsort for quicksort and requires that two values always give the same answer
+        // regardless of comparison order. Unfortunately, compareBorders does not honor that requirement.
+        // Call compareBorders again with reversed parameters. If it returns the first value again then
+        // we can assume the values are equal. http://bugs.webkit.org/show_bug.cgi?id=13147
+        CollapsedBorderValue qSortHack = compareBorders(*b, *a);
+        if (*b == qSortHack)
+            return 0;
+        return 1;
+    }
+#else
+    if (*a == borderWithHigherPrecedence)
+        return 1;
+#endif
+    return -1;
+}
+
+void RenderTableCell::sortBorderStyles(CollapsedBorderStyles& borderStyles)
+{
+    qsort(borderStyles.data(), borderStyles.size(), sizeof(CollapsedBorderValue),
+        compareBorderStylesForQSort);
+}
+
+void RenderTableCell::paintCollapsedBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h)
+{
+    if (!table()->currentBorderStyle())
+        return;
+    
+    bool rtl = table()->style()->direction() == RTL;
+    CollapsedBorderValue leftVal = collapsedLeftBorder(rtl);
+    CollapsedBorderValue rightVal = collapsedRightBorder(rtl);
+    CollapsedBorderValue topVal = collapsedTopBorder();
+    CollapsedBorderValue bottomVal = collapsedBottomBorder();
+     
+    // Adjust our x/y/width/height so that we paint the collapsed borders at the correct location.
+    int topWidth = topVal.width();
+    int bottomWidth = bottomVal.width();
+    int leftWidth = leftVal.width();
+    int rightWidth = rightVal.width();
+    
+    tx -= leftWidth / 2;
+    ty -= topWidth / 2;
+    w += leftWidth / 2 + (rightWidth + 1) / 2;
+    h += topWidth / 2 + (bottomWidth + 1) / 2;
+    
+    EBorderStyle topStyle = collapsedBorderStyle(topVal.style());
+    EBorderStyle bottomStyle = collapsedBorderStyle(bottomVal.style());
+    EBorderStyle leftStyle = collapsedBorderStyle(leftVal.style());
+    EBorderStyle rightStyle = collapsedBorderStyle(rightVal.style());
+    
+    bool renderTop = topStyle > BHIDDEN && !topVal.isTransparent();
+    bool renderBottom = bottomStyle > BHIDDEN && !bottomVal.isTransparent();
+    bool renderLeft = leftStyle > BHIDDEN && !leftVal.isTransparent();
+    bool renderRight = rightStyle > BHIDDEN && !rightVal.isTransparent();
+
+    // We never paint diagonals at the joins.  We simply let the border with the highest
+    // precedence paint on top of borders with lower precedence.  
+    CollapsedBorders borders;
+    borders.addBorder(topVal, BSTop, renderTop, tx, ty, tx + w, ty + topWidth, topStyle);
+    borders.addBorder(bottomVal, BSBottom, renderBottom, tx, ty + h - bottomWidth, tx + w, ty + h, bottomStyle);
+    borders.addBorder(leftVal, BSLeft, renderLeft, tx, ty, tx + leftWidth, ty + h, leftStyle);
+    borders.addBorder(rightVal, BSRight, renderRight, tx + w - rightWidth, ty, tx + w, ty + h, rightStyle);
+    
+    for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) {
+        if (border->borderValue == *table()->currentBorderStyle())
+            drawBorder(graphicsContext, border->x1, border->y1, border->x2, border->y2, border->side, 
+                       border->borderValue.color(), style()->color(), border->style, 0, 0);
+    }
+}
+
+void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, int tx, int ty, RenderObject* backgroundObject)
+{
+    if (!backgroundObject)
+        return;
+
+    if (style()->visibility() != VISIBLE)
+        return;
+
+    RenderTable* tableElt = table();
+    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
+        return;
+
+    if (backgroundObject != this) {
+        tx += m_x;
+        ty += m_y + m_topExtra;
+    }
+
+    int w = width();
+    int h = height() + borderTopExtra() + borderBottomExtra();
+    ty -= borderTopExtra();
+
+    int my = max(ty, paintInfo.rect.y());
+    int end = min(paintInfo.rect.bottom(), ty + h);
+    int mh = end - my;
+
+    Color c = backgroundObject->style()->backgroundColor();
+    const FillLayer* bgLayer = backgroundObject->style()->backgroundLayers();
+
+    if (bgLayer->hasImage() || c.isValid()) {
+        // We have to clip here because the background would paint
+        // on top of the borders otherwise.  This only matters for cells and rows.
+        bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == this || backgroundObject == parent()) && tableElt->collapseBorders();
+        if (shouldClip) {
+            IntRect clipRect(tx + borderLeft(), ty + borderTop(),
+                w - borderLeft() - borderRight(), h - borderTop() - borderBottom());
+            paintInfo.context->save();
+            paintInfo.context->clip(clipRect);
+        }
+        paintFillLayers(paintInfo, c, bgLayer, my, mh, tx, ty, w, h);
+        if (shouldClip)
+            paintInfo.context->restore();
+    }
+}
+
+void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
+{
+    RenderTable* tableElt = table();
+    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
+        return;
+
+    int w = width();
+    int h = height() + borderTopExtra() + borderBottomExtra();
+   
+    if (style()->boxShadow())
+        paintBoxShadow(paintInfo.context, tx, ty - borderTopExtra(), w, h, style());
+    
+    // Paint our cell background.
+    paintBackgroundsBehindCell(paintInfo, tx, ty, this);
+
+    if (!style()->hasBorder() || tableElt->collapseBorders())
+        return;
+
+    ty -= borderTopExtra();
+    paintBorder(paintInfo.context, tx, ty, w, h, style());
+}
+
+void RenderTableCell::paintMask(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+        return;
+
+    RenderTable* tableElt = table();
+    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
+        return;
+
+    int w = width();
+    int h = height() + borderTopExtra() + borderBottomExtra();
+   
+    int my = max(ty, paintInfo.rect.y());
+    int end = min(paintInfo.rect.bottom(), ty + h);
+    int mh = end - my;
+
+    paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderTableCell.h b/WebCore/rendering/RenderTableCell.h
new file mode 100644
index 0000000..eb093fb
--- /dev/null
+++ b/WebCore/rendering/RenderTableCell.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 1997 Martin Jones ([email protected])
+ *           (C) 1997 Torben Weis ([email protected])
+ *           (C) 1998 Waldo Bastian ([email protected])
+ *           (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RenderTableCell_h
+#define RenderTableCell_h
+
+#include "RenderTableSection.h"
+
+namespace WebCore {
+
+class RenderTableCell : public RenderBlock {
+public:
+    RenderTableCell(Node*);
+
+    virtual const char* renderName() const { return isAnonymous() ? "RenderTableCell (anonymous)" : "RenderTableCell"; }
+
+    virtual bool isTableCell() const { return true; }
+
+    virtual void destroy();
+
+    // FIXME: need to implement cellIndex
+    int cellIndex() const { return 0; }
+    void setCellIndex(int) { }
+
+    int colSpan() const { return m_columnSpan; }
+    void setColSpan(int c) { m_columnSpan = c; }
+
+    int rowSpan() const { return m_rowSpan; }
+    void setRowSpan(int r) { m_rowSpan = r; }
+
+    int col() const { return m_column; }
+    void setCol(int col) { m_column = col; }
+    int row() const { return m_row; }
+    void setRow(int row) { m_row = row; }
+
+    RenderTableSection* section() const { return static_cast<RenderTableSection*>(parent()->parent()); }
+    RenderTable* table() const { return static_cast<RenderTable*>(parent()->parent()->parent()); }
+
+    Length styleOrColWidth() const;
+
+    virtual bool requiresLayer();
+
+    virtual void calcPrefWidths();
+    virtual void calcWidth();
+    virtual void setWidth(int);
+
+#ifdef ANDROID_LAYOUT
+    // RenderTableSection needs to access this in setCellWidths()
+    int getVisibleWidth() { return m_visibleWidth; }
+#endif    
+
+    virtual bool expandsToEncloseOverhangingFloats() const { return true; }
+
+    int borderLeft() const;
+    int borderRight() const;
+    int borderTop() const;
+    int borderBottom() const;
+
+    int borderHalfLeft(bool outer) const;
+    int borderHalfRight(bool outer) const;
+    int borderHalfTop(bool outer) const;
+    int borderHalfBottom(bool outer) const;
+
+    CollapsedBorderValue collapsedLeftBorder(bool rtl) const;
+    CollapsedBorderValue collapsedRightBorder(bool rtl) const;
+    CollapsedBorderValue collapsedTopBorder() const;
+    CollapsedBorderValue collapsedBottomBorder() const;
+
+    typedef Vector<CollapsedBorderValue, 100> CollapsedBorderStyles;
+    void collectBorderStyles(CollapsedBorderStyles&) const;
+    static void sortBorderStyles(CollapsedBorderStyles&);
+
+    virtual void updateFromElement();
+
+    virtual void layout();
+
+    virtual void paint(PaintInfo&, int tx, int ty);
+    virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
+    virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
+    void paintCollapsedBorder(GraphicsContext*, int x, int y, int w, int h);
+    void paintBackgroundsBehindCell(PaintInfo&, int tx, int ty, RenderObject* backgroundObject);
+
+    // Lie about position to outside observers.
+    virtual int yPos() const { return m_y + m_topExtra; }
+
+    virtual IntRect absoluteClippedOverflowRect();
+    virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed = false);
+    virtual bool absolutePosition(int& x, int& y, bool fixed = false) const;
+
+    virtual int baselinePosition(bool firstLine = false, bool isRootLineBox = false) const;
+
+    void setCellTopExtra(int p) { m_topExtra = p; }
+    void setCellBottomExtra(int p) { m_bottomExtra = p; }
+
+    virtual int borderTopExtra() const { return m_topExtra; }
+    virtual int borderBottomExtra() const { return m_bottomExtra; }
+
+protected:
+    virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+private:
+    int m_row;
+    int m_column;
+    int m_rowSpan;
+    int m_columnSpan;
+    int m_topExtra : 31;
+    int m_bottomExtra : 31;
+    bool m_widthChanged : 1;
+    int m_percentageHeight;
+};
+
+} // namespace WebCore
+
+#endif // RenderTableCell_h
diff --git a/WebCore/rendering/RenderTableCol.cpp b/WebCore/rendering/RenderTableCol.cpp
new file mode 100644
index 0000000..0d714da
--- /dev/null
+++ b/WebCore/rendering/RenderTableCol.cpp
@@ -0,0 +1,92 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1997 Martin Jones ([email protected])
+ *           (C) 1997 Torben Weis ([email protected])
+ *           (C) 1998 Waldo Bastian ([email protected])
+ *           (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RenderTableCol.h"
+
+#include "CachedImage.h"
+#include "HTMLNames.h"
+#include "HTMLTableColElement.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderTableCol::RenderTableCol(Node* node)
+    : RenderContainer(node), m_span(1)
+{
+    // init RenderObject attributes
+    setInline(true); // our object is not Inline
+    updateFromElement();
+}
+
+void RenderTableCol::updateFromElement()
+{
+    int oldSpan = m_span;
+    Node* node = element();
+    if (node && (node->hasTagName(colTag) || node->hasTagName(colgroupTag))) {
+        HTMLTableColElement* tc = static_cast<HTMLTableColElement*>(node);
+        m_span = tc->span();
+    } else
+        m_span = !(style() && style()->display() == TABLE_COLUMN_GROUP);
+    if (m_span != oldSpan && style() && parent())
+        setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+bool RenderTableCol::isChildAllowed(RenderObject* child, RenderStyle* style) const
+{
+    return !child->isText() && style && (style->display() == TABLE_COLUMN);
+}
+
+bool RenderTableCol::canHaveChildren() const
+{
+    // Cols cannot have children. This is actually necessary to fix a bug
+    // with libraries.uc.edu, which makes a <p> be a table-column.
+    return style()->display() == TABLE_COLUMN_GROUP;
+}
+
+IntRect RenderTableCol::absoluteClippedOverflowRect()
+{
+    // For now, just repaint the whole table.
+    // FIXME: Find a better way to do this, e.g., need to repaint all the cells that we
+    // might have propagated a background color or borders into.
+    RenderObject* table = parent();
+    if (table && !table->isTable())
+        table = table->parent();
+    if (table && table->isTable())
+        return table->absoluteClippedOverflowRect();
+
+    return IntRect();
+}
+
+void RenderTableCol::imageChanged(WrappedImagePtr image)
+{
+    // FIXME: Repaint only the rect the image paints in.
+    repaint();
+}
+
+}
diff --git a/WebCore/rendering/RenderTableCol.h b/WebCore/rendering/RenderTableCol.h
new file mode 100644
index 0000000..9d46e2b
--- /dev/null
+++ b/WebCore/rendering/RenderTableCol.h
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1997 Martin Jones ([email protected])
+ *           (C) 1997 Torben Weis ([email protected])
+ *           (C) 1998 Waldo Bastian ([email protected])
+ *           (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RenderTableCol_h
+#define RenderTableCol_h
+
+#include "RenderContainer.h"
+
+namespace WebCore {
+
+class RenderTableCol : public RenderContainer
+{
+public:
+    RenderTableCol(Node*);
+
+    virtual const char* renderName() const { return "RenderTableCol"; }
+    virtual bool isTableCol() const { return true; }
+    virtual int lineHeight(bool) const { return 0; }
+    virtual void updateFromElement();
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+    virtual bool canHaveChildren() const;
+    virtual bool requiresLayer() { return false; }
+
+    virtual IntRect absoluteClippedOverflowRect();
+    virtual void imageChanged(WrappedImagePtr);
+
+    int span() const { return m_span; }
+    void setSpan(int s) { m_span = s; }
+    
+private:
+    int m_span;
+};
+
+}
+
+#endif
diff --git a/WebCore/rendering/RenderTableRow.cpp b/WebCore/rendering/RenderTableRow.cpp
new file mode 100644
index 0000000..4e9323d
--- /dev/null
+++ b/WebCore/rendering/RenderTableRow.cpp
@@ -0,0 +1,210 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1997 Martin Jones ([email protected])
+ *           (C) 1997 Torben Weis ([email protected])
+ *           (C) 1998 Waldo Bastian ([email protected])
+ *           (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RenderTableRow.h"
+
+#include "CachedImage.h"
+#include "Document.h"
+#include "HTMLNames.h"
+#include "RenderTableCell.h"
+#include "RenderView.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderTableRow::RenderTableRow(Node* node)
+    : RenderContainer(node)
+{
+    // init RenderObject attributes
+    setInline(false);   // our object is not Inline
+}
+
+void RenderTableRow::destroy()
+{
+    RenderTableSection* recalcSection = section();
+    
+    RenderContainer::destroy();
+    
+    if (recalcSection)
+        recalcSection->setNeedsCellRecalc();
+}
+
+void RenderTableRow::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+{
+    if (section() && style() && style()->height() != newStyle->height())
+        section()->setNeedsCellRecalc();
+
+    ASSERT(newStyle->display() == TABLE_ROW);
+
+    RenderContainer::styleWillChange(diff, newStyle);
+}
+
+void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    // Make sure we don't append things after :after-generated content if we have it.
+    if (!beforeChild && isAfterContent(lastChild()))
+        beforeChild = lastChild();
+
+    bool isTableRow = element() && element()->hasTagName(trTag);
+    
+    if (!child->isTableCell()) {
+        if (isTableRow && child->element() && child->element()->hasTagName(formTag) && document()->isHTMLDocument()) {
+            RenderContainer::addChild(child, beforeChild);
+            return;
+        }
+
+        RenderObject* last = beforeChild;
+        if (!last)
+            last = lastChild();
+        if (last && last->isAnonymous() && last->isTableCell()) {
+            last->addChild(child);
+            return;
+        }
+
+        // If beforeChild is inside an anonymous cell, insert into the cell.
+        if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous()) {
+            last->parent()->addChild(child, beforeChild);
+            return;
+        }
+
+        RenderTableCell* cell = new (renderArena()) RenderTableCell(document() /* anonymous object */);
+        RefPtr<RenderStyle> newStyle = RenderStyle::create();
+        newStyle->inheritFrom(style());
+        newStyle->setDisplay(TABLE_CELL);
+        cell->setStyle(newStyle.release());
+        addChild(cell, beforeChild);
+        cell->addChild(child);
+        return;
+    } 
+    
+    // If the next renderer is actually wrapped in an anonymous table cell, we need to go up and find that.
+    while (beforeChild && beforeChild->parent() != this)
+        beforeChild = beforeChild->parent();
+
+    RenderTableCell* cell = static_cast<RenderTableCell*>(child);
+
+    // Generated content can result in us having a null section so make sure to null check our parent.
+    if (parent())
+        section()->addCell(cell, this);
+
+    ASSERT(!beforeChild || beforeChild->isTableCell() || isTableRow && beforeChild->element() && beforeChild->element()->hasTagName(formTag) && document()->isHTMLDocument());
+    RenderContainer::addChild(cell, beforeChild);
+
+    if (beforeChild || nextSibling())
+        section()->setNeedsCellRecalc();
+}
+
+void RenderTableRow::layout()
+{
+    ASSERT(needsLayout());
+
+    // Table rows do not add translation.
+    view()->pushLayoutState(this, IntSize());
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isTableCell()) {
+            RenderTableCell* cell = static_cast<RenderTableCell*>(child);
+            if (child->needsLayout()) {
+                cell->calcVerticalMargins();
+                cell->layout();
+            }
+        }
+    }
+
+    // We only ever need to repaint if our cells didn't, which menas that they didn't need
+    // layout, so we know that our bounds didn't change. This code is just making up for
+    // the fact that we did not repaint in setStyle() because we had a layout hint.
+    // We cannot call repaint() because our absoluteClippedOverflowRect() is taken from the
+    // parent table, and being mid-layout, that is invalid. Instead, we repaint our cells.
+    if (selfNeedsLayout() && checkForRepaintDuringLayout()) {
+        for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+            if (child->isTableCell())
+                child->repaint();
+        }
+    }
+
+    view()->popLayoutState();
+    setNeedsLayout(false);
+}
+
+IntRect RenderTableRow::absoluteClippedOverflowRect()
+{
+    // For now, just repaint the whole table.
+    // FIXME: Find a better way to do this, e.g., need to repaint all the cells that we
+    // might have propagated a background color into.
+    if (RenderTable* parentTable = table())
+        return parentTable->absoluteClippedOverflowRect();
+
+    return IntRect();
+}
+
+// Hit Testing
+bool RenderTableRow::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction action)
+{
+    // Table rows cannot ever be hit tested.  Effectively they do not exist.
+    // Just forward to our children always.
+    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+        // FIXME: We have to skip over inline flows, since they can show up inside table rows
+        // at the moment (a demoted inline <form> for example). If we ever implement a
+        // table-specific hit-test method (which we should do for performance reasons anyway),
+        // then we can remove this check.
+        if (!child->hasLayer() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
+            updateHitTestResult(result, IntPoint(x - tx, y - ty));
+            return true;
+        }
+    }
+    
+    return false;
+}
+
+void RenderTableRow::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    ASSERT(m_layer);
+    if (!m_layer)
+        return;
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isTableCell()) {
+            // Paint the row background behind the cell.
+            if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseChildBlockBackground) {
+                RenderTableCell* cell = static_cast<RenderTableCell*>(child);
+                cell->paintBackgroundsBehindCell(paintInfo, tx, ty, this);
+            }
+            if (!child->hasLayer())
+                child->paint(paintInfo, tx, ty);
+        }
+    }
+}
+
+void RenderTableRow::imageChanged(WrappedImagePtr image)
+{
+    // FIXME: Examine cells and repaint only the rect the image paints in.
+    repaint();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderTableRow.h b/WebCore/rendering/RenderTableRow.h
new file mode 100644
index 0000000..99482be
--- /dev/null
+++ b/WebCore/rendering/RenderTableRow.h
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1997 Martin Jones ([email protected])
+ *           (C) 1997 Torben Weis ([email protected])
+ *           (C) 1998 Waldo Bastian ([email protected])
+ *           (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RenderTableRow_h
+#define RenderTableRow_h
+
+#include "RenderTableSection.h"
+
+namespace WebCore {
+
+class RenderTableRow : public RenderContainer {
+public:
+    RenderTableRow(Node*);
+
+    virtual const char* renderName() const { return isAnonymous() ? "RenderTableRow (anonymous)" : "RenderTableRow"; }
+
+    virtual bool isTableRow() const { return true; }
+
+    virtual void destroy();
+
+    RenderTableSection* section() const { return static_cast<RenderTableSection*>(parent()); }
+    RenderTable* table() const { return static_cast<RenderTable*>(parent()->parent()); }
+
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const { return 0; }
+    virtual void position(InlineBox*) { }
+    virtual void layout();
+    virtual IntRect absoluteClippedOverflowRect();
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+    // The only time rows get a layer is when they have transparency.
+    virtual bool requiresLayer() { return isTransparent() || hasOverflowClip(); }
+
+    virtual void paint(PaintInfo&, int tx, int ty);
+    virtual void imageChanged(WrappedImagePtr);
+
+protected:
+    virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
+
+};
+
+} // namespace WebCore
+
+#endif // RenderTableRow_h
diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp
new file mode 100644
index 0000000..acc5596
--- /dev/null
+++ b/WebCore/rendering/RenderTableSection.cpp
@@ -0,0 +1,1181 @@
+/*
+ * Copyright (C) 1997 Martin Jones ([email protected])
+ *           (C) 1997 Torben Weis ([email protected])
+ *           (C) 1998 Waldo Bastian ([email protected])
+ *           (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RenderTableSection.h"
+
+#include "CachedImage.h"
+#include "Document.h"
+#include "HTMLNames.h"
+#include "RenderTableCell.h"
+#include "RenderTableCol.h"
+#include "RenderTableRow.h"
+#include "RenderView.h"
+#include <limits>
+#include <wtf/Vector.h>
+#ifdef ANDROID_LAYOUT
+#include "Frame.h"
+#include "Settings.h"
+#endif
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderTableSection::RenderTableSection(Node* node)
+    : RenderContainer(node)
+    , m_gridRows(0)
+    , m_cCol(0)
+    , m_cRow(-1)
+    , m_needsCellRecalc(false)
+    , m_outerBorderLeft(0)
+    , m_outerBorderRight(0)
+    , m_outerBorderTop(0)
+    , m_outerBorderBottom(0)
+    , m_overflowLeft(0)
+    , m_overflowWidth(0)
+    , m_overflowTop(0)
+    , m_overflowHeight(0)
+    , m_hasOverflowingCell(false)
+{
+    // init RenderObject attributes
+    setInline(false);   // our object is not Inline
+}
+
+RenderTableSection::~RenderTableSection()
+{
+    clearGrid();
+}
+
+void RenderTableSection::destroy()
+{
+    RenderTable* recalcTable = table();
+    
+    RenderContainer::destroy();
+    
+    // recalc cell info because RenderTable has unguarded pointers
+    // stored that point to this RenderTableSection.
+    if (recalcTable)
+        recalcTable->setNeedsSectionRecalc();
+}
+
+void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    // Make sure we don't append things after :after-generated content if we have it.
+    if (!beforeChild && isAfterContent(lastChild()))
+        beforeChild = lastChild();
+
+    bool isTableSection = element() && (element()->hasTagName(theadTag) || element()->hasTagName(tbodyTag) || element()->hasTagName(tfootTag));
+
+    if (!child->isTableRow()) {
+        if (isTableSection && child->element() && child->element()->hasTagName(formTag) && document()->isHTMLDocument()) {
+            RenderContainer::addChild(child, beforeChild);
+            return;
+        }
+
+        RenderObject* last = beforeChild;
+        if (!last)
+            last = lastChild();
+        if (last && last->isAnonymous()) {
+            last->addChild(child);
+            return;
+        }
+
+        // If beforeChild is inside an anonymous cell/row, insert into the cell or into
+        // the anonymous row containing it, if there is one.
+        RenderObject* lastBox = last;
+        while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow())
+            lastBox = lastBox->parent();
+        if (lastBox && lastBox->isAnonymous()) {
+            lastBox->addChild(child, beforeChild);
+            return;
+        }
+
+        RenderObject* row = new (renderArena()) RenderTableRow(document() /* anonymous table */);
+        RefPtr<RenderStyle> newStyle = RenderStyle::create();
+        newStyle->inheritFrom(style());
+        newStyle->setDisplay(TABLE_ROW);
+        row->setStyle(newStyle.release());
+        addChild(row, beforeChild);
+        row->addChild(child);
+        return;
+    }
+
+    if (beforeChild)
+        setNeedsCellRecalc();
+
+    ++m_cRow;
+    m_cCol = 0;
+
+    // make sure we have enough rows
+    if (!ensureRows(m_cRow + 1))
+        return;
+
+    m_grid[m_cRow].rowRenderer = child;
+
+    if (!beforeChild) {
+        m_grid[m_cRow].height = child->style()->height();
+        if (m_grid[m_cRow].height.isRelative())
+            m_grid[m_cRow].height = Length();
+    }
+
+    // If the next renderer is actually wrapped in an anonymous table row, we need to go up and find that.
+    while (beforeChild && beforeChild->parent() != this)
+        beforeChild = beforeChild->parent();
+
+    ASSERT(!beforeChild || beforeChild->isTableRow() || isTableSection && beforeChild->element() && beforeChild->element()->hasTagName(formTag) && document()->isHTMLDocument());
+    RenderContainer::addChild(child, beforeChild);
+}
+
+bool RenderTableSection::ensureRows(int numRows)
+{
+    int nRows = m_gridRows;
+    if (numRows > nRows) {
+        if (numRows > static_cast<int>(m_grid.size())) {
+            size_t maxSize = numeric_limits<size_t>::max() / sizeof(RowStruct);
+            if (static_cast<size_t>(numRows) > maxSize)
+                return false;
+            m_grid.grow(numRows);
+        }
+        m_gridRows = numRows;
+        int nCols = max(1, table()->numEffCols());
+        CellStruct emptyCellStruct;
+        emptyCellStruct.cell = 0;
+        emptyCellStruct.inColSpan = false;
+        for (int r = nRows; r < numRows; r++) {
+            m_grid[r].row = new Row(nCols);
+            m_grid[r].row->fill(emptyCellStruct);
+            m_grid[r].rowRenderer = 0;
+            m_grid[r].baseline = 0;
+            m_grid[r].height = Length();
+        }
+    }
+
+    return true;
+}
+
+void RenderTableSection::addCell(RenderTableCell* cell, RenderObject* row)
+{
+    int rSpan = cell->rowSpan();
+    int cSpan = cell->colSpan();
+    Vector<RenderTable::ColumnStruct>& columns = table()->columns();
+    int nCols = columns.size();
+
+    // ### mozilla still seems to do the old HTML way, even for strict DTD
+    // (see the annotation on table cell layouting in the CSS specs and the testcase below:
+    // <TABLE border>
+    // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
+    // <TR><TD colspan="2">5
+    // </TABLE>
+
+    while (m_cCol < nCols && (cellAt(m_cRow, m_cCol).cell || cellAt(m_cRow, m_cCol).inColSpan))
+        m_cCol++;
+
+    if (rSpan == 1) {
+        // we ignore height settings on rowspan cells
+        Length height = cell->style()->height();
+        if (height.isPositive() || (height.isRelative() && height.value() >= 0)) {
+            Length cRowHeight = m_grid[m_cRow].height;
+            switch (height.type()) {
+                case Percent:
+                    if (!(cRowHeight.isPercent()) ||
+                        (cRowHeight.isPercent() && cRowHeight.rawValue() < height.rawValue()))
+                        m_grid[m_cRow].height = height;
+                        break;
+                case Fixed:
+                    if (cRowHeight.type() < Percent ||
+                        (cRowHeight.isFixed() && cRowHeight.value() < height.value()))
+                        m_grid[m_cRow].height = height;
+                    break;
+                case Relative:
+                default:
+                    break;
+            }
+        }
+    }
+
+    // make sure we have enough rows
+    if (!ensureRows(m_cRow + rSpan))
+        return;
+
+    m_grid[m_cRow].rowRenderer = row;
+
+    int col = m_cCol;
+    // tell the cell where it is
+    CellStruct currentCell;
+    currentCell.cell = cell;
+    currentCell.inColSpan = false;
+    while (cSpan) {
+        int currentSpan;
+        if (m_cCol >= nCols) {
+            table()->appendColumn(cSpan);
+            currentSpan = cSpan;
+        } else {
+            if (cSpan < columns[m_cCol].span)
+                table()->splitColumn(m_cCol, cSpan);
+            currentSpan = columns[m_cCol].span;
+        }
+
+        for (int r = 0; r < rSpan; r++) {
+            CellStruct& c = cellAt(m_cRow + r, m_cCol);
+            if (currentCell.cell && !c.cell)
+                c.cell = currentCell.cell;
+            if (currentCell.inColSpan)
+                c.inColSpan = true;
+        }
+        m_cCol++;
+        cSpan -= currentSpan;
+        currentCell.cell = 0;
+        currentCell.inColSpan = true;
+    }
+    if (cell) {
+        cell->setRow(m_cRow);
+        cell->setCol(table()->effColToCol(col));
+    }
+}
+
+void RenderTableSection::setCellWidths()
+{
+    Vector<int>& columnPos = table()->columnPositions();
+    bool pushedLayoutState = false;
+
+#ifdef ANDROID_LAYOUT
+    int visibleWidth = 0;
+    if (view()->frameView()) {
+        const Settings* settings = document()->settings();
+        ASSERT(settings);
+        if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) {
+            visibleWidth = view()->frameView()->screenWidth();
+        }
+    }
+#endif
+    
+    for (int i = 0; i < m_gridRows; i++) {
+        Row& row = *m_grid[i].row;
+        int cols = row.size();
+        for (int j = 0; j < cols; j++) {
+            CellStruct current = row[j];
+            RenderTableCell* cell = current.cell;
+
+            if (!cell)
+                continue;
+            int endCol = j;
+            int cspan = cell->colSpan();
+            while (cspan && endCol < cols) {
+                cspan -= table()->columns()[endCol].span;
+                endCol++;
+            }
+            int w = columnPos[endCol] - columnPos[j] - table()->hBorderSpacing();
+#ifdef ANDROID_LAYOUT          
+            if (table()->isSingleColumn())
+                w = table()->width()-(table()->borderLeft()+table()->borderRight()+
+                    (table()->collapseBorders()?0:(table()->paddingLeft()+table()->paddingRight()+
+                    2*table()->hBorderSpacing())));
+#endif          
+            int oldWidth = cell->width();
+#ifdef ANDROID_LAYOUT
+            if (w != oldWidth || (visibleWidth > 0 && visibleWidth != cell->getVisibleWidth())) {
+#else
+            if (w != oldWidth) {
+#endif
+                cell->setNeedsLayout(true);
+                if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout()) {
+                    if (!pushedLayoutState) {
+                        // Technically, we should also push state for the row, but since
+                        // rows don't push a coordinate transform, that's not necessary.
+                        view()->pushLayoutState(this, IntSize(m_x, m_y));
+                        pushedLayoutState = true;
+                    }
+                    cell->repaint();
+                }
+#ifdef ANDROID_LAYOUT
+                if (w != oldWidth)
+                    cell->setWidth(w);
+#else
+                cell->setWidth(w);
+#endif
+            }
+        }
+    }
+    
+    if (pushedLayoutState)
+        view()->popLayoutState();
+}
+
+int RenderTableSection::calcRowHeight()
+{
+#ifdef ANDROID_LAYOUT
+    if (table()->isSingleColumn())
+        return m_rowPos[m_gridRows];
+#endif    
+    RenderTableCell* cell;
+
+    int spacing = table()->vBorderSpacing();
+    bool pushedLayoutState = false;
+
+    m_rowPos.resize(m_gridRows + 1);
+    m_rowPos[0] = spacing;
+
+    for (int r = 0; r < m_gridRows; r++) {
+        m_rowPos[r + 1] = 0;
+        m_grid[r].baseline = 0;
+        int baseline = 0;
+        int bdesc = 0;
+        int ch = m_grid[r].height.calcMinValue(0);
+        int pos = m_rowPos[r] + ch + (m_grid[r].rowRenderer ? spacing : 0);
+
+        m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);
+
+        Row* row = m_grid[r].row;
+        int totalCols = row->size();
+
+        for (int c = 0; c < totalCols; c++) {
+            CellStruct current = cellAt(r, c);
+            cell = current.cell;
+            if (!cell || current.inColSpan)
+                continue;
+            if (r < m_gridRows - 1 && cellAt(r + 1, c).cell == cell)
+                continue;
+
+            int indx = max(r - cell->rowSpan() + 1, 0);
+
+            if (cell->overrideSize() != -1) {
+                if (!pushedLayoutState) {
+                    // Technically, we should also push state for the row, but since
+                    // rows don't push a coordinate transform, that's not necessary.
+                    view()->pushLayoutState(this, IntSize(m_x, m_y));
+                    pushedLayoutState = true;
+                }
+                cell->setOverrideSize(-1);
+                cell->setChildNeedsLayout(true, false);
+                cell->layoutIfNeeded();
+            }
+            
+            // Explicit heights use the border box in quirks mode.  In strict mode do the right
+            // thing and actually add in the border and padding.
+            ch = cell->style()->height().calcValue(0) + 
+                (cell->style()->htmlHacks() ? 0 : (cell->paddingTop() + cell->paddingBottom() +
+                                                   cell->borderTop() + cell->borderBottom()));
+            ch = max(ch, cell->height());
+
+            pos = m_rowPos[indx] + ch + (m_grid[r].rowRenderer ? spacing : 0);
+
+            m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);
+
+            // find out the baseline
+            EVerticalAlign va = cell->style()->verticalAlign();
+            if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
+                int b = cell->baselinePosition();
+                if (b > cell->borderTop() + cell->paddingTop()) {
+                    baseline = max(baseline, b);
+                    bdesc = max(bdesc, m_rowPos[indx] + ch - b);
+                }
+            }
+        }
+
+        //do we have baseline aligned elements?
+        if (baseline) {
+            // increase rowheight if baseline requires
+            m_rowPos[r + 1] = max(m_rowPos[r + 1], baseline + bdesc + (m_grid[r].rowRenderer ? spacing : 0));
+            m_grid[r].baseline = baseline;
+        }
+
+        m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r]);
+    }
+
+    if (pushedLayoutState)
+        view()->popLayoutState();
+
+    return m_rowPos[m_gridRows];
+}
+
+int RenderTableSection::layoutRows(int toAdd)
+{
+#ifdef ANDROID_LAYOUT
+    if (table()->isSingleColumn()) {
+        int totalRows = m_gridRows;
+        int hspacing = table()->hBorderSpacing();
+        int vspacing = table()->vBorderSpacing();
+        int rHeight = vspacing;
+    
+        int leftOffset = hspacing;
+    
+        int nEffCols = table()->numEffCols();
+        for (int r = 0; r < totalRows; r++) {
+            for (int c = 0; c < nEffCols; c++) {
+                CellStruct current = cellAt(r, c);
+                RenderTableCell* cell = current.cell;
+                
+                if (!cell || current.inColSpan)
+                    continue;
+                if (r > 0 && (cellAt(r-1, c).cell == cell))
+                    continue;
+                   
+                cell->setCellTopExtra(0);
+                cell->setCellBottomExtra(0);
+                
+                int oldCellX = cell->xPos();
+                int oldCellY = cell->yPos();
+            
+                if (style()->direction() == RTL)
+                    cell->setPos(table()->width(), rHeight);
+                else
+                    cell->setPos(leftOffset, rHeight);
+    
+                // If the cell moved, we have to repaint it as well as any floating/positioned
+                // descendants.  An exception is if we need a layout.  In this case, we know we're going to
+                // repaint ourselves (and the cell) anyway.
+                if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout()) {
+                    IntRect cellRect(oldCellX, oldCellY - cell->borderTopExtra() , cell->width(), cell->height());
+                    cell->repaintDuringLayoutIfMoved(cellRect);
+                }
+                rHeight += cell->height() + vspacing;
+            }
+        }
+    
+        m_height = rHeight;
+        return m_height;
+    }
+#endif
+    int rHeight;
+    int rindx;
+    int totalRows = m_gridRows;
+    
+    // Set the width of our section now.  The rows will also be this width.
+    m_width = table()->contentWidth();
+    m_overflowLeft = 0;
+    m_overflowWidth = m_width;
+    m_overflowTop = 0;
+    m_overflowHeight = 0;
+    m_hasOverflowingCell = false;
+
+    if (toAdd && totalRows && (m_rowPos[totalRows] || !nextSibling())) {
+        int totalHeight = m_rowPos[totalRows] + toAdd;
+
+        int dh = toAdd;
+        int totalPercent = 0;
+        int numAuto = 0;
+        for (int r = 0; r < totalRows; r++) {
+            if (m_grid[r].height.isAuto())
+                numAuto++;
+            else if (m_grid[r].height.isPercent())
+                totalPercent += m_grid[r].height.rawValue();
+        }
+        if (totalPercent) {
+            // try to satisfy percent
+            int add = 0;
+            totalPercent = min(totalPercent, 100 * percentScaleFactor);
+            int rh = m_rowPos[1] - m_rowPos[0];
+            for (int r = 0; r < totalRows; r++) {
+                if (totalPercent > 0 && m_grid[r].height.isPercent()) {
+                    int toAdd = min(dh, (totalHeight * m_grid[r].height.rawValue() / (100 * percentScaleFactor)) - rh);
+                    // If toAdd is negative, then we don't want to shrink the row (this bug
+                    // affected Outlook Web Access).
+                    toAdd = max(0, toAdd);
+                    add += toAdd;
+                    dh -= toAdd;
+                    totalPercent -= m_grid[r].height.rawValue();
+                }
+                if (r < totalRows - 1)
+                    rh = m_rowPos[r + 2] - m_rowPos[r + 1];
+                m_rowPos[r + 1] += add;
+            }
+        }
+        if (numAuto) {
+            // distribute over variable cols
+            int add = 0;
+            for (int r = 0; r < totalRows; r++) {
+                if (numAuto > 0 && m_grid[r].height.isAuto()) {
+                    int toAdd = dh / numAuto;
+                    add += toAdd;
+                    dh -= toAdd;
+                    numAuto--;
+                }
+                m_rowPos[r + 1] += add;
+            }
+        }
+        if (dh > 0 && m_rowPos[totalRows]) {
+            // if some left overs, distribute equally.
+            int tot = m_rowPos[totalRows];
+            int add = 0;
+            int prev = m_rowPos[0];
+            for (int r = 0; r < totalRows; r++) {
+                //weight with the original height
+                add += dh * (m_rowPos[r + 1] - prev) / tot;
+                prev = m_rowPos[r + 1];
+                m_rowPos[r + 1] += add;
+            }
+        }
+    }
+
+    int hspacing = table()->hBorderSpacing();
+    int vspacing = table()->vBorderSpacing();
+    int nEffCols = table()->numEffCols();
+
+    view()->pushLayoutState(this, IntSize(m_x, m_y));
+
+    for (int r = 0; r < totalRows; r++) {
+        // Set the row's x/y position and width/height.
+        if (RenderObject* rowRenderer = m_grid[r].rowRenderer) {
+            rowRenderer->setPos(0, m_rowPos[r]);
+            rowRenderer->setWidth(m_width);
+            rowRenderer->setHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
+        }
+
+        for (int c = 0; c < nEffCols; c++) {
+            RenderTableCell* cell = cellAt(r, c).cell;
+            
+            if (!cell)
+                continue;
+            if (r < totalRows - 1 && cell == cellAt(r + 1, c).cell)
+                continue;
+
+            rindx = max(0, r - cell->rowSpan() + 1);
+
+            rHeight = m_rowPos[r + 1] - m_rowPos[rindx] - vspacing;
+            
+            // Force percent height children to lay themselves out again.
+            // This will cause these children to grow to fill the cell.
+            // FIXME: There is still more work to do here to fully match WinIE (should
+            // it become necessary to do so).  In quirks mode, WinIE behaves like we
+            // do, but it will clip the cells that spill out of the table section.  In
+            // strict mode, Mozilla and WinIE both regrow the table to accommodate the
+            // new height of the cell (thus letting the percentages cause growth one
+            // time only).  We may also not be handling row-spanning cells correctly.
+            //
+            // Note also the oddity where replaced elements always flex, and yet blocks/tables do
+            // not necessarily flex.  WinIE is crazy and inconsistent, and we can't hope to
+            // match the behavior perfectly, but we'll continue to refine it as we discover new
+            // bugs. :)
+            bool cellChildrenFlex = false;
+            bool flexAllChildren = cell->style()->height().isFixed() || 
+                (!table()->style()->height().isAuto() && rHeight != cell->height());
+
+            for (RenderObject* o = cell->firstChild(); o; o = o->nextSibling()) {
+                if (!o->isText() && o->style()->height().isPercent() && (o->isReplaced() || o->scrollsOverflow() || flexAllChildren)) {
+                    // Tables with no sections do not flex.
+                    if (!o->isTable() || static_cast<RenderTable*>(o)->hasSections()) {
+                        o->setNeedsLayout(true, false);
+                        cell->setChildNeedsLayout(true, false);
+                        cellChildrenFlex = true;
+                    }
+                }
+            }
+            if (cellChildrenFlex) {
+                // Alignment within a cell is based off the calculated
+                // height, which becomes irrelevant once the cell has
+                // been resized based off its percentage. -dwh
+                cell->setOverrideSize(max(0, 
+                                           rHeight - cell->borderTop() - cell->paddingTop() - 
+                                                     cell->borderBottom() - cell->paddingBottom()));
+                cell->layoutIfNeeded();
+                
+                // If the baseline moved, we may have to update the data for our row. Find out the new baseline.
+                EVerticalAlign va = cell->style()->verticalAlign();
+                if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
+                    int b = cell->baselinePosition();
+                    if (b > cell->borderTop() + cell->paddingTop())
+                        m_grid[r].baseline = max(m_grid[r].baseline, b);
+                }
+            }
+            
+            int te = 0;
+            switch (cell->style()->verticalAlign()) {
+                case SUB:
+                case SUPER:
+                case TEXT_TOP:
+                case TEXT_BOTTOM:
+                case BASELINE:
+                    te = getBaseline(r) - cell->baselinePosition();
+                    break;
+                case TOP:
+                    te = 0;
+                    break;
+                case MIDDLE:
+                    te = (rHeight - cell->height()) / 2;
+                    break;
+                case BOTTOM:
+                    te = rHeight - cell->height();
+                    break;
+                default:
+                    break;
+            }
+                
+            int oldTe = cell->borderTopExtra();
+            int oldBe = cell->borderBottomExtra();
+                
+            int be = rHeight - cell->height() - te;
+            cell->setCellTopExtra(te);
+            cell->setCellBottomExtra(be);
+            if ((te != oldTe || be > oldBe) && !table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
+                cell->repaint();
+            
+            IntRect oldCellRect(cell->xPos(), cell->yPos() - cell->borderTopExtra() , cell->width(), cell->height());
+        
+            if (style()->direction() == RTL) {
+                cell->setPos(table()->columnPositions()[nEffCols] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + hspacing, m_rowPos[rindx]);
+            } else
+                cell->setPos(table()->columnPositions()[c] + hspacing, m_rowPos[rindx]);
+
+            m_overflowLeft = min(m_overflowLeft, cell->xPos() + cell->overflowLeft(false));
+            m_overflowWidth = max(m_overflowWidth, cell->xPos() + cell->overflowWidth(false));
+            m_overflowTop = min(m_overflowTop, cell->yPos() + cell->overflowTop(false));
+            m_overflowHeight = max(m_overflowHeight, cell->yPos() + cell->overflowHeight(false));
+            m_hasOverflowingCell |= cell->overflowLeft(false) || cell->overflowWidth(false) > cell->width() || cell->overflowTop(false) || cell->overflowHeight(false) > cell->height();
+
+            // If the cell moved, we have to repaint it as well as any floating/positioned
+            // descendants.  An exception is if we need a layout.  In this case, we know we're going to
+            // repaint ourselves (and the cell) anyway.
+            if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
+                cell->repaintDuringLayoutIfMoved(oldCellRect);
+        }
+    }
+
+    view()->popLayoutState();
+
+    m_height = m_rowPos[totalRows];
+    m_overflowHeight = max(m_overflowHeight, m_height);
+    return m_height;
+}
+
+int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    int bottom = RenderContainer::lowestPosition(includeOverflowInterior, includeSelf);
+    if (!includeOverflowInterior && hasOverflowClip())
+        return bottom;
+
+    for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
+        for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
+            if (cell->isTableCell())
+                bottom = max(bottom, cell->yPos() + cell->lowestPosition(false));
+        }
+    }
+    
+    return bottom;
+}
+
+int RenderTableSection::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    int right = RenderContainer::rightmostPosition(includeOverflowInterior, includeSelf);
+    if (!includeOverflowInterior && hasOverflowClip())
+        return right;
+
+    for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
+        for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
+            if (cell->isTableCell())
+                right = max(right, cell->xPos() + cell->rightmostPosition(false));
+        }
+    }
+    
+    return right;
+}
+
+int RenderTableSection::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+    int left = RenderContainer::leftmostPosition(includeOverflowInterior, includeSelf);
+    if (!includeOverflowInterior && hasOverflowClip())
+        return left;
+    
+    for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
+        for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
+            if (cell->isTableCell())
+                left = min(left, cell->xPos() + cell->leftmostPosition(false));
+        }
+    }
+    
+    return left;
+}
+
+int RenderTableSection::calcOuterBorderTop() const
+{
+    int totalCols = table()->numEffCols();
+    if (!m_gridRows || !totalCols)
+        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 (!m_gridRows || !totalCols)
+        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(m_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 (!m_gridRows || !totalCols)
+        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 < m_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 (!m_gridRows || !totalCols)
+        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 < m_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);
+}
+
+int RenderTableSection::getBaselineOfFirstLineBox() const
+{
+    if (!m_gridRows)
+        return -1;
+
+    int firstLineBaseline = m_grid[0].baseline;
+    if (firstLineBaseline)
+        return firstLineBaseline + m_rowPos[0];
+
+    firstLineBaseline = -1;
+    Row* firstRow = m_grid[0].row;
+    for (size_t i = 0; i < firstRow->size(); ++i) {
+        RenderTableCell* cell = firstRow->at(i).cell;
+        if (cell)
+            firstLineBaseline = max(firstLineBaseline, cell->yPos() + cell->paddingTop() + cell->borderTop() + cell->contentHeight());
+    }
+
+    return firstLineBaseline;
+}
+
+void RenderTableSection::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    // put this back in when all layout tests can handle it
+    // ASSERT(!needsLayout());
+    // avoid crashing on bugs that cause us to paint with dirty layout
+    if (needsLayout())
+        return;
+    
+    unsigned totalRows = m_gridRows;
+    unsigned totalCols = table()->columns().size();
+
+    if (!totalRows || !totalCols)
+        return;
+
+    tx += m_x;
+    ty += m_y;
+
+    // Check which rows and cols are visible and only paint these.
+    // FIXME: Could use a binary search here.
+    PaintPhase paintPhase = paintInfo.phase;
+    int x = paintInfo.rect.x();
+    int y = paintInfo.rect.y();
+    int w = paintInfo.rect.width();
+    int h = paintInfo.rect.height();
+
+#ifdef ANDROID_LAYOUT
+    unsigned int startrow = 0;
+    unsigned int endrow = totalRows;
+    unsigned int startcol = 0;
+    unsigned int endcol = totalCols;
+    if (table()->isSingleColumn()) {
+        // FIXME: should we be smarter too?        
+    } else {
+    // FIXME: possible to rollback to the common tree.
+    // rowPos size is set in calcRowHeight(), which is called from table layout().
+    // BUT RenderTableSection is init through parsing. On a slow device, paint() as
+    // the result of layout() can come after the next parse() as everything is triggered
+    // by timer. So we have to check rowPos before using it.
+    if (m_rowPos.size() != (totalRows + 1))
+        return;
+#endif
+
+    int os = 2 * maximalOutlineSize(paintPhase);
+    unsigned startrow = 0;
+    unsigned endrow = totalRows;
+    
+    // If some cell overflows, just paint all of them.
+    if (!m_hasOverflowingCell) {
+        for (; startrow < totalRows; startrow++) {
+            if (ty + m_rowPos[startrow + 1] >= y - os)
+                break;
+        }
+        if (startrow == totalRows && ty + m_rowPos[totalRows] + table()->outerBorderBottom() >= y - os)
+            startrow--;
+
+        for (; endrow > 0; endrow--) {
+            if (ty + m_rowPos[endrow - 1] <= y + h + os)
+                break;
+        }
+        if (!endrow && ty + m_rowPos[0] - table()->outerBorderTop() <= y + h + os)
+            endrow++;
+    }
+
+    unsigned startcol = 0;
+    unsigned endcol = totalCols;
+    // FIXME: Implement RTL.
+    if (!m_hasOverflowingCell && style()->direction() == LTR) {
+        for (; startcol < totalCols; startcol++) {
+            if (tx + table()->columnPositions()[startcol + 1] >= x - os)
+                break;
+        }
+        if (startcol == totalCols && tx + table()->columnPositions()[totalCols] + table()->outerBorderRight() >= x - os)
+            startcol--;
+
+        for (; endcol > 0; endcol--) {
+            if (tx + table()->columnPositions()[endcol - 1] <= x + w + os)
+                break;
+        }
+        if (!endcol && tx + table()->columnPositions()[0] - table()->outerBorderLeft() <= y + w + os)
+            endcol++;
+    }
+#ifdef ANDROID_LAYOUT
+    }
+#endif
+
+    if (startcol < endcol) {
+        // draw the cells
+        for (unsigned r = startrow; r < endrow; r++) {
+            unsigned c = startcol;
+            // since a cell can be -1 (indicating a colspan) we might have to search backwards to include it
+            while (c && cellAt(r, c).inColSpan)
+                c--;
+            for (; c < endcol; c++) {
+                CellStruct current = cellAt(r, c);
+                RenderTableCell* cell = current.cell;
+                    
+                // Cells must always paint in the order in which they appear taking into account
+                // their upper left originating row/column.  For cells with rowspans, avoid repainting
+                // if we've already seen the cell.
+                if (!cell || (r > startrow && (cellAt(r - 1, c).cell == cell)))
+                    continue;
+
+                RenderTableRow* row = static_cast<RenderTableRow*>(cell->parent());
+
+                if (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) {
+                    // We need to handle painting a stack of backgrounds.  This stack (from bottom to top) consists of
+                    // the column group, column, row group, row, and then the cell.
+                    RenderObject* col = table()->colElement(c);
+                    RenderObject* colGroup = 0;
+                    if (col && col->parent()->style()->display() == TABLE_COLUMN_GROUP)
+                        colGroup = col->parent();
+
+                    // Column groups and columns first.
+                    // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
+                    // the stack, since we have already opened a transparency layer (potentially) for the table row group.
+                    // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
+                    // cell.
+                    cell->paintBackgroundsBehindCell(paintInfo, tx, ty, colGroup);
+                    cell->paintBackgroundsBehindCell(paintInfo, tx, ty, col);
+
+                    // Paint the row group next.
+                    cell->paintBackgroundsBehindCell(paintInfo, tx, ty, this);
+
+                    // Paint the row next, but only if it doesn't have a layer.  If a row has a layer, it will be responsible for
+                    // painting the row background for the cell.
+                    if (!row->hasLayer())
+                        cell->paintBackgroundsBehindCell(paintInfo, tx, ty, row);
+                }
+                if ((!cell->hasLayer() && !row->hasLayer()) || paintInfo.phase == PaintPhaseCollapsedTableBorders)
+                    cell->paint(paintInfo, tx, ty);
+            }
+        }
+    }
+}
+
+void RenderTableSection::imageChanged(WrappedImagePtr image)
+{
+    // FIXME: Examine cells and repaint only the rect the image paints in.
+    repaint();
+}
+
+void RenderTableSection::recalcCells()
+{
+    m_cCol = 0;
+    m_cRow = -1;
+    clearGrid();
+    m_gridRows = 0;
+
+    for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
+        if (row->isTableRow()) {
+            m_cRow++;
+            m_cCol = 0;
+            if (!ensureRows(m_cRow + 1))
+                break;
+            m_grid[m_cRow].rowRenderer = row;
+
+            for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
+                if (cell->isTableCell())
+                    addCell(static_cast<RenderTableCell*>(cell), row);
+            }
+        }
+    }
+    m_needsCellRecalc = false;
+    setNeedsLayout(true);
+}
+
+void RenderTableSection::clearGrid()
+{
+    int rows = m_gridRows;
+    while (rows--)
+        delete m_grid[rows].row;
+}
+
+int RenderTableSection::numColumns() const
+{
+    int result = 0;
+    
+    for (int r = 0; r < m_gridRows; ++r) {
+        for (int c = result; c < table()->numEffCols(); ++c) {
+            const CellStruct& cell = cellAt(r, c);
+            if (cell.cell || cell.inColSpan)
+                result = c;
+        }
+    }
+    
+    return result + 1;
+}
+
+void RenderTableSection::appendColumn(int pos)
+{
+    for (int row = 0; row < m_gridRows; ++row) {
+        m_grid[row].row->resize(pos + 1);
+        CellStruct& c = cellAt(row, pos);
+        c.cell = 0;
+        c.inColSpan = false;
+    }
+}
+
+void RenderTableSection::splitColumn(int pos, int newSize)
+{
+    if (m_cCol > pos)
+        m_cCol++;
+    for (int row = 0; row < m_gridRows; ++row) {
+        m_grid[row].row->resize(newSize);
+        Row& r = *m_grid[row].row;
+        memmove(r.data() + pos + 1, r.data() + pos, (newSize - 1 - pos) * sizeof(CellStruct));
+        r[pos + 1].cell = 0;
+        r[pos + 1].inColSpan = r[pos].inColSpan || r[pos].cell;
+    }
+}
+
+RenderObject* RenderTableSection::removeChildNode(RenderObject* child, bool fullRemove)
+{
+    setNeedsCellRecalc();
+    return RenderContainer::removeChildNode(child, fullRemove);
+}
+
+// Hit Testing
+bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction action)
+{
+    // Table sections cannot ever be hit tested.  Effectively they do not exist.
+    // Just forward to our children always.
+    tx += m_x;
+    ty += m_y;
+
+    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+        // FIXME: We have to skip over inline flows, since they can show up inside table rows
+        // at the moment (a demoted inline <form> for example). If we ever implement a
+        // table-specific hit-test method (which we should do for performance reasons anyway),
+        // then we can remove this check.
+        if (!child->hasLayer() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
+            updateHitTestResult(result, IntPoint(x - tx, y - ty));
+            return true;
+        }
+    }
+    
+    return false;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderTableSection.h b/WebCore/rendering/RenderTableSection.h
new file mode 100644
index 0000000..1866fd5
--- /dev/null
+++ b/WebCore/rendering/RenderTableSection.h
@@ -0,0 +1,154 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1997 Martin Jones ([email protected])
+ *           (C) 1997 Torben Weis ([email protected])
+ *           (C) 1998 Waldo Bastian ([email protected])
+ *           (C) 1999 Lars Knoll ([email protected])
+ *           (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RenderTableSection_h
+#define RenderTableSection_h
+
+#include "RenderTable.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderTableCell;
+
+class RenderTableSection : public RenderContainer {
+public:
+    RenderTableSection(Node*);
+    ~RenderTableSection();
+
+    virtual const char* renderName() const { return isAnonymous() ? "RenderTableSection (anonymous)" : "RenderTableSection"; }
+
+    virtual bool isTableSection() const { return true; }
+
+    virtual void destroy();
+
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+
+    virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const { return 0; }
+    virtual void position(InlineBox*) { }
+
+    virtual int getBaselineOfFirstLineBox() const;
+
+    void addCell(RenderTableCell*, RenderObject* row);
+
+    void setCellWidths();
+    int calcRowHeight();
+    int layoutRows(int height);
+
+    RenderTable* table() const { return static_cast<RenderTable*>(parent()); }
+
+    struct CellStruct {
+        RenderTableCell* cell;
+        bool inColSpan; // true for columns after the first in a colspan
+    };
+
+    typedef Vector<CellStruct> Row;
+
+    struct RowStruct {
+        Row* row;
+        RenderObject* rowRenderer;
+        int baseline;
+        Length height;
+    };
+
+    CellStruct& cellAt(int row,  int col) { return (*m_grid[row].row)[col]; }
+    const CellStruct& cellAt(int row, int col) const { return (*m_grid[row].row)[col]; }
+
+    void appendColumn(int pos);
+    void splitColumn(int pos, int newSize);
+
+    virtual int overflowWidth(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? m_width : m_overflowWidth; }
+    virtual int overflowLeft(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? 0 : m_overflowLeft; }
+    virtual int overflowHeight(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? m_height : m_overflowHeight; }
+    virtual int overflowTop(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? 0 : m_overflowTop; }
+
+    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&, int tx, int ty);
+    virtual void imageChanged(WrappedImagePtr);
+
+    int numRows() const { return m_gridRows; }
+    int numColumns() const;
+    void recalcCells();
+    void recalcCellsIfNeeded()
+    {
+        if (m_needsCellRecalc)
+            recalcCells();
+    }
+
+    bool needsCellRecalc() const { return m_needsCellRecalc; }
+    void setNeedsCellRecalc()
+    {
+        m_needsCellRecalc = true;
+        table()->setNeedsSectionRecalc();
+    }
+
+    int getBaseline(int row) { return m_grid[row].baseline; }
+
+    virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+private:
+    bool ensureRows(int);
+    void clearGrid();
+
+    Vector<RowStruct> m_grid;
+    int m_gridRows;
+    Vector<int> m_rowPos;
+
+    // the current insertion position
+    int m_cCol;
+    int m_cRow;
+    bool m_needsCellRecalc;
+
+    int m_outerBorderLeft;
+    int m_outerBorderRight;
+    int m_outerBorderTop;
+    int m_outerBorderBottom;
+    int m_overflowLeft;
+    int m_overflowWidth;
+    int m_overflowTop;
+    int m_overflowHeight;
+    bool m_hasOverflowingCell;
+};
+
+} // namespace WebCore
+
+#endif // RenderTableSection_h
diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp
new file mode 100644
index 0000000..be8e337
--- /dev/null
+++ b/WebCore/rendering/RenderText.cpp
@@ -0,0 +1,1172 @@
+/**
+ * (C) 1999 Lars Knoll ([email protected])
+ * (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Andrew Wellington ([email protected])
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderText.h"
+
+#include "CharacterNames.h"
+#include "InlineTextBox.h"
+#include "Range.h"
+#include "RenderArena.h"
+#include "RenderBlock.h"
+#include "RenderLayer.h"
+#include "Text.h"
+#include "TextBreakIterator.h"
+#include "break_lines.h"
+#include <wtf/AlwaysInline.h>
+
+using namespace std;
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+// FIXME: Move to StringImpl.h eventually.
+static inline bool charactersAreAllASCII(StringImpl* text)
+{
+    return charactersAreAllASCII(text->characters(), text->length());
+}
+
+RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str)
+     : RenderObject(node)
+     , m_text(str)
+     , m_firstTextBox(0)
+     , m_lastTextBox(0)
+     , m_minWidth(-1)
+     , m_maxWidth(-1)
+     , m_selectionState(SelectionNone)
+     , m_hasTab(false)
+     , m_linesDirty(false)
+     , m_containsReversedText(false)
+     , m_isAllASCII(charactersAreAllASCII(m_text.get()))
+{
+    ASSERT(m_text);
+    setRenderText();
+    m_text = m_text->replace('\\', backslashAsCurrencySymbol());
+}
+
+#ifndef NDEBUG
+
+RenderText::~RenderText()
+{
+    ASSERT(!m_firstTextBox);
+    ASSERT(!m_lastTextBox);
+}
+
+#endif
+
+const char* RenderText::renderName() const
+{
+    return "RenderText";
+}
+
+bool RenderText::isTextFragment() const
+{
+    return false;
+}
+
+bool RenderText::isWordBreak() const
+{
+    return false;
+}
+
+void RenderText::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderObject::styleDidChange(diff, oldStyle);
+
+    ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE;
+    ETextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TSNONE;
+
+    if (oldTransform != style()->textTransform() || oldSecurity != style()->textSecurity()
+#if ENABLE(SVG)
+        || isSVGText() /* All SVG text has to be transformed */
+#endif
+       ) {
+        if (RefPtr<StringImpl> textToTransform = originalText())
+            setText(textToTransform.release(), true);
+    }
+}
+
+void RenderText::destroy()
+{
+    if (!documentBeingDestroyed()) {
+        if (firstTextBox()) {
+            if (isBR()) {
+                RootInlineBox* next = firstTextBox()->root()->nextRootBox();
+                if (next)
+                    next->markDirty();
+            }
+            for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+                box->remove();
+        } else if (parent())
+            parent()->dirtyLinesFromChangedChild(this);
+    }
+    deleteTextBoxes();
+    RenderObject::destroy();
+}
+
+void RenderText::extractTextBox(InlineTextBox* box)
+{
+    checkConsistency();
+
+    m_lastTextBox = box->prevTextBox();
+    if (box == m_firstTextBox)
+        m_firstTextBox = 0;
+    if (box->prevTextBox())
+        box->prevTextBox()->setNextLineBox(0);
+    box->setPreviousLineBox(0);
+    for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox())
+        curr->setExtracted();
+
+    checkConsistency();
+}
+
+void RenderText::attachTextBox(InlineTextBox* box)
+{
+    checkConsistency();
+
+    if (m_lastTextBox) {
+        m_lastTextBox->setNextLineBox(box);
+        box->setPreviousLineBox(m_lastTextBox);
+    } else
+        m_firstTextBox = box;
+    InlineTextBox* last = box;
+    for (InlineTextBox* curr = box; curr; curr = curr->nextTextBox()) {
+        curr->setExtracted(false);
+        last = curr;
+    }
+    m_lastTextBox = last;
+
+    checkConsistency();
+}
+
+void RenderText::removeTextBox(InlineTextBox* box)
+{
+    checkConsistency();
+
+    if (box == m_firstTextBox)
+        m_firstTextBox = box->nextTextBox();
+    if (box == m_lastTextBox)
+        m_lastTextBox = box->prevTextBox();
+    if (box->nextTextBox())
+        box->nextTextBox()->setPreviousLineBox(box->prevTextBox());
+    if (box->prevTextBox())
+        box->prevTextBox()->setNextLineBox(box->nextTextBox());
+
+    checkConsistency();
+}
+
+void RenderText::deleteTextBoxes()
+{
+    if (firstTextBox()) {
+        RenderArena* arena = renderArena();
+        InlineTextBox* next;
+        for (InlineTextBox* curr = firstTextBox(); curr; curr = next) {
+            next = curr->nextTextBox();
+            curr->destroy(arena);
+        }
+        m_firstTextBox = m_lastTextBox = 0;
+    }
+}
+
+PassRefPtr<StringImpl> RenderText::originalText() const
+{
+    Node* e = element();
+    return e ? static_cast<Text*>(e)->string() : 0;
+}
+
+void RenderText::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool)
+{
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+        rects.append(IntRect(tx + box->xPos(), ty + box->yPos(), box->width(), box->height()));
+}
+
+void RenderText::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end, bool useSelectionHeight)
+{
+    // Work around signed/unsigned issues. This function takes unsigneds, and is often passed UINT_MAX
+    // to mean "all the way to the end". InlineTextBox coordinates are unsigneds, so changing this 
+    // function to take ints causes various internal mismatches. But selectionRect takes ints, and 
+    // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take unsigneds, but 
+    // that would cause many ripple effects, so for now we'll just clamp our unsigned parameters to INT_MAX.
+    ASSERT(end == UINT_MAX || end <= INT_MAX);
+    ASSERT(start <= INT_MAX);
+    start = min(start, static_cast<unsigned>(INT_MAX));
+    end = min(end, static_cast<unsigned>(INT_MAX));
+    
+    int x, y;
+    absolutePositionForContent(x, y);
+
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+        // Note: box->end() returns the index of the last character, not the index past it
+        if (start <= box->start() && box->end() < end) {
+            IntRect r = IntRect(x + box->xPos(), y + box->yPos(), box->width(), box->height());
+            if (useSelectionHeight) {
+                IntRect selectionRect = box->selectionRect(x, y, start, end);
+                r.setHeight(selectionRect.height());
+                r.setY(selectionRect.y());
+            }
+            rects.append(r);
+        } else {
+            unsigned realEnd = min(box->end() + 1, end);
+            IntRect r = box->selectionRect(x, y, start, realEnd);
+            if (!r.isEmpty()) {
+                if (!useSelectionHeight) {
+                    // change the height and y position because selectionRect uses selection-specific values
+                    r.setHeight(box->height());
+                    r.setY(y + box->yPos());
+                }
+                rects.append(r);
+            }
+        }
+    }
+}
+
+InlineTextBox* RenderText::findNextInlineTextBox(int offset, int& pos) const
+{
+    // The text runs point to parts of the RenderText's m_text
+    // (they don't include '\n')
+    // Find the text run that includes the character at offset
+    // and return pos, which is the position of the char in the run.
+
+    if (!m_firstTextBox)
+        return 0;
+
+    InlineTextBox* s = m_firstTextBox;
+    int off = s->m_len;
+    while (offset > off && s->nextTextBox()) {
+        s = s->nextTextBox();
+        off = s->m_start + s->m_len;
+    }
+    // we are now in the correct text run
+    pos = (offset > off ? s->m_len : s->m_len - (off - offset) );
+    return s;
+}
+
+VisiblePosition RenderText::positionForCoordinates(int x, int y)
+{
+    if (!firstTextBox() || textLength() == 0)
+        return VisiblePosition(element(), 0, DOWNSTREAM);
+
+    // Get the offset for the position, since this will take rtl text into account.
+    int offset;
+
+    // FIXME: We should be able to roll these special cases into the general cases in the loop below.
+    if (firstTextBox() && y <  firstTextBox()->root()->bottomOverflow() && x < firstTextBox()->m_x) {
+        // at the y coordinate of the first line or above
+        // and the x coordinate is to the left of the first text box left edge
+        offset = firstTextBox()->offsetForPosition(x);
+        return VisiblePosition(element(), offset + firstTextBox()->m_start, DOWNSTREAM);
+    }
+    if (lastTextBox() && y >= lastTextBox()->root()->topOverflow() && x >= lastTextBox()->m_x + lastTextBox()->m_width) {
+        // at the y coordinate of the last line or below
+        // and the x coordinate is to the right of the last text box right edge
+        offset = lastTextBox()->offsetForPosition(x);
+        return VisiblePosition(element(), offset + lastTextBox()->m_start, DOWNSTREAM);
+    }
+
+    InlineTextBox* lastBoxAbove = 0;
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+        if (y >= box->root()->topOverflow()) {
+            int bottom = box->root()->nextRootBox() ? box->root()->nextRootBox()->topOverflow() : box->root()->bottomOverflow();
+            if (y < bottom) {
+                offset = box->offsetForPosition(x);
+
+                if (x == box->m_x)
+                    // the x coordinate is equal to the left edge of this box
+                    // the affinity must be downstream so the position doesn't jump back to the previous line
+                    return VisiblePosition(element(), offset + box->m_start, DOWNSTREAM);
+
+                if (x < box->m_x + box->m_width)
+                    // and the x coordinate is to the left of the right edge of this box
+                    // check to see if position goes in this box
+                    return VisiblePosition(element(), offset + box->m_start, offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
+
+                if (!box->prevOnLine() && x < box->m_x)
+                    // box is first on line
+                    // and the x coordinate is to the left of the first text box left edge
+                    return VisiblePosition(element(), offset + box->m_start, DOWNSTREAM);
+
+                if (!box->nextOnLine())
+                    // box is last on line
+                    // and the x coordinate is to the right of the last text box right edge
+                    // generate VisiblePosition, use UPSTREAM affinity if possible
+                    return VisiblePosition(element(), offset + box->m_start, offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
+            }
+            lastBoxAbove = box;
+        }
+    }
+
+    return VisiblePosition(element(), lastBoxAbove ? lastBoxAbove->m_start + lastBoxAbove->m_len : 0, DOWNSTREAM);
+}
+
+IntRect RenderText::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
+{
+    if (!inlineBox)
+        return IntRect();
+
+    ASSERT(inlineBox->isInlineTextBox());
+    if (!inlineBox->isInlineTextBox())
+        return IntRect();
+
+    InlineTextBox* box = static_cast<InlineTextBox*>(inlineBox);
+
+    int height = box->root()->bottomOverflow() - box->root()->topOverflow();
+    int top = box->root()->topOverflow();
+
+    int left = box->positionForOffset(caretOffset);
+
+    int rootLeft = box->root()->xPos();
+    // FIXME: should we use the width of the root inline box or the
+    // width of the containing block for this?
+    if (extraWidthToEndOfLine)
+        *extraWidthToEndOfLine = (box->root()->width() + rootLeft) - (left + 1);
+
+    int absx, absy;
+    absolutePositionForContent(absx, absy);
+    left += absx;
+    top += absy;
+
+    RenderBlock* cb = containingBlock();
+    if (style()->autoWrap()) {
+        int availableWidth = cb->lineWidth(top);
+        if (box->direction() == LTR)
+            left = min(left, absx + rootLeft + availableWidth - 1);
+        else
+            left = max(left, absx + rootLeft);
+    }
+
+    return IntRect(left, top, 1, height);
+}
+
+ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len, int xPos) const
+{
+    if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII) {
+        int monospaceCharacterWidth = f.spaceWidth();
+        int tabWidth = allowTabs() ? monospaceCharacterWidth * 8 : 0;
+        int w = 0;
+        bool isSpace;
+        bool previousCharWasSpace = true; // FIXME: Preserves historical behavior, but seems wrong for start > 0.
+        for (int i = start; i < start + len; i++) {
+            char c = (*m_text)[i];
+            if (c <= ' ') {
+                if (c == ' ' || c == '\n') {
+                    w += monospaceCharacterWidth;
+                    isSpace = true;
+                } else if (c == '\t') {
+                    w += tabWidth ? tabWidth - ((xPos + w) % tabWidth) : monospaceCharacterWidth;
+                    isSpace = true;
+                } else
+                    isSpace = false;
+            } else {
+                w += monospaceCharacterWidth;
+                isSpace = false;
+            }
+            if (isSpace && !previousCharWasSpace)
+                w += f.wordSpacing();
+            previousCharWasSpace = isSpace;
+        }
+        return w;
+    }
+
+    return f.width(TextRun(text()->characters() + start, len, allowTabs(), xPos));
+}
+
+void RenderText::trimmedPrefWidths(int leadWidth,
+                                   int& beginMinW, bool& beginWS,
+                                   int& endMinW, bool& endWS,
+                                   bool& hasBreakableChar, bool& hasBreak,
+                                   int& beginMaxW, int& endMaxW,
+                                   int& minW, int& maxW, bool& stripFrontSpaces)
+{
+    bool collapseWhiteSpace = style()->collapseWhiteSpace();
+    if (!collapseWhiteSpace)
+        stripFrontSpaces = false;
+
+    if (m_hasTab || prefWidthsDirty())
+        calcPrefWidths(leadWidth);
+
+    beginWS = !stripFrontSpaces && m_hasBeginWS;
+    endWS = m_hasEndWS;
+
+    int len = textLength();
+
+    if (!len || (stripFrontSpaces && m_text->containsOnlyWhitespace())) {
+        beginMinW = 0;
+        endMinW = 0;
+        beginMaxW = 0;
+        endMaxW = 0;
+        minW = 0;
+        maxW = 0;
+        hasBreak = false;
+        return;
+    }
+
+    minW = m_minWidth;
+    maxW = m_maxWidth;
+
+    beginMinW = m_beginMinWidth;
+    endMinW = m_endMinWidth;
+
+    hasBreakableChar = m_hasBreakableChar;
+    hasBreak = m_hasBreak;
+
+    if ((*m_text)[0] == ' ' || ((*m_text)[0] == '\n' && !style()->preserveNewline()) || (*m_text)[0] == '\t') {
+        const Font& f = style()->font(); // FIXME: This ignores first-line.
+        if (stripFrontSpaces) {
+            const UChar space = ' ';
+            int spaceWidth = f.width(TextRun(&space, 1));
+            maxW -= spaceWidth;
+        } else
+            maxW += f.wordSpacing();
+    }
+
+    stripFrontSpaces = collapseWhiteSpace && m_hasEndWS;
+
+    if (!style()->autoWrap() || minW > maxW)
+        minW = maxW;
+
+    // Compute our max widths by scanning the string for newlines.
+    if (hasBreak) {
+        const Font& f = style()->font(); // FIXME: This ignores first-line.
+        bool firstLine = true;
+        beginMaxW = maxW;
+        endMaxW = maxW;
+        for (int i = 0; i < len; i++) {
+            int linelen = 0;
+            while (i + linelen < len && (*m_text)[i + linelen] != '\n')
+                linelen++;
+
+            if (linelen) {
+                endMaxW = widthFromCache(f, i, linelen, leadWidth + endMaxW);
+                if (firstLine) {
+                    firstLine = false;
+                    leadWidth = 0;
+                    beginMaxW = endMaxW;
+                }
+                i += linelen;
+            } else if (firstLine) {
+                beginMaxW = 0;
+                firstLine = false;
+                leadWidth = 0;
+            }
+
+            if (i == len - 1)
+                // A <pre> run that ends with a newline, as in, e.g.,
+                // <pre>Some text\n\n<span>More text</pre>
+                endMaxW = 0;
+        }
+    }
+}
+
+static inline bool isSpaceAccordingToStyle(UChar c, RenderStyle* style)
+{
+    return c == ' ' || (c == noBreakSpace && style->nbspMode() == SPACE);
+}
+
+int RenderText::minPrefWidth() const
+{
+    if (prefWidthsDirty())
+        const_cast<RenderText*>(this)->calcPrefWidths(0);
+        
+    return m_minWidth;
+}
+
+int RenderText::maxPrefWidth() const
+{
+    if (prefWidthsDirty())
+        const_cast<RenderText*>(this)->calcPrefWidths(0);
+        
+    return m_maxWidth;
+}
+
+void RenderText::calcPrefWidths(int leadWidth)
+{
+    ASSERT(m_hasTab || prefWidthsDirty());
+
+    m_minWidth = 0;
+    m_beginMinWidth = 0;
+    m_endMinWidth = 0;
+    m_maxWidth = 0;
+
+    if (isBR())
+        return;
+
+    int currMinWidth = 0;
+    int currMaxWidth = 0;
+    m_hasBreakableChar = false;
+    m_hasBreak = false;
+    m_hasTab = false;
+    m_hasBeginWS = false;
+    m_hasEndWS = false;
+
+    const Font& f = style()->font(); // FIXME: This ignores first-line.
+    int wordSpacing = style()->wordSpacing();
+    int len = textLength();
+    const UChar* txt = characters();
+    bool needsWordSpacing = false;
+    bool ignoringSpaces = false;
+    bool isSpace = false;
+    bool firstWord = true;
+    bool firstLine = true;
+    int nextBreakable = -1;
+    int lastWordBoundary = 0;
+
+    bool breakNBSP = style()->autoWrap() && style()->nbspMode() == SPACE;
+    bool breakAll = (style()->wordBreak() == BreakAllWordBreak || style()->wordBreak() == BreakWordBreak) && style()->autoWrap();
+
+    for (int i = 0; i < len; i++) {
+        UChar c = txt[i];
+
+        bool previousCharacterIsSpace = isSpace;
+
+        bool isNewline = false;
+        if (c == '\n') {
+            if (style()->preserveNewline()) {
+                m_hasBreak = true;
+                isNewline = true;
+                isSpace = false;
+            } else
+                isSpace = true;
+        } else if (c == '\t') {
+            if (!style()->collapseWhiteSpace()) {
+                m_hasTab = true;
+                isSpace = false;
+            } else
+                isSpace = true;
+        } else
+            isSpace = c == ' ';
+
+        if ((isSpace || isNewline) && !i)
+            m_hasBeginWS = true;
+        if ((isSpace || isNewline) && i == len - 1)
+            m_hasEndWS = true;
+
+        if (!ignoringSpaces && style()->collapseWhiteSpace() && previousCharacterIsSpace && isSpace)
+            ignoringSpaces = true;
+
+        if (ignoringSpaces && !isSpace)
+            ignoringSpaces = false;
+
+        // Ignore spaces and soft hyphens
+        if (ignoringSpaces) {
+            ASSERT(lastWordBoundary == i);
+            lastWordBoundary++;
+            continue;
+        } else if (c == softHyphen) {
+            currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth);
+            lastWordBoundary = i + 1;
+            continue;
+        }
+
+        bool hasBreak = breakAll || isBreakable(txt, i, len, nextBreakable, breakNBSP);
+        bool betweenWords = true;
+        int j = i;
+        while (c != '\n' && !isSpaceAccordingToStyle(c, style()) && c != '\t' && c != softHyphen) {
+            j++;
+            if (j == len)
+                break;
+            c = txt[j];
+            if (isBreakable(txt, j, len, nextBreakable, breakNBSP))
+                break;
+            if (breakAll) {
+                betweenWords = false;
+                break;
+            }
+        }
+
+        int wordLen = j - i;
+        if (wordLen) {
+            int w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth);
+            currMinWidth += w;
+            if (betweenWords) {
+                if (lastWordBoundary == i)
+                    currMaxWidth += w;
+                else
+                    currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth);
+                lastWordBoundary = j;
+            }
+
+            bool isSpace = (j < len) && isSpaceAccordingToStyle(c, style());
+            bool isCollapsibleWhiteSpace = (j < len) && style()->isCollapsibleWhiteSpace(c);
+            if (j < len && style()->autoWrap())
+                m_hasBreakableChar = true;
+
+            // Add in wordSpacing to our currMaxWidth, but not if this is the last word on a line or the
+            // last word in the run.
+            if (wordSpacing && (isSpace || isCollapsibleWhiteSpace) && !containsOnlyWhitespace(j, len-j))
+                currMaxWidth += wordSpacing;
+
+            if (firstWord) {
+                firstWord = false;
+                // If the first character in the run is breakable, then we consider ourselves to have a beginning
+                // minimum width of 0, since a break could occur right before our run starts, preventing us from ever
+                // being appended to a previous text run when considering the total minimum width of the containing block.
+                if (hasBreak)
+                    m_hasBreakableChar = true;
+                m_beginMinWidth = hasBreak ? 0 : w;
+            }
+            m_endMinWidth = w;
+
+            if (currMinWidth > m_minWidth)
+                m_minWidth = currMinWidth;
+            currMinWidth = 0;
+
+            i += wordLen - 1;
+        } else {
+            // Nowrap can never be broken, so don't bother setting the
+            // breakable character boolean. Pre can only be broken if we encounter a newline.
+            if (style()->autoWrap() || isNewline)
+                m_hasBreakableChar = true;
+
+            if (currMinWidth > m_minWidth)
+                m_minWidth = currMinWidth;
+            currMinWidth = 0;
+
+            if (isNewline) { // Only set if preserveNewline was true and we saw a newline.
+                if (firstLine) {
+                    firstLine = false;
+                    leadWidth = 0;
+                    if (!style()->autoWrap())
+                        m_beginMinWidth = currMaxWidth;
+                }
+
+                if (currMaxWidth > m_maxWidth)
+                    m_maxWidth = currMaxWidth;
+                currMaxWidth = 0;
+            } else {
+                currMaxWidth += f.width(TextRun(txt + i, 1, allowTabs(), leadWidth + currMaxWidth));
+                needsWordSpacing = isSpace && !previousCharacterIsSpace && i == len - 1;
+            }
+            ASSERT(lastWordBoundary == i);
+            lastWordBoundary++;
+        }
+    }
+
+    if (needsWordSpacing && len > 1 || ignoringSpaces && !firstWord)
+        currMaxWidth += wordSpacing;
+
+    m_minWidth = max(currMinWidth, m_minWidth);
+    m_maxWidth = max(currMaxWidth, m_maxWidth);
+
+    if (!style()->autoWrap())
+        m_minWidth = m_maxWidth;
+
+    if (style()->whiteSpace() == PRE) {
+        if (firstLine)
+            m_beginMinWidth = m_maxWidth;
+        m_endMinWidth = currMaxWidth;
+    }
+
+    setPrefWidthsDirty(false);
+}
+
+bool RenderText::containsOnlyWhitespace(unsigned from, unsigned len) const
+{
+    unsigned currPos;
+    for (currPos = from;
+         currPos < from + len && ((*m_text)[currPos] == '\n' || (*m_text)[currPos] == ' ' || (*m_text)[currPos] == '\t');
+         currPos++) { }
+    return currPos >= (from + len);
+}
+
+int RenderText::minXPos() const
+{
+    if (!m_firstTextBox)
+        return 0;
+
+    // FIXME: we should not use an arbitrary value like this.  Perhaps we should use INT_MAX.
+    int minXPos = 6666666;
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+        minXPos = min(minXPos, static_cast<int>(box->m_x));
+    return minXPos;
+}
+
+int RenderText::xPos() const
+{
+    return m_firstTextBox ? m_firstTextBox->m_x : 0;
+}
+
+int RenderText::yPos() const
+{
+    return m_firstTextBox ? m_firstTextBox->m_y : 0;
+}
+
+void RenderText::setSelectionState(SelectionState state)
+{
+    InlineTextBox* box;
+
+    m_selectionState = state;
+    if (state == SelectionStart || state == SelectionEnd || state == SelectionBoth) {
+        int startPos, endPos;
+        selectionStartEnd(startPos, endPos);
+        if (selectionState() == SelectionStart) {
+            endPos = textLength();
+
+            // to handle selection from end of text to end of line
+            if (startPos != 0 && startPos == endPos)
+                startPos = endPos - 1;
+        } else if (selectionState() == SelectionEnd)
+            startPos = 0;
+
+        for (box = firstTextBox(); box; box = box->nextTextBox()) {
+            if (box->isSelected(startPos, endPos)) {
+                RootInlineBox* line = box->root();
+                if (line)
+                    line->setHasSelectedChildren(true);
+            }
+        }
+    } else {
+        for (box = firstTextBox(); box; box = box->nextTextBox()) {
+            RootInlineBox* line = box->root();
+            if (line)
+                line->setHasSelectedChildren(state == SelectionInside);
+        }
+    }
+
+    containingBlock()->setSelectionState(state);
+}
+
+void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset, unsigned len, bool force)
+{
+    unsigned oldLen = textLength();
+    unsigned newLen = text->length();
+    int delta = newLen - oldLen;
+    unsigned end = len ? offset + len - 1 : offset;
+
+    RootInlineBox* firstRootBox = 0;
+    RootInlineBox* lastRootBox = 0;
+
+    bool dirtiedLines = false;
+
+    // Dirty all text boxes that include characters in between offset and offset+len.
+    for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
+        // Text run is entirely before the affected range.
+        if (curr->end() < offset)
+            continue;
+
+        // Text run is entirely after the affected range.
+        if (curr->start() > end) {
+            curr->offsetRun(delta);
+            RootInlineBox* root = curr->root();
+            if (!firstRootBox) {
+                firstRootBox = root;
+                if (!dirtiedLines) {
+                    // The affected area was in between two runs. Go ahead and mark the root box of
+                    // the run after the affected area as dirty.
+                    firstRootBox->markDirty();
+                    dirtiedLines = true;
+                }
+            }
+            lastRootBox = root;
+        } else if (curr->end() >= offset && curr->end() <= end) {
+            // Text run overlaps with the left end of the affected range.
+            curr->dirtyLineBoxes();
+            dirtiedLines = true;
+        } else if (curr->start() <= offset && curr->end() >= end) {
+            // Text run subsumes the affected range.
+            curr->dirtyLineBoxes();
+            dirtiedLines = true;
+        } else if (curr->start() <= end && curr->end() >= end) {
+            // Text run overlaps with right end of the affected range.
+            curr->dirtyLineBoxes();
+            dirtiedLines = true;
+        }
+    }
+
+    // Now we have to walk all of the clean lines and adjust their cached line break information
+    // to reflect our updated offsets.
+    if (lastRootBox)
+        lastRootBox = lastRootBox->nextRootBox();
+    if (firstRootBox) {
+        RootInlineBox* prev = firstRootBox->prevRootBox();
+        if (prev)
+            firstRootBox = prev;
+    }
+    for (RootInlineBox* curr = firstRootBox; curr && curr != lastRootBox; curr = curr->nextRootBox()) {
+        if (curr->lineBreakObj() == this && curr->lineBreakPos() > end)
+            curr->setLineBreakPos(curr->lineBreakPos() + delta);
+    }
+
+    // If the text node is empty, dirty the line where new text will be inserted.
+    if (!firstTextBox() && parent()) {
+        parent()->dirtyLinesFromChangedChild(this);
+        dirtiedLines = true;
+    }
+
+    m_linesDirty = dirtiedLines;
+    setText(text, force);
+}
+
+static inline bool isInlineFlowOrEmptyText(RenderObject* o)
+{
+    if (o->isInlineFlow())
+        return true;
+    if (!o->isText())
+        return false;
+    StringImpl* text = static_cast<RenderText*>(o)->text();
+    if (!text)
+        return true;
+    return !text->length();
+}
+
+UChar RenderText::previousCharacter()
+{
+    // find previous text renderer if one exists
+    RenderObject* previousText = this;
+    while ((previousText = previousText->previousInPreOrder()))
+        if (!isInlineFlowOrEmptyText(previousText))
+            break;
+    UChar prev = ' ';
+    if (previousText && previousText->isText())
+        if (StringImpl* previousString = static_cast<RenderText*>(previousText)->text())
+            prev = (*previousString)[previousString->length() - 1];
+    return prev;
+}
+
+void RenderText::setTextInternal(PassRefPtr<StringImpl> text)
+{
+    m_text = text;
+    ASSERT(m_text);
+
+    m_text = m_text->replace('\\', backslashAsCurrencySymbol());
+
+#if ENABLE(SVG)
+    if (isSVGText()) {
+        if (style() && style()->whiteSpace() == PRE) {
+            // Spec: When xml:space="preserve", the SVG user agent will do the following using a
+            // copy of the original character data content. It will convert all newline and tab
+            // characters into space characters. Then, it will draw all space characters, including
+            // leading, trailing and multiple contiguous space characters.
+
+            m_text = m_text->replace('\n', ' ');
+
+            // If xml:space="preserve" is set, white-space is set to "pre", which
+            // preserves leading, trailing & contiguous space character for us.
+       } else {
+            // Spec: When xml:space="default", the SVG user agent will do the following using a
+            // copy of the original character data content. First, it will remove all newline
+            // characters. Then it will convert all tab characters into space characters.
+            // Then, it will strip off all leading and trailing space characters.
+            // Then, all contiguous space characters will be consolidated.    
+
+           m_text = m_text->replace('\n', StringImpl::empty());
+
+           // If xml:space="default" is set, white-space is set to "nowrap", which handles
+           // leading, trailing & contiguous space character removal for us.
+        }
+
+        m_text = m_text->replace('\t', ' ');
+    }
+#endif
+
+    if (style()) {
+        switch (style()->textTransform()) {
+            case TTNONE:
+                break;
+            case CAPITALIZE: {
+                m_text = m_text->capitalize(previousCharacter());
+                break;
+            }
+            case UPPERCASE:
+                m_text = m_text->upper();
+                break;
+            case LOWERCASE:
+                m_text = m_text->lower();
+                break;
+        }
+
+        // We use the same characters here as for list markers.
+        // See the listMarkerText function in RenderListMarker.cpp.
+        switch (style()->textSecurity()) {
+            case TSNONE:
+                break;
+            case TSCIRCLE:
+                m_text = m_text->secure(whiteBullet);
+                break;
+            case TSDISC:
+                m_text = m_text->secure(bullet);
+                break;
+            case TSSQUARE:
+                m_text = m_text->secure(blackSquare);
+        }
+    }
+
+    ASSERT(m_text);
+    ASSERT(!isBR() || (textLength() == 1 && (*m_text)[0] == '\n'));
+
+    m_isAllASCII = charactersAreAllASCII(m_text.get());
+}
+
+void RenderText::setText(PassRefPtr<StringImpl> text, bool force)
+{
+    ASSERT(text);
+
+    if (!force && equal(m_text.get(), text.get()))
+        return;
+
+    setTextInternal(text);
+    setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+int RenderText::height() const
+{
+    int retval = 0;
+    if (firstTextBox())
+        retval = lastTextBox()->m_y + lastTextBox()->height() - firstTextBox()->m_y;
+    return retval;
+}
+
+int RenderText::lineHeight(bool firstLine, bool) const
+{
+    // Always use the interior line height of the parent (e.g., if our parent is an inline block).
+    return parent()->lineHeight(firstLine, true);
+}
+
+void RenderText::dirtyLineBoxes(bool fullLayout, bool)
+{
+    if (fullLayout)
+        deleteTextBoxes();
+    else if (!m_linesDirty) {
+        for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+            box->dirtyLineBoxes();
+    }
+    m_linesDirty = false;
+}
+
+InlineTextBox* RenderText::createInlineTextBox()
+{
+    return new (renderArena()) InlineTextBox(this);
+}
+
+InlineBox* RenderText::createInlineBox(bool, bool isRootLineBox, bool)
+{
+    ASSERT(!isRootLineBox);
+    InlineTextBox* textBox = createInlineTextBox();
+    if (!m_firstTextBox)
+        m_firstTextBox = m_lastTextBox = textBox;
+    else {
+        m_lastTextBox->setNextLineBox(textBox);
+        textBox->setPreviousLineBox(m_lastTextBox);
+        m_lastTextBox = textBox;
+    }
+    return textBox;
+}
+
+void RenderText::position(InlineBox* box)
+{
+    InlineTextBox* s = static_cast<InlineTextBox*>(box);
+
+    // FIXME: should not be needed!!!
+    if (!s->m_len) {
+        // We want the box to be destroyed.
+        s->remove();
+        s->destroy(renderArena());
+        m_firstTextBox = m_lastTextBox = 0;
+        return;
+    }
+
+    m_containsReversedText |= s->direction() == RTL;
+}
+
+unsigned int RenderText::width(unsigned int from, unsigned int len, int xPos, bool firstLine) const
+{
+    if (from >= textLength())
+        return 0;
+
+    if (from + len > textLength())
+        len = textLength() - from;
+
+    return width(from, len, style(firstLine)->font(), xPos);
+}
+
+unsigned int RenderText::width(unsigned int from, unsigned int len, const Font& f, int xPos) const
+{
+    if (!characters() || from > textLength())
+        return 0;
+
+    if (from + len > textLength())
+        len = textLength() - from;
+
+    int w;
+    if (&f == &style()->font()) {
+        if (!style()->preserveNewline() && !from && len == textLength())
+            w = maxPrefWidth();
+        else
+            w = widthFromCache(f, from, len, xPos);
+    } else
+        w = f.width(TextRun(text()->characters() + from, len, allowTabs(), xPos));
+
+    return w;
+}
+
+int RenderText::width() const
+{
+    // FIXME: we should not use an arbitrary value like this.  Perhaps we should use INT_MAX.
+    int minx = 100000000;
+    int maxx = 0;
+    // slooow
+    for (InlineTextBox* s = firstTextBox(); s; s = s->nextTextBox()) {
+        if (s->m_x < minx)
+            minx = s->m_x;
+        if (s->m_x + s->m_width > maxx)
+            maxx = s->m_x + s->m_width;
+    }
+
+    return max(0, maxx - minx);
+}
+
+IntRect RenderText::absoluteClippedOverflowRect()
+{
+    RenderObject* cb = containingBlock();
+    return cb->absoluteClippedOverflowRect();
+}
+
+IntRect RenderText::selectionRect(bool clipToVisibleContent)
+{
+    ASSERT(!needsLayout());
+
+    IntRect rect;
+    if (selectionState() == SelectionNone)
+        return rect;
+    RenderBlock* cb =  containingBlock();
+    if (!cb)
+        return rect;
+
+    // Now calculate startPos and endPos for painting selection.
+    // We include a selection while endPos > 0
+    int startPos, endPos;
+    if (selectionState() == SelectionInside) {
+        // We are fully selected.
+        startPos = 0;
+        endPos = textLength();
+    } else {
+        selectionStartEnd(startPos, endPos);
+        if (selectionState() == SelectionStart)
+            endPos = textLength();
+        else if (selectionState() == SelectionEnd)
+            startPos = 0;
+    }
+
+    if (startPos == endPos)
+        return rect;
+
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+        rect.unite(box->selectionRect(0, 0, startPos, endPos));
+
+    if (clipToVisibleContent)
+        computeAbsoluteRepaintRect(rect);
+    else {
+        if (cb->hasColumns())
+            cb->adjustRectForColumns(rect);
+        int absx, absy;
+        absolutePosition(absx, absy);
+        rect.move(absx, absy);
+    }
+
+    return rect;
+}
+
+int RenderText::verticalPositionHint(bool firstLine) const
+{
+    if (parent()->isReplaced())
+        return 0; // Treat inline blocks just like blocks.  There can't be any vertical position hint.
+    return parent()->verticalPositionHint(firstLine);
+}
+
+int RenderText::caretMinOffset() const
+{
+    InlineTextBox* box = firstTextBox();
+    if (!box)
+        return 0;
+    int minOffset = box->m_start;
+    for (box = box->nextTextBox(); box; box = box->nextTextBox())
+        minOffset = min(minOffset, box->m_start);
+    return minOffset;
+}
+
+int RenderText::caretMaxOffset() const
+{
+    InlineTextBox* box = lastTextBox();
+    if (!box)
+        return textLength();
+    int maxOffset = box->m_start + box->m_len;
+    for (box = box->prevTextBox(); box; box = box->prevTextBox())
+        maxOffset = max(maxOffset, box->m_start + box->m_len);
+    return maxOffset;
+}
+
+unsigned RenderText::caretMaxRenderedOffset() const
+{
+    int l = 0;
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+        l += box->m_len;
+    return l;
+}
+
+int RenderText::previousOffset(int current) const
+{
+    StringImpl* si = m_text.get();
+    TextBreakIterator* iterator = characterBreakIterator(si->characters(), si->length());
+    if (!iterator)
+        return current - 1;
+
+    long result = textBreakPreceding(iterator, current);
+    if (result == TextBreakDone)
+        result = current - 1;
+
+    return result;
+}
+
+int RenderText::nextOffset(int current) const
+{
+    StringImpl* si = m_text.get();
+    TextBreakIterator* iterator = characterBreakIterator(si->characters(), si->length());
+    if (!iterator)
+        return current + 1;
+
+    long result = textBreakFollowing(iterator, current);
+    if (result == TextBreakDone)
+        result = current + 1;
+
+    return result;
+}
+
+#ifndef NDEBUG
+
+void RenderText::checkConsistency() const
+{
+#ifdef CHECK_CONSISTENCY
+    const InlineTextBox* prev = 0;
+    for (const InlineTextBox* child = m_firstTextBox; child != 0; child = child->nextTextBox()) {
+        ASSERT(child->object() == this);
+        ASSERT(child->prevTextBox() == prev);
+        prev = child;
+    }
+    ASSERT(prev == m_lastTextBox);
+#endif
+}
+
+#endif
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderText.h b/WebCore/rendering/RenderText.h
new file mode 100644
index 0000000..a68ba57
--- /dev/null
+++ b/WebCore/rendering/RenderText.h
@@ -0,0 +1,181 @@
+/*
+ * (C) 1999 Lars Knoll ([email protected])
+ * (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderText_h
+#define RenderText_h
+
+#include "RenderObject.h"
+
+namespace WebCore {
+
+class InlineTextBox;
+class StringImpl;
+
+class RenderText : public RenderObject {
+public:
+    RenderText(Node*, PassRefPtr<StringImpl>);
+#ifndef NDEBUG
+    virtual ~RenderText();
+#endif
+
+    virtual const char* renderName() const;
+
+    virtual bool isTextFragment() const;
+    virtual bool isWordBreak() const;
+
+    virtual PassRefPtr<StringImpl> originalText() const;
+
+    void extractTextBox(InlineTextBox*);
+    void attachTextBox(InlineTextBox*);
+    void removeTextBox(InlineTextBox*);
+
+    virtual void destroy();
+
+    StringImpl* text() const { return m_text.get(); }
+
+    virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun = false);
+    virtual InlineTextBox* createInlineTextBox();
+    virtual void dirtyLineBoxes(bool fullLayout, bool isRootInlineBox = false);
+
+    virtual void paint(PaintInfo&, int tx, int ty) { ASSERT_NOT_REACHED(); }
+    virtual void layout() { ASSERT_NOT_REACHED(); }
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) { ASSERT_NOT_REACHED(); return false; }
+
+    virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
+    virtual void addLineBoxRects(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
+
+    virtual VisiblePosition positionForCoordinates(int x, int y);
+
+    const UChar* characters() const { return m_text->characters(); }
+    unsigned textLength() const { return m_text->length(); } // non virtual implementation of length()
+    virtual void position(InlineBox*);
+
+    virtual unsigned width(unsigned from, unsigned len, const Font&, int xPos) const;
+    virtual unsigned width(unsigned from, unsigned len, int xPos, bool firstLine = false) const;
+    virtual int width() const;
+    virtual int height() const;
+
+    virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
+
+    virtual int minPrefWidth() const;
+    virtual int maxPrefWidth() const;
+
+    void trimmedPrefWidths(int leadWidth,
+                           int& beginMinW, bool& beginWS,
+                           int& endMinW, bool& endWS,
+                           bool& hasBreakableChar, bool& hasBreak,
+                           int& beginMaxW, int& endMaxW,
+                           int& minW, int& maxW, bool& stripFrontSpaces);
+
+    // returns the minimum x position of all runs relative to the parent.
+    // defaults to 0.
+    int minXPos() const;
+
+    virtual int xPos() const;
+    virtual int yPos() const;
+
+    virtual int verticalPositionHint(bool firstLine) const;
+
+    void setText(PassRefPtr<StringImpl>, bool force = false);
+    void setTextWithOffset(PassRefPtr<StringImpl>, unsigned offset, unsigned len, bool force = false);
+
+    virtual bool canBeSelectionLeaf() const { return true; }
+    virtual SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState); }
+    virtual void setSelectionState(SelectionState s);
+    virtual IntRect selectionRect(bool clipToVisibleContent = true);
+    virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
+
+    virtual int marginLeft() const { return style()->marginLeft().calcMinValue(0); }
+    virtual int marginRight() const { return style()->marginRight().calcMinValue(0); }
+
+    virtual IntRect absoluteClippedOverflowRect();
+
+    InlineTextBox* firstTextBox() const { return m_firstTextBox; }
+    InlineTextBox* lastTextBox() const { return m_lastTextBox; }
+
+    virtual int caretMinOffset() const;
+    virtual int caretMaxOffset() const;
+    virtual unsigned caretMaxRenderedOffset() const;
+
+    virtual int previousOffset(int current) const;
+    virtual int nextOffset(int current) const;
+
+    bool containsReversedText() const { return m_containsReversedText; }
+
+    InlineTextBox* findNextInlineTextBox(int offset, int& pos) const;
+
+    bool allowTabs() const { return !style()->collapseWhiteSpace(); }
+
+    void checkConsistency() const;
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+    virtual void setTextInternal(PassRefPtr<StringImpl>);
+    virtual void calcPrefWidths(int leadWidth);
+    virtual UChar previousCharacter();
+
+private:
+    // Make length() private so that callers that have a RenderText*
+    // will use the more efficient textLength() instead, while
+    // callers with a RenderObject* can continue to use length().
+    virtual unsigned length() const { return textLength(); }
+
+    void deleteTextBoxes();
+    bool containsOnlyWhitespace(unsigned from, unsigned len) const;
+    int widthFromCache(const Font&, int start, int len, int xPos) const;
+    bool isAllASCII() const { return m_isAllASCII; }
+
+    RefPtr<StringImpl> m_text;
+
+    InlineTextBox* m_firstTextBox;
+    InlineTextBox* m_lastTextBox;
+
+    int m_minWidth;
+    int m_maxWidth;
+    int m_beginMinWidth;
+    int m_endMinWidth;
+
+    unsigned m_selectionState : 3; // enums on Windows are signed, so this needs to be unsigned to prevent it turning negative. 
+    bool m_hasBreakableChar : 1; // Whether or not we can be broken into multiple lines.
+    bool m_hasBreak : 1; // Whether or not we have a hard break (e.g., <pre> with '\n').
+    bool m_hasTab : 1; // Whether or not we have a variable width tab character (e.g., <pre> with '\t').
+    bool m_hasBeginWS : 1; // Whether or not we begin with WS (only true if we aren't pre)
+    bool m_hasEndWS : 1; // Whether or not we end with WS (only true if we aren't pre)
+    bool m_linesDirty : 1; // This bit indicates that the text run has already dirtied specific
+                           // line boxes, and this hint will enable layoutInlineChildren to avoid
+                           // just dirtying everything when character data is modified (e.g., appended/inserted
+                           // or removed).
+    bool m_containsReversedText : 1;
+    bool m_isAllASCII : 1;
+};
+
+#ifdef NDEBUG
+inline void RenderText::checkConsistency() const
+{
+}
+#endif
+
+} // namespace WebCore
+
+#endif // RenderText_h
diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp
new file mode 100644
index 0000000..a971028
--- /dev/null
+++ b/WebCore/rendering/RenderTextControl.cpp
@@ -0,0 +1,1272 @@
+/**
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderTextControl.h"
+
+#include "CharacterNames.h"
+#include "CSSStyleSelector.h"
+#include "Document.h"
+#include "Editor.h"
+#include "EditorClient.h"
+#include "Event.h"
+#include "EventNames.h"
+#include "FontSelector.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "HTMLBRElement.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "HTMLTextAreaElement.h"
+#include "HitTestResult.h"
+#include "LocalizedStrings.h"
+#include "MouseEvent.h"
+#include "PlatformKeyboardEvent.h"
+#include "RenderScrollbar.h"
+#include "RenderTheme.h"
+#include "ScrollbarTheme.h"
+#include "SearchPopupMenu.h"
+#include "SelectionController.h"
+#include "Settings.h"
+#include "Text.h"
+#include "TextControlInnerElements.h"
+#include "TextIterator.h"
+#include "htmlediting.h"
+#include "visible_units.h"
+#include <math.h>
+
+#ifdef ANDROID_LAYOUT
+#include "FrameView.h"
+#endif
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+// Value chosen by observation.  This can be tweaked.
+static const int minColorContrastValue = 1300;
+
+static Color disabledTextColor(const Color& textColor, const Color& backgroundColor)
+{
+    // The explicit check for black is an optimization for the 99% case (black on white).
+    // This also means that black on black will turn into grey on black when disabled.
+    Color disabledColor;
+    if (textColor.rgb() == Color::black || differenceSquared(textColor, Color::white) > differenceSquared(backgroundColor, Color::white))
+        disabledColor = textColor.light();
+    else
+        disabledColor = textColor.dark();
+    
+    // If there's not very much contrast between the disabled color and the background color,
+    // just leave the text color alone.  We don't want to change a good contrast color scheme so that it has really bad contrast.
+    // If the the contrast was already poor, then it doesn't do any good to change it to a different poor contrast color scheme.
+    if (differenceSquared(disabledColor, backgroundColor) < minColorContrastValue)
+        return textColor;
+    
+    return disabledColor;
+}
+
+RenderTextControl::RenderTextControl(Node* node, bool multiLine)
+    : RenderBlock(node)
+    , m_dirty(false)
+    , m_multiLine(multiLine)
+    , m_placeholderVisible(false)
+    , m_userEdited(false)
+    , m_shouldDrawCapsLockIndicator(false)
+    , m_searchPopup(0)
+    , m_searchPopupIsVisible(false)
+    , m_searchEventTimer(this, &RenderTextControl::searchEventTimerFired)
+{
+}
+
+RenderTextControl::~RenderTextControl()
+{
+    if (m_searchPopup) {
+        m_searchPopup->disconnectClient();
+        m_searchPopup = 0;
+    }
+    if (m_multiLine && node())
+        static_cast<HTMLTextAreaElement*>(node())->rendererWillBeDestroyed();
+    // The children renderers have already been destroyed by destroyLeftoverChildren
+    if (m_innerBlock)
+        m_innerBlock->detach();
+    else if (m_innerText)
+        m_innerText->detach();
+}
+
+void RenderTextControl::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    if (m_innerBlock) {
+        // We may have set the width and the height in the old style in layout(). Reset them now to avoid
+        // getting a spurious layout hint.
+        m_innerBlock->renderer()->style()->setHeight(Length());
+        m_innerBlock->renderer()->style()->setWidth(Length());
+        m_innerBlock->renderer()->setStyle(createInnerBlockStyle(style()));
+    }
+
+    if (m_innerText) {
+        RenderBlock* textBlockRenderer = static_cast<RenderBlock*>(m_innerText->renderer());
+        RefPtr<RenderStyle> textBlockStyle = createInnerTextStyle(style());
+        // We may have set the width and the height in the old style in layout(). Reset them now to avoid
+        // getting a spurious layout hint.
+        textBlockRenderer->style()->setHeight(Length());
+        textBlockRenderer->style()->setWidth(Length());
+        textBlockRenderer->setStyle(textBlockStyle);
+        for (Node* n = m_innerText->firstChild(); n; n = n->traverseNextNode(m_innerText.get())) {
+            if (n->renderer())
+                n->renderer()->setStyle(textBlockStyle);
+        }
+    }
+    if (m_resultsButton && m_resultsButton->renderer())
+        m_resultsButton->renderer()->setStyle(createResultsButtonStyle(style()));
+
+    if (m_cancelButton && m_cancelButton->renderer())
+        m_cancelButton->renderer()->setStyle(createCancelButtonStyle(style()));
+
+    setHasOverflowClip(false);
+    setReplaced(isInline());
+}
+
+PassRefPtr<RenderStyle> RenderTextControl::createInnerBlockStyle(const RenderStyle* startStyle)
+{
+    RefPtr<RenderStyle> innerBlockStyle = RenderStyle::create();
+
+    innerBlockStyle->inheritFrom(startStyle);
+    innerBlockStyle->setDisplay(BLOCK);
+    innerBlockStyle->setDirection(LTR);
+    // We don't want the shadow dom to be editable, so we set this block to read-only in case the input itself is editable.
+    innerBlockStyle->setUserModify(READ_ONLY);
+
+    return innerBlockStyle.release();
+}
+
+PassRefPtr<RenderStyle> RenderTextControl::createInnerTextStyle(const RenderStyle* startStyle)
+{
+    HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(node());
+    bool placeholderShouldBeVisible = !m_multiLine && static_cast<HTMLInputElement*>(element)->placeholderShouldBeVisible();
+
+    RefPtr<RenderStyle> textBlockStyle;
+    if (placeholderShouldBeVisible) {
+        RenderStyle* pseudoStyle = getCachedPseudoStyle(RenderStyle::INPUT_PLACEHOLDER);
+        textBlockStyle = RenderStyle::clone(pseudoStyle);
+    } else {
+        textBlockStyle = RenderStyle::create();   
+        textBlockStyle->inheritFrom(startStyle);
+    }
+    
+    // The inner block, if present, always has its direction set to LTR,
+    // so we need to inherit the direction from the element.
+    textBlockStyle->setDirection(style()->direction());
+    textBlockStyle->setUserModify(element->isReadOnlyControl() || element->disabled() ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
+    if (m_innerBlock)
+        textBlockStyle->setDisplay(INLINE_BLOCK);
+    else
+        textBlockStyle->setDisplay(BLOCK);
+
+    if (m_multiLine) {
+        // Forward overflow properties.
+        textBlockStyle->setOverflowX(startStyle->overflowX() == OVISIBLE ? OAUTO : startStyle->overflowX());
+        textBlockStyle->setOverflowY(startStyle->overflowY() == OVISIBLE ? OAUTO : startStyle->overflowY());
+
+        // Set word wrap property based on wrap attribute.
+        if (!static_cast<HTMLTextAreaElement*>(element)->shouldWrapText()) {
+            textBlockStyle->setWhiteSpace(PRE);
+            textBlockStyle->setWordWrap(NormalWordWrap);
+        } else {
+            textBlockStyle->setWhiteSpace(PRE_WRAP);
+            textBlockStyle->setWordWrap(BreakWordWrap);
+        }
+    } else {
+        textBlockStyle->setWhiteSpace(PRE);
+        textBlockStyle->setWordWrap(NormalWordWrap);
+        textBlockStyle->setOverflowX(OHIDDEN);
+        textBlockStyle->setOverflowY(OHIDDEN);
+        
+        // Do not allow line-height to be smaller than our default.
+        if (textBlockStyle->font().lineSpacing() > lineHeight(true, true))
+            textBlockStyle->setLineHeight(Length(-100.0f, Percent));
+    }
+
+    if (!m_multiLine) {
+        // We're adding one extra pixel of padding to match WinIE.
+        textBlockStyle->setPaddingLeft(Length(1, Fixed));
+        textBlockStyle->setPaddingRight(Length(1, Fixed));
+    } else {
+        // We're adding three extra pixels of padding to line textareas up with text fields.
+        textBlockStyle->setPaddingLeft(Length(3, Fixed));
+        textBlockStyle->setPaddingRight(Length(3, Fixed));
+    }
+    
+    // When the placeholder is going to be displayed, temporarily override the text security to be "none".
+    // After this, updateFromElement will immediately update the text displayed.
+    // When the placeholder is no longer visible, updatePlaceholderVisiblity will reset the style, 
+    // and the text security mode will be set back to the computed value correctly.
+    if (!m_multiLine && static_cast<HTMLInputElement*>(element)->placeholderShouldBeVisible())
+        textBlockStyle->setTextSecurity(TSNONE);
+
+    if (!element->isEnabled())
+        textBlockStyle->setColor(disabledTextColor(textBlockStyle->color(), startStyle->backgroundColor()));
+
+    return textBlockStyle.release();
+}
+
+PassRefPtr<RenderStyle> RenderTextControl::createResultsButtonStyle(const RenderStyle* startStyle)
+{
+    ASSERT(!m_multiLine);
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+    RefPtr<RenderStyle> resultsBlockStyle;
+    if (input->maxResults() < 0)
+        resultsBlockStyle = getCachedPseudoStyle(RenderStyle::SEARCH_DECORATION);
+    else if (!input->maxResults())
+        resultsBlockStyle = getCachedPseudoStyle(RenderStyle::SEARCH_RESULTS_DECORATION);
+    else
+        resultsBlockStyle = getCachedPseudoStyle(RenderStyle::SEARCH_RESULTS_BUTTON);
+
+    if (!resultsBlockStyle)
+        resultsBlockStyle = RenderStyle::create();
+
+    if (startStyle)
+        resultsBlockStyle->inheritFrom(startStyle);
+
+    return resultsBlockStyle.release();
+}
+
+PassRefPtr<RenderStyle> RenderTextControl::createCancelButtonStyle(const RenderStyle* startStyle)
+{
+    RefPtr<RenderStyle> cancelBlockStyle;
+    
+    if (RefPtr<RenderStyle> pseudoStyle = getCachedPseudoStyle(RenderStyle::SEARCH_CANCEL_BUTTON))
+        // We may be sharing style with another search field, but we must not share the cancel button style.
+        cancelBlockStyle = RenderStyle::clone(pseudoStyle.get());
+    else
+        cancelBlockStyle = RenderStyle::create();
+
+    if (startStyle)
+        cancelBlockStyle->inheritFrom(startStyle);
+
+    updateCancelButtonVisibility(cancelBlockStyle.get());
+
+    return cancelBlockStyle.release();
+}
+
+void RenderTextControl::createSubtreeIfNeeded()
+{
+    bool isSearchField = !m_multiLine && static_cast<HTMLInputElement*>(node())->isSearchField();
+    if (isSearchField && !m_innerBlock) {
+        // Create the inner block element
+        m_innerBlock = new TextControlInnerElement(document(), node());
+        m_innerBlock->attachInnerElement(node(), createInnerBlockStyle(style()), renderArena());
+    }
+    if (isSearchField && !m_resultsButton) {
+        // Create the search results button element
+        m_resultsButton = new SearchFieldResultsButtonElement(document());
+        m_resultsButton->attachInnerElement(m_innerBlock.get(), createResultsButtonStyle(m_innerBlock->renderer()->style()), renderArena());
+    }
+    if (!m_innerText) {
+        // Create the text block element
+        // For non-search fields, there is no intermediate m_innerBlock as the shadow node.
+        // m_innerText will be the shadow node in that case.
+        
+        RenderStyle* parentStyle = style();
+        if (m_innerBlock)
+            parentStyle = m_innerBlock->renderer()->style();
+        m_innerText = new TextControlInnerTextElement(document(), m_innerBlock ? 0 : node());
+        m_innerText->attachInnerElement(m_innerBlock ? m_innerBlock.get() : node(), createInnerTextStyle(parentStyle), renderArena());
+    }
+    if (isSearchField && !m_cancelButton) {
+        // Create the cancel button element
+        m_cancelButton = new SearchFieldCancelButtonElement(document());
+        m_cancelButton->attachInnerElement(m_innerBlock.get(), createCancelButtonStyle(m_innerBlock->renderer()->style()), renderArena());
+    }
+}
+
+void RenderTextControl::updateFromElement()
+{
+    HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(node());
+
+    bool placeholderShouldBeVisible = !m_multiLine && static_cast<HTMLInputElement*>(element)->placeholderShouldBeVisible();
+    bool placeholderVisibilityShouldChange = m_placeholderVisible != placeholderShouldBeVisible;
+    m_placeholderVisible = placeholderShouldBeVisible;
+
+    createSubtreeIfNeeded();
+
+    if (m_cancelButton && m_cancelButton->renderer())
+        updateCancelButtonVisibility(m_cancelButton->renderer()->style());
+
+    m_innerText->renderer()->style()->setUserModify(element->isReadOnlyControl() || element->disabled() ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
+    
+    if (m_placeholderVisible) {
+        ExceptionCode ec;
+        m_innerText->setInnerText(static_cast<HTMLInputElement*>(element)->getAttribute(placeholderAttr), ec);
+    } else if (!element->valueMatchesRenderer() || m_multiLine || placeholderVisibilityShouldChange) {
+        String value;
+        if (m_multiLine)
+            value = static_cast<HTMLTextAreaElement*>(element)->value();
+        else
+            value = static_cast<HTMLInputElement*>(element)->value();
+        if (value.isNull())
+            value = "";
+        else
+            value = value.replace('\\', backslashAsCurrencySymbol());
+        if (value != text() || !m_innerText->hasChildNodes()) {
+            if (value != text()) {
+                if (Frame* frame = document()->frame())
+                    frame->editor()->clearUndoRedoOperations();
+            }
+            ExceptionCode ec = 0;
+            m_innerText->setInnerText(value, ec);
+            if (value.endsWith("\n") || value.endsWith("\r"))
+                m_innerText->appendChild(new HTMLBRElement(document()), ec);
+            m_dirty = false;
+            m_userEdited = false;
+        }
+        element->setValueMatchesRenderer();
+    }
+
+    if (m_searchPopupIsVisible)
+        m_searchPopup->updateFromElement();
+}
+
+void RenderTextControl::setUserEdited(bool isUserEdited)
+{
+    m_userEdited = isUserEdited;
+    document()->setIgnoreAutofocus(isUserEdited);
+}
+
+int RenderTextControl::selectionStart()
+{
+    Frame* frame = document()->frame();
+    if (!frame)
+        return 0;
+    return indexForVisiblePosition(frame->selection()->start());
+}
+
+int RenderTextControl::selectionEnd()
+{
+    Frame* frame = document()->frame();
+    if (!frame)
+        return 0;
+    return indexForVisiblePosition(frame->selection()->end());
+}
+
+void RenderTextControl::setSelectionStart(int start)
+{
+    setSelectionRange(start, max(start, selectionEnd()));
+}
+
+void RenderTextControl::setSelectionEnd(int end)
+{
+    setSelectionRange(min(end, selectionStart()), end);
+}
+
+void RenderTextControl::select()
+{
+    setSelectionRange(0, text().length());
+}
+
+void RenderTextControl::setSelectionRange(int start, int end)
+{
+    end = max(end, 0);
+    start = min(max(start, 0), end);
+
+    document()->updateLayout();
+
+    if (style()->visibility() == HIDDEN || !m_innerText || !m_innerText->renderer() || !m_innerText->renderer()->height()) {
+        if (m_multiLine)
+            static_cast<HTMLTextAreaElement*>(node())->cacheSelection(start, end);
+        else
+            static_cast<HTMLInputElement*>(node())->cacheSelection(start, end);
+        return;
+    }
+    VisiblePosition startPosition = visiblePositionForIndex(start);
+    VisiblePosition endPosition;
+    if (start == end)
+        endPosition = startPosition;
+    else
+        endPosition = visiblePositionForIndex(end);
+
+    ASSERT(startPosition.isNotNull() && endPosition.isNotNull());
+    ASSERT(startPosition.deepEquivalent().node()->shadowAncestorNode() == node() && endPosition.deepEquivalent().node()->shadowAncestorNode() == node());
+
+    Selection newSelection = Selection(startPosition, endPosition);
+
+    if (Frame* frame = document()->frame())
+        frame->selection()->setSelection(newSelection);
+
+    // FIXME: Granularity is stored separately on the frame, but also in the selection controller.
+    // The granularity in the selection controller should be used, and then this line of code would not be needed.
+    if (Frame* frame = document()->frame())
+        frame->setSelectionGranularity(CharacterGranularity);
+}
+
+Selection RenderTextControl::selection(int start, int end) const
+{
+    return Selection(VisiblePosition(m_innerText.get(), start, VP_DEFAULT_AFFINITY),
+                     VisiblePosition(m_innerText.get(), end, VP_DEFAULT_AFFINITY));
+}
+
+VisiblePosition RenderTextControl::visiblePositionForIndex(int index)
+{
+    if (index <= 0)
+        return VisiblePosition(m_innerText.get(), 0, DOWNSTREAM);
+    ExceptionCode ec = 0;
+    RefPtr<Range> range = Range::create(document());
+    range->selectNodeContents(m_innerText.get(), ec);
+    CharacterIterator it(range.get());
+    it.advance(index - 1);
+    return VisiblePosition(it.range()->endContainer(ec), it.range()->endOffset(ec), UPSTREAM);
+}
+
+int RenderTextControl::indexForVisiblePosition(const VisiblePosition& pos)
+{
+    Position indexPosition = pos.deepEquivalent();
+    if (!indexPosition.node() || indexPosition.node()->rootEditableElement() != m_innerText)
+        return 0;
+    ExceptionCode ec = 0;
+    RefPtr<Range> range = Range::create(document());
+    range->setStart(m_innerText.get(), 0, ec);
+    range->setEnd(indexPosition.node(), indexPosition.offset(), ec);
+    return TextIterator::rangeLength(range.get());
+}
+
+void RenderTextControl::updateCancelButtonVisibility(RenderStyle* style)
+{
+    ASSERT(!m_multiLine);
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+    if (input->value().isEmpty())
+        style->setVisibility(HIDDEN);
+    else
+        style->setVisibility(VISIBLE);
+}
+
+void RenderTextControl::subtreeHasChanged()
+{
+    bool wasDirty = m_dirty;
+    m_dirty = true;
+    m_userEdited = true;
+    HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(node());
+    if (m_multiLine) {
+        element->setValueMatchesRenderer(false);
+        if (element->focused())
+            if (Frame* frame = document()->frame())
+                frame->textDidChangeInTextArea(element);
+    } else {
+        HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
+        input->setValueFromRenderer(input->constrainValue(text()));
+        if (m_cancelButton && m_cancelButton->renderer())
+            updateCancelButtonVisibility(m_cancelButton->renderer()->style());
+
+        // If the incremental attribute is set, then dispatch the search event
+        if (!input->getAttribute(incrementalAttr).isNull())
+            startSearchEventTimer();
+
+        if (!wasDirty) {
+            if (input->focused())
+                if (Frame* frame = document()->frame())
+                    frame->textFieldDidBeginEditing(input);
+        }
+        if (input->focused())
+            if (Frame* frame = document()->frame())
+                frame->textDidChangeInTextField(input);
+    }
+}
+
+String RenderTextControl::finishText(Vector<UChar>& result) const
+{
+    // ANDROID: This method was modified with a fix from WebKit r31081. This
+    // comment can be removed the next time we update.
+
+    // Remove one trailing newline; there's always one that's collapsed out by rendering.
+    size_t size = result.size();
+    if (size && result[size - 1] == '\n')
+        result.shrink(--size);
+
+    // Convert backslash to currency symbol.
+    UChar symbol = backslashAsCurrencySymbol();
+    if (symbol != '\\') {
+        for (size_t i = 0; i < size; ++i) {
+            if (result[i] == '\\')
+                result[i] = symbol;
+        }
+    }
+
+    return String::adopt(result);
+}
+
+HTMLElement* RenderTextControl::innerTextElement() const
+{
+    return m_innerText.get();
+}
+
+String RenderTextControl::text()
+{
+    if (!m_innerText)
+        return "";
+ 
+    Frame* frame = document()->frame();
+    Text* compositionNode = frame ? frame->editor()->compositionNode() : 0;
+
+    Vector<UChar> result;
+
+    for (Node* n = m_innerText.get(); n; n = n->traverseNextNode(m_innerText.get())) {
+        if (n->isTextNode()) {
+            Text* text = static_cast<Text*>(n);
+            String data = text->data();
+            unsigned length = data.length();
+            if (text != compositionNode)
+                result.append(data.characters(), length);
+            else {
+                unsigned compositionStart = min(frame->editor()->compositionStart(), length);
+                unsigned compositionEnd = min(max(compositionStart, frame->editor()->compositionEnd()), length);
+                result.append(data.characters(), compositionStart);
+                result.append(data.characters() + compositionEnd, length - compositionEnd);
+            }
+        }
+    }
+
+    return finishText(result);
+}
+
+static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& breakOffset)
+{
+    RootInlineBox* next;
+    for (; line; line = next) {
+        next = line->nextRootBox();
+        if (next && !line->endsWithBreak()) {
+            ASSERT(line->lineBreakObj());
+            breakNode = line->lineBreakObj()->node();
+            breakOffset = line->lineBreakPos();
+            line = next;
+            return;
+        }
+    }
+    breakNode = 0;
+}
+
+String RenderTextControl::textWithHardLineBreaks()
+{
+    if (!m_innerText)
+        return "";
+    Node* firstChild = m_innerText->firstChild();
+    if (!firstChild)
+        return "";
+
+    document()->updateLayout();
+
+    RenderObject* renderer = firstChild->renderer();
+    if (!renderer)
+        return "";
+
+    InlineBox* box = renderer->isText() ? static_cast<RenderText*>(renderer)->firstTextBox() : renderer->inlineBoxWrapper();
+    if (!box)
+        return "";
+
+    Frame* frame = document()->frame();
+    Text* compositionNode = frame ? frame->editor()->compositionNode() : 0;
+
+    Node* breakNode;
+    unsigned breakOffset;
+    RootInlineBox* line = box->root();
+    getNextSoftBreak(line, breakNode, breakOffset);
+
+    Vector<UChar> result;
+
+    for (Node* n = firstChild; n; n = n->traverseNextNode(m_innerText.get())) {
+        if (n->hasTagName(brTag))
+            result.append(&newlineCharacter, 1);
+        else if (n->isTextNode()) {
+            Text* text = static_cast<Text*>(n);
+            String data = text->data();
+            unsigned length = data.length();
+            unsigned compositionStart = (text == compositionNode)
+                ? min(frame->editor()->compositionStart(), length) : 0;
+            unsigned compositionEnd = (text == compositionNode)
+                ? min(max(compositionStart, frame->editor()->compositionEnd()), length) : 0;
+            unsigned position = 0;
+            while (breakNode == n && breakOffset < compositionStart) {
+                result.append(data.characters() + position, breakOffset - position);
+                position = breakOffset;
+                result.append(&newlineCharacter, 1);
+                getNextSoftBreak(line, breakNode, breakOffset);
+            }
+            result.append(data.characters() + position, compositionStart - position);
+            position = compositionEnd;
+            while (breakNode == n && breakOffset <= length) {
+                if (breakOffset > position) {
+                    result.append(data.characters() + position, breakOffset - position);
+                    position = breakOffset;
+                    result.append(&newlineCharacter, 1);
+                }
+                getNextSoftBreak(line, breakNode, breakOffset);
+            }
+            result.append(data.characters() + position, length - position);
+        }
+        while (breakNode == n)
+            getNextSoftBreak(line, breakNode, breakOffset);
+    }
+
+    return finishText(result);
+}
+
+void RenderTextControl::calcHeight()
+{
+    int rows = 1;
+    if (m_multiLine)
+        rows = static_cast<HTMLTextAreaElement*>(node())->rows();
+
+    int line = m_innerText->renderer()->lineHeight(true, true);
+    int toAdd = paddingTop() + paddingBottom() + borderTop() + borderBottom();
+
+    int innerToAdd = m_innerText->renderer()->borderTop() + m_innerText->renderer()->borderBottom() +
+                     m_innerText->renderer()->paddingTop() + m_innerText->renderer()->paddingBottom() +
+                     m_innerText->renderer()->marginTop() + m_innerText->renderer()->marginBottom();
+    
+    if (m_resultsButton && m_resultsButton->renderer()) {
+        static_cast<RenderBlock*>(m_resultsButton->renderer())->calcHeight();
+        innerToAdd = max(innerToAdd,
+                         m_resultsButton->renderer()->borderTop() + m_resultsButton->renderer()->borderBottom() +
+                         m_resultsButton->renderer()->paddingTop() + m_resultsButton->renderer()->paddingBottom() +
+                         m_resultsButton->renderer()->marginTop() + m_resultsButton->renderer()->marginBottom());
+        line = max(line, m_resultsButton->renderer()->height());
+    }
+    if (m_cancelButton && m_cancelButton->renderer()) {
+        static_cast<RenderBlock*>(m_cancelButton->renderer())->calcHeight();
+        innerToAdd = max(innerToAdd,
+                         m_cancelButton->renderer()->borderTop() + m_cancelButton->renderer()->borderBottom() +
+                         m_cancelButton->renderer()->paddingTop() + m_cancelButton->renderer()->paddingBottom() +
+                         m_cancelButton->renderer()->marginTop() + m_cancelButton->renderer()->marginBottom());
+        line = max(line, m_cancelButton->renderer()->height());
+    }
+    toAdd += innerToAdd;
+
+    // FIXME: We should get the size of the scrollbar from the RenderTheme instead.
+    int scrollbarSize = 0;
+    // We are able to have a horizontal scrollbar if the overflow style is scroll, or if its auto and there's no word wrap.
+    if (m_innerText->renderer()->style()->overflowX() == OSCROLL ||  (m_innerText->renderer()->style()->overflowX() == OAUTO && m_innerText->renderer()->style()->wordWrap() == NormalWordWrap))
+        scrollbarSize = ScrollbarTheme::nativeTheme()->scrollbarThickness();
+
+    m_height = line * rows + toAdd + scrollbarSize;
+
+    RenderBlock::calcHeight();
+}
+
+int RenderTextControl::baselinePosition(bool b, bool isRootLineBox) const
+{
+    if (m_multiLine)
+        return height() + marginTop() + marginBottom();
+    return RenderBlock::baselinePosition(b, isRootLineBox);
+}
+
+bool RenderTextControl::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
+{
+    // If we're within the text control, we want to act as if we've hit the inner text block element, in case the point
+    // was on the control but not on the inner element (see Radar 4617841).
+
+    // In a search field, we want to act as if we've hit the results block if we're to the left of the inner text block,
+    // and act as if we've hit the close block if we're to the right of the inner text block.
+
+    if (RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction) &&
+        (result.innerNode() == element() || result.innerNode() == m_innerBlock)) {
+        IntPoint localPoint = IntPoint(x - tx - m_x, y - ty - m_y);
+        if (m_innerBlock) {
+            int textLeft = tx + m_x + m_innerBlock->renderer()->xPos() + m_innerText->renderer()->xPos();
+            int textRight = textLeft + m_innerText->renderer()->width();
+            if (m_resultsButton && m_resultsButton->renderer() && x < textLeft) {
+                result.setInnerNode(m_resultsButton.get());
+                result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - m_innerBlock->renderer()->xPos() - m_resultsButton->renderer()->xPos(),
+                                              localPoint.y() - m_innerText->renderer()->yPos() - m_innerBlock->renderer()->yPos() - m_resultsButton->renderer()->yPos()));
+                return true;
+            } 
+            if (m_cancelButton && m_cancelButton->renderer() && x > textRight) {
+                result.setInnerNode(m_cancelButton.get());
+                result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - m_innerBlock->renderer()->xPos() - m_cancelButton->renderer()->xPos(),
+                                              localPoint.y() - m_innerText->renderer()->yPos() - m_innerBlock->renderer()->yPos() - m_cancelButton->renderer()->yPos()));
+                return true;
+            }
+        }
+        
+        // Hit the inner text block.
+        result.setInnerNode(m_innerText.get());
+        result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - (m_innerBlock.get() ? m_innerBlock->renderer()->xPos() : 0),
+                                      localPoint.y() - m_innerText->renderer()->yPos() - (m_innerBlock.get() ? m_innerBlock->renderer()->yPos() : 0)));
+        
+        return true;
+    }
+
+    return false;
+}
+
+IntRect RenderTextControl::controlClipRect(int tx, int ty) const
+{
+    IntRect clipRect = contentBox();
+    clipRect.move(tx, ty);
+    return clipRect;
+}
+
+void RenderTextControl::layout()
+{
+    int oldHeight = m_height;
+    calcHeight();
+    bool relayoutChildren = oldHeight != m_height;
+
+    // Set the text block's height
+    int textBlockHeight = m_height - paddingTop() - paddingBottom() - borderTop() - borderBottom();
+    int currentTextBlockHeight = m_innerText->renderer()->height();
+    if (m_multiLine || m_innerBlock || currentTextBlockHeight > m_height) {
+        if (textBlockHeight != currentTextBlockHeight)
+            relayoutChildren = true;
+        m_innerText->renderer()->style()->setHeight(Length(textBlockHeight, Fixed));
+    }
+    if (m_innerBlock) {
+        if (textBlockHeight != m_innerBlock->renderer()->height())
+            relayoutChildren = true;
+        m_innerBlock->renderer()->style()->setHeight(Length(textBlockHeight, Fixed));
+    }
+
+#ifdef ANDROID_LAYOUT
+    int oldVisibleWidth = m_visibleWidth;
+#endif
+    
+    int oldWidth = m_width;
+    calcWidth();
+    
+    // FIXME: This causes cnn.com loading way slow. Comment it out for now
+//#ifdef ANDROID_LAYOUT
+#if 0
+    Frame* frame = document()->frame();
+    if (frame && frame->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) {
+        int maxWidth = frame->view()->visibleWidth() - 2 * ANDROID_FCTS_MARGIN_PADDING;
+        if (maxWidth > 0 && maxWidth < m_width) {
+            m_width = maxWidth;
+            // not only modify the control's width, we also need to modify its
+            // parent (even grandparent) width if it is not auto
+            Length styleWidth = style()->width();
+            if (styleWidth.isFixed()) {
+                // now we need to get max style width
+                maxWidth -= borderLeft() + borderRight() + paddingLeft() + paddingRight();                
+                style()->setWidth(Length(maxWidth, Fixed));
+            } else if (styleWidth.isPercent()) {
+                RenderObject* o = this;
+                while (RenderBox* p = (RenderBox*)(o->parent())) {
+                    int maxParentWidth = (int)(maxWidth * 100 / styleWidth.percent());
+                    if (p->width() <= maxParentWidth)
+                        break;
+                    p->setWidth(maxParentWidth);
+                    styleWidth = p->style()->width();
+                    if (!styleWidth.isPercent())
+                        break;
+                    o = p;
+                    maxWidth = maxParentWidth;                     
+                }
+            }
+        }
+    }
+#endif
+    if (oldWidth != m_width)
+        relayoutChildren = true;
+
+#ifdef ANDROID_LAYOUT
+    if (oldVisibleWidth != m_visibleWidth
+            && document()->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
+        relayoutChildren = true;
+#endif
+
+    int searchExtrasWidth = 0;
+    if (m_resultsButton && m_resultsButton->renderer()) {
+        m_resultsButton->renderer()->calcWidth();
+        searchExtrasWidth += m_resultsButton->renderer()->width();
+    }
+    if (m_cancelButton && m_cancelButton->renderer()) {
+        m_cancelButton->renderer()->calcWidth();
+        searchExtrasWidth += m_cancelButton->renderer()->width();
+    }
+
+    // Set the text block's width
+    int textBlockWidth = m_width - paddingLeft() - paddingRight() - borderLeft() - borderRight() -
+                         m_innerText->renderer()->paddingLeft() - m_innerText->renderer()->paddingRight() - searchExtrasWidth;
+    if (textBlockWidth != m_innerText->renderer()->width())
+        relayoutChildren = true;
+    m_innerText->renderer()->style()->setWidth(Length(textBlockWidth, Fixed));
+    if (m_innerBlock) {
+        int innerBlockWidth = m_width - paddingLeft() - paddingRight() - borderLeft() - borderRight();
+        if (innerBlockWidth != m_innerBlock->renderer()->width())
+            relayoutChildren = true;
+        m_innerBlock->renderer()->style()->setWidth(Length(innerBlockWidth, Fixed));
+    }
+
+    RenderBlock::layoutBlock(relayoutChildren);
+    
+    // For text fields, center the inner text vertically
+    // Don't do this for search fields, since we don't honor height for them
+    if (!m_multiLine) {
+        currentTextBlockHeight = m_innerText->renderer()->height();
+        if (!m_innerBlock && currentTextBlockHeight < m_height)
+            m_innerText->renderer()->setPos(m_innerText->renderer()->xPos(), (m_height - currentTextBlockHeight) / 2);
+    }
+}
+
+void RenderTextControl::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    RenderBlock::paint(paintInfo, tx, ty);
+    if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator)
+        theme()->paintCapsLockIndicator(this, paintInfo, absoluteContentBox());
+} 
+
+void RenderTextControl::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+
+    m_minPrefWidth = 0;
+    m_maxPrefWidth = 0;
+
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
+    else {
+        // Figure out how big a text control needs to be for a given number of characters
+        // (using "0" as the nominal character).
+        const UChar ch = '0';
+        float charWidth = style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, false, false, false));
+        int factor;
+        int scrollbarSize = 0;
+        if (m_multiLine) {
+            factor = static_cast<HTMLTextAreaElement*>(node())->cols();
+            // FIXME: We should get the size of the scrollbar from the RenderTheme instead.
+            if (m_innerText->renderer()->style()->overflowY() != OHIDDEN)
+                scrollbarSize = ScrollbarTheme::nativeTheme()->scrollbarThickness();
+        } else {
+            factor = static_cast<HTMLInputElement*>(node())->size();
+            if (factor <= 0)
+                factor = 20;
+        }
+        m_maxPrefWidth = static_cast<int>(ceilf(charWidth * factor)) + scrollbarSize +
+                         m_innerText->renderer()->paddingLeft() + m_innerText->renderer()->paddingRight();
+                
+        if (m_resultsButton && m_resultsButton->renderer())
+            m_maxPrefWidth += m_resultsButton->renderer()->borderLeft() + m_resultsButton->renderer()->borderRight() +
+                              m_resultsButton->renderer()->paddingLeft() + m_resultsButton->renderer()->paddingRight();
+        if (m_cancelButton && m_cancelButton->renderer())
+            m_maxPrefWidth += m_cancelButton->renderer()->borderLeft() + m_cancelButton->renderer()->borderRight() +
+                              m_cancelButton->renderer()->paddingLeft() + m_cancelButton->renderer()->paddingRight();
+    }
+
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+        m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+    } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
+        m_minPrefWidth = 0;
+    else
+        m_minPrefWidth = m_maxPrefWidth;
+
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
+        m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+        m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+    }
+
+    int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+
+    m_minPrefWidth += toAdd;
+    m_maxPrefWidth += toAdd;
+
+    // FIXME: This causes cnn.com loading way slow. Comment it out for now
+//#ifdef ANDROID_LAYOUT
+#if 0
+    Frame* frame = document()->frame();
+    if (frame && frame->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) {
+        int maxWidth = frame->view()->visibleWidth() - 2 * ANDROID_FCTS_MARGIN_PADDING;
+        if (maxWidth > 0 && maxWidth < m_minPrefWidth)
+            m_minPrefWidth = maxWidth;
+        if (maxWidth > 0 && maxWidth < m_maxPrefWidth)
+            m_maxPrefWidth = maxWidth;
+    }
+#endif
+    setPrefWidthsDirty(false);
+}
+
+void RenderTextControl::forwardEvent(Event* evt)
+{
+    if (evt->type() == eventNames().blurEvent) {
+        RenderObject* innerRenderer = m_innerText->renderer();
+        if (innerRenderer) {
+            RenderLayer* innerLayer = innerRenderer->layer();
+            if (innerLayer && !m_multiLine)
+                innerLayer->scrollToOffset(style()->direction() == RTL ? innerLayer->scrollWidth() : 0, 0);
+        }
+        capsLockStateMayHaveChanged();
+    } else if (evt->type() == eventNames().focusEvent)
+        capsLockStateMayHaveChanged();
+    else {
+        if (evt->isMouseEvent() && m_resultsButton && static_cast<MouseEvent*>(evt)->x() < m_innerText->renderer()->absoluteBoundingBoxRect().x())
+            m_resultsButton->defaultEventHandler(evt);
+        else if (evt->isMouseEvent() && m_cancelButton && static_cast<MouseEvent*>(evt)->x() > m_innerText->renderer()->absoluteBoundingBoxRect().right())
+            m_cancelButton->defaultEventHandler(evt);
+        else
+            m_innerText->defaultEventHandler(evt);
+    }
+}
+
+void RenderTextControl::selectionChanged(bool userTriggered)
+{
+    HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(node());
+    if (m_multiLine)
+        static_cast<HTMLTextAreaElement*>(element)->cacheSelection(selectionStart(), selectionEnd());
+    else
+        static_cast<HTMLInputElement*>(element)->cacheSelection(selectionStart(), selectionEnd());
+    if (Frame* frame = document()->frame())
+        if (frame->selection()->isRange() && userTriggered)
+            element->dispatchEventForType(eventNames().selectEvent, true, false);
+}
+
+void RenderTextControl::autoscroll()
+{
+    RenderLayer* layer = m_innerText->renderer()->layer();
+    if (layer)
+        layer->autoscroll();
+}
+
+int RenderTextControl::scrollWidth() const
+{
+    if (m_innerText)
+        return m_innerText->scrollWidth();
+    return RenderBlock::scrollWidth();
+}
+
+int RenderTextControl::scrollHeight() const
+{
+    if (m_innerText)
+        return m_innerText->scrollHeight();
+    return RenderBlock::scrollHeight();
+}
+
+int RenderTextControl::scrollLeft() const
+{
+    if (m_innerText)
+        return m_innerText->scrollLeft();
+    return RenderBlock::scrollLeft();
+}
+
+int RenderTextControl::scrollTop() const
+{
+    if (m_innerText)
+        return m_innerText->scrollTop();
+    return RenderBlock::scrollTop();
+}
+
+void RenderTextControl::setScrollLeft(int newLeft)
+{
+    if (m_innerText)
+        m_innerText->setScrollLeft(newLeft);
+}
+
+void RenderTextControl::setScrollTop(int newTop)
+{
+    if (m_innerText)
+        m_innerText->setScrollTop(newTop);
+}
+
+const AtomicString& RenderTextControl::autosaveName() const
+{
+    return static_cast<Element*>(node())->getAttribute(autosaveAttr);
+}
+
+void RenderTextControl::addSearchResult()
+{
+    ASSERT(!m_multiLine);
+
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+    if (input->maxResults() <= 0)
+        return;
+
+    String value = input->value();
+    if (value.isEmpty())
+        return;
+
+    Settings* settings = document()->settings();
+    if (!settings || settings->privateBrowsingEnabled())
+        return;
+
+    int size = static_cast<int>(m_recentSearches.size());
+    for (int i = size - 1; i >= 0; --i)
+        if (m_recentSearches[i] == value)
+            m_recentSearches.remove(i);
+
+    m_recentSearches.insert(0, value);
+    while (static_cast<int>(m_recentSearches.size()) > input->maxResults())
+        m_recentSearches.removeLast();
+
+    const AtomicString& name = autosaveName();
+    if (!m_searchPopup)
+        m_searchPopup = SearchPopupMenu::create(this);
+    m_searchPopup->saveRecentSearches(name, m_recentSearches);
+}
+
+void RenderTextControl::showPopup()
+{
+    if (m_searchPopupIsVisible)
+        return;
+
+    if (!m_searchPopup)
+        m_searchPopup = SearchPopupMenu::create(this);
+
+    if (!m_searchPopup->enabled())
+        return;
+    
+    m_searchPopupIsVisible = true;
+
+    const AtomicString& name = autosaveName();
+    m_searchPopup->loadRecentSearches(name, m_recentSearches);
+
+    // Trim the recent searches list if the maximum size has changed since we last saved.
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+    if (static_cast<int>(m_recentSearches.size()) > input->maxResults()) {
+        do
+            m_recentSearches.removeLast();
+        while (static_cast<int>(m_recentSearches.size()) > input->maxResults());
+        m_searchPopup->saveRecentSearches(name, m_recentSearches);
+    }
+
+    m_searchPopup->show(absoluteBoundingBoxRect(), document()->view(), -1);
+}
+
+void RenderTextControl::hidePopup()
+{
+    if (m_searchPopup)
+        m_searchPopup->hide();
+    m_searchPopupIsVisible = false;
+}
+
+void RenderTextControl::valueChanged(unsigned listIndex, bool fireEvents)
+{
+    ASSERT(static_cast<int>(listIndex) < listSize());
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+    if (static_cast<int>(listIndex) == (listSize() - 1)) {
+        if (fireEvents) {
+            m_recentSearches.clear();
+            const AtomicString& name = autosaveName();
+            if (!name.isEmpty()) {
+                if (!m_searchPopup)
+                    m_searchPopup = SearchPopupMenu::create(this);
+                m_searchPopup->saveRecentSearches(name, m_recentSearches);
+            }
+        }
+    } else {
+        input->setValue(itemText(listIndex));
+        if (fireEvents)
+            input->onSearch();
+        input->select();
+    }
+}
+
+String RenderTextControl::itemText(unsigned listIndex) const
+{
+    int size = listSize();
+    if (size == 1) {
+        ASSERT(!listIndex);
+        return searchMenuNoRecentSearchesText();
+    }
+    if (!listIndex)
+        return searchMenuRecentSearchesText();
+    if (itemIsSeparator(listIndex))
+        return String();
+    if (static_cast<int>(listIndex) == (size - 1))
+        return searchMenuClearRecentSearchesText();
+    return m_recentSearches[listIndex - 1];
+}
+
+bool RenderTextControl::itemIsEnabled(unsigned listIndex) const
+{
+     if (!listIndex || itemIsSeparator(listIndex))
+        return false;
+    return true;
+}
+
+PopupMenuStyle RenderTextControl::itemStyle(unsigned listIndex) const
+{
+    return menuStyle();
+}
+
+PopupMenuStyle RenderTextControl::menuStyle() const
+{
+    return PopupMenuStyle(style()->color(), style()->backgroundColor(), style()->font(), style()->visibility() == VISIBLE);
+}
+
+HostWindow* RenderTextControl::hostWindow() const
+{
+    return document()->view()->hostWindow();
+}
+
+PassRefPtr<Scrollbar> RenderTextControl::createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
+{
+    RefPtr<Scrollbar> widget;
+    bool hasCustomScrollbarStyle = style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
+    if (hasCustomScrollbarStyle)
+        widget = RenderScrollbar::createCustomScrollbar(client, orientation, this);
+    else
+        widget = Scrollbar::createNativeScrollbar(client, orientation, controlSize);
+    return widget.release();
+}
+
+int RenderTextControl::clientInsetLeft() const
+{
+    // Inset the menu by the radius of the cap on the left so that
+    // it only runs along the straight part of the bezel.
+    return height() / 2;
+}
+
+int RenderTextControl::clientInsetRight() const
+{
+    // Inset the menu by the radius of the cap on the right so that
+    // it only runs along the straight part of the bezel (unless it needs
+    // to be wider).
+    return height() / 2;
+}
+
+int RenderTextControl::clientPaddingLeft() const
+{
+    int padding = paddingLeft();
+    if (m_resultsButton->renderer())
+        padding += m_resultsButton->renderer()->width(); 
+    return padding;
+}
+
+int RenderTextControl::clientPaddingRight() const
+{
+    int padding = paddingRight();
+    if (m_cancelButton->renderer())
+        padding += m_cancelButton->renderer()->width(); 
+    return padding;
+}
+
+int RenderTextControl::listSize() const
+{
+    // If there are no recent searches, then our menu will have 1 "No recent searches" item.
+    if (!m_recentSearches.size())
+        return 1;
+    // Otherwise, leave room in the menu for a header, a separator, and the "Clear recent searches" item.
+    return m_recentSearches.size() + 3;
+}
+
+int RenderTextControl::selectedIndex() const
+{
+    return -1;
+}
+
+bool RenderTextControl::itemIsSeparator(unsigned listIndex) const
+{
+   // The separator will be the second to last item in our list.
+   return static_cast<int>(listIndex) == (listSize() - 2);
+}
+
+bool RenderTextControl::itemIsLabel(unsigned listIndex) const
+{
+    return listIndex == 0;
+}
+
+bool RenderTextControl::itemIsSelected(unsigned listIndex) const
+{
+    return false;
+}
+
+void RenderTextControl::setTextFromItem(unsigned listIndex)
+{
+    static_cast<HTMLInputElement*>(node())->setValue(itemText(listIndex));
+}
+
+bool RenderTextControl::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
+{
+    RenderLayer* layer = m_innerText->renderer()->layer();
+    if (layer && layer->scroll(direction, granularity, multiplier))
+        return true;
+    return RenderObject::scroll(direction, granularity, multiplier);
+}
+
+void RenderTextControl::searchEventTimerFired(Timer<RenderTextControl>*)
+{
+    static_cast<HTMLInputElement*>(node())->onSearch();
+}
+
+void RenderTextControl::stopSearchEventTimer()
+{
+    m_searchEventTimer.stop();
+}
+
+void RenderTextControl::startSearchEventTimer()
+{
+    unsigned length = text().length();
+
+    // If there's no text, fire the event right away.
+    if (!length) {
+        m_searchEventTimer.stop();
+        static_cast<HTMLInputElement*>(node())->onSearch();
+        return;
+    }
+
+    // After typing the first key, we wait 0.5 seconds.
+    // After the second key, 0.4 seconds, then 0.3, then 0.2 from then on.
+    m_searchEventTimer.startOneShot(max(0.2, 0.6 - 0.1 * length));
+}
+
+bool RenderTextControl::isScrollable() const
+{
+    if (m_innerText && m_innerText->renderer()->isScrollable())
+        return true;
+    return RenderObject::isScrollable();
+}
+
+FontSelector* RenderTextControl::fontSelector() const
+{
+    return document()->styleSelector()->fontSelector();
+}
+
+void RenderTextControl::updatePlaceholderVisibility()
+{
+    RenderStyle* parentStyle = m_innerBlock ? m_innerBlock->renderer()->style() : style();
+    RefPtr<RenderStyle> textBlockStyle = createInnerTextStyle(parentStyle);
+    m_innerText->renderer()->setStyle(textBlockStyle);
+    for (Node* n = m_innerText->firstChild(); n; n = n->traverseNextNode(m_innerText.get())) {
+        if (n->renderer())
+            n->renderer()->setStyle(textBlockStyle);
+    }
+    updateFromElement();
+}
+
+void RenderTextControl::capsLockStateMayHaveChanged()
+{
+    // Only draw the caps lock indicator if these things are true:
+    // 1) The field is a password field
+    // 2) The frame is active
+    // 3) The element is focused
+    // 4) The caps lock is on
+
+    bool shouldDrawCapsLockIndicator = false;
+    if (Node* n = node())
+        if (Document* d = document())
+            if (Frame* f = d->frame())
+                shouldDrawCapsLockIndicator = !m_multiLine && static_cast<HTMLInputElement*>(n)->inputType() == HTMLInputElement::PASSWORD && 
+                                               f->selection()->isFocusedAndActive() && d->focusedNode() == n && PlatformKeyboardEvent::currentCapsLockState();
+
+    if (shouldDrawCapsLockIndicator != m_shouldDrawCapsLockIndicator) {
+        m_shouldDrawCapsLockIndicator = shouldDrawCapsLockIndicator;
+        repaint();
+    }
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderTextControl.h b/WebCore/rendering/RenderTextControl.h
new file mode 100644
index 0000000..74fdd26
--- /dev/null
+++ b/WebCore/rendering/RenderTextControl.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.s
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderTextControl_h
+#define RenderTextControl_h
+
+#include "PopupMenuClient.h"
+#include "RenderBlock.h"
+#include "Timer.h"
+
+namespace WebCore {
+
+class FontSelector;
+class SearchFieldCancelButtonElement;
+class SearchFieldResultsButtonElement;
+class SearchPopupMenu;
+class Selection;
+class TextControlInnerElement;
+class TextControlInnerTextElement;
+
+class RenderTextControl : public RenderBlock, private PopupMenuClient {
+public:
+    RenderTextControl(Node*, bool multiLine);
+    virtual ~RenderTextControl();
+
+    virtual const char* renderName() const { return "RenderTextControl"; }
+
+    virtual bool hasControlClip() const { return m_cancelButton; }
+    virtual IntRect controlClipRect(int tx, int ty) const;
+    virtual void calcHeight();
+    virtual void calcPrefWidths();
+    virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
+    virtual void updateFromElement();
+    virtual bool canHaveChildren() const { return false; }
+    virtual int baselinePosition(bool firstLine, bool isRootLineBox) const;
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+    virtual void layout();
+    virtual bool avoidsFloats() const { return true; }
+    virtual void paint(PaintInfo&, int tx, int ty);
+    
+    virtual bool isEdited() const { return m_dirty; }
+    virtual void setEdited(bool isEdited) { m_dirty = isEdited; }
+    virtual bool isTextField() const { return !m_multiLine; }
+    virtual bool isTextArea() const { return m_multiLine; }
+    
+    bool isUserEdited() const { return m_userEdited; }
+    void setUserEdited(bool isUserEdited);
+
+    int selectionStart();
+    int selectionEnd();
+    void setSelectionStart(int);
+    void setSelectionEnd(int);
+    void select();
+    void setSelectionRange(int start, int end);
+    Selection selection(int start, int end) const;
+
+    void subtreeHasChanged();
+    String text();
+    String textWithHardLineBreaks();
+    void forwardEvent(Event*);
+    void selectionChanged(bool userTriggered);
+
+    virtual bool canBeProgramaticallyScrolled(bool) const { return true; }
+    virtual void autoscroll();
+
+    // Subclassed to forward to our inner div.
+    virtual int scrollLeft() const;
+    virtual int scrollTop() const;
+    virtual int scrollWidth() const;
+    virtual int scrollHeight() const;
+    virtual void setScrollLeft(int);
+    virtual void setScrollTop(int);
+    virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f);
+    virtual bool isScrollable() const;
+
+    VisiblePosition visiblePositionForIndex(int index);
+    int indexForVisiblePosition(const VisiblePosition&);
+
+    void addSearchResult();
+
+    bool popupIsVisible() const { return m_searchPopupIsVisible; }
+    void showPopup();
+    void hidePopup();
+
+    void stopSearchEventTimer();
+    
+    bool placeholderIsVisible() const { return m_placeholderVisible; }
+    void updatePlaceholderVisibility();
+
+    virtual void capsLockStateMayHaveChanged();
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+private:
+    // PopupMenuClient methods
+    virtual void valueChanged(unsigned listIndex, bool fireEvents = true);
+    virtual String itemText(unsigned listIndex) const;
+    virtual bool itemIsEnabled(unsigned listIndex) const;
+    virtual PopupMenuStyle itemStyle(unsigned listIndex) const;
+    virtual PopupMenuStyle menuStyle() const;
+    virtual int clientInsetLeft() const;
+    virtual int clientInsetRight() const;
+    virtual int clientPaddingLeft() const;
+    virtual int clientPaddingRight() const;
+    virtual int listSize() const;
+    virtual int selectedIndex() const;
+    virtual bool itemIsSeparator(unsigned listIndex) const;
+    virtual bool itemIsLabel(unsigned listIndex) const;
+    virtual bool itemIsSelected(unsigned listIndex) const;
+    virtual void setTextFromItem(unsigned listIndex);
+    virtual bool shouldPopOver() const { return false; }
+    virtual bool valueShouldChangeOnHotTrack() const { return false; }
+    virtual FontSelector* fontSelector() const;
+    virtual HostWindow* hostWindow() const;
+    virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
+
+    PassRefPtr<RenderStyle> createInnerBlockStyle(const RenderStyle* startStyle);
+    PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle);
+    PassRefPtr<RenderStyle> createCancelButtonStyle(const RenderStyle* startStyle);
+    PassRefPtr<RenderStyle> createResultsButtonStyle(const RenderStyle* startStyle);
+
+    void createSubtreeIfNeeded();
+    void updateCancelButtonVisibility(RenderStyle*);
+    const AtomicString& autosaveName() const;
+    void startSearchEventTimer();
+    void searchEventTimerFired(Timer<RenderTextControl>*);
+    String finishText(Vector<UChar>&) const;
+
+    friend class TextIterator;
+    HTMLElement* innerTextElement() const;
+
+    RefPtr<TextControlInnerElement> m_innerBlock;
+    RefPtr<TextControlInnerTextElement> m_innerText;
+    RefPtr<SearchFieldResultsButtonElement> m_resultsButton;
+    RefPtr<SearchFieldCancelButtonElement> m_cancelButton;
+
+    bool m_dirty;
+    bool m_multiLine;
+    bool m_placeholderVisible;
+    bool m_userEdited;
+    bool m_shouldDrawCapsLockIndicator;
+    
+    RefPtr<SearchPopupMenu> m_searchPopup;
+    bool m_searchPopupIsVisible;
+    mutable Vector<String> m_recentSearches;
+
+    Timer<RenderTextControl> m_searchEventTimer;
+};
+
+} // namespace WebCore
+
+#endif // RenderTextControl_h
diff --git a/WebCore/rendering/RenderTextFragment.cpp b/WebCore/rendering/RenderTextFragment.cpp
new file mode 100644
index 0000000..c8beba0
--- /dev/null
+++ b/WebCore/rendering/RenderTextFragment.cpp
@@ -0,0 +1,87 @@
+/*
+ * (C) 1999 Lars Knoll ([email protected])
+ * (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderTextFragment.h"
+
+#include "Text.h"
+
+namespace WebCore {
+
+RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str, int startOffset, int length)
+    : RenderText(node, str ? str->substring(startOffset, length) : 0)
+    , m_start(startOffset)
+    , m_end(length)
+    , m_firstLetter(0)
+{
+}
+
+RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str)
+    : RenderText(node, str)
+    , m_start(0)
+    , m_end(str ? str->length() : 0)
+    , m_contentString(str)
+    , m_firstLetter(0)
+{
+}
+
+PassRefPtr<StringImpl> RenderTextFragment::originalText() const
+{
+    Node* e = element();
+    RefPtr<StringImpl> result = (e ? static_cast<Text*>(e)->string() : contentString());
+    if (result && (start() > 0 || start() < result->length()))
+        result = result->substring(start(), end());
+    return result.release();
+}
+
+void RenderTextFragment::destroy()
+{
+    if (m_firstLetter)
+        m_firstLetter->destroy();
+    RenderText::destroy();
+}
+
+void RenderTextFragment::setTextInternal(PassRefPtr<StringImpl> text)
+{
+    RenderText::setTextInternal(text);
+    if (m_firstLetter) {
+        ASSERT(!m_contentString);
+        m_firstLetter->destroy();
+        m_firstLetter = 0;
+        m_start = 0;
+        m_end = textLength();
+    }
+}
+
+UChar RenderTextFragment::previousCharacter()
+{
+    if (start()) {
+        Node* e = element();
+        StringImpl*  original = (e ? static_cast<Text*>(e)->string() : contentString());
+        if (original)
+            return (*original)[start() - 1];
+    }
+
+    return RenderText::previousCharacter();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderTextFragment.h b/WebCore/rendering/RenderTextFragment.h
new file mode 100644
index 0000000..1fa509a
--- /dev/null
+++ b/WebCore/rendering/RenderTextFragment.h
@@ -0,0 +1,64 @@
+/*
+ * (C) 1999 Lars Knoll ([email protected])
+ * (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderTextFragment_h
+#define RenderTextFragment_h
+
+#include "RenderText.h"
+
+namespace WebCore {
+
+// Used to represent a text substring of an element, e.g., for text runs that are split because of
+// first letter and that must therefore have different styles (and positions in the render tree).
+// We cache offsets so that text transformations can be applied in such a way that we can recover
+// the original unaltered string from our corresponding DOM node.
+class RenderTextFragment : public RenderText {
+public:
+    RenderTextFragment(Node*, StringImpl*, int startOffset, int length);
+    RenderTextFragment(Node*, StringImpl*);
+
+    virtual bool isTextFragment() const { return true; }
+
+    virtual void destroy();
+
+    unsigned start() const { return m_start; }
+    unsigned end() const { return m_end; }
+
+    RenderObject* firstLetter() const { return m_firstLetter; }
+    void setFirstLetter(RenderObject* firstLetter) { m_firstLetter = firstLetter; }
+
+    StringImpl* contentString() const { return m_contentString.get(); }
+    virtual PassRefPtr<StringImpl> originalText() const;
+
+private:
+    virtual void setTextInternal(PassRefPtr<StringImpl>);
+    virtual UChar previousCharacter();
+
+    unsigned m_start;
+    unsigned m_end;
+    RefPtr<StringImpl> m_contentString;
+    RenderObject* m_firstLetter;
+};
+
+} // namespace WebCore
+
+#endif // RenderTextFragment_h
diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp
new file mode 100644
index 0000000..9eb3ac2
--- /dev/null
+++ b/WebCore/rendering/RenderTheme.cpp
@@ -0,0 +1,771 @@
+/**
+ * This file is part of the theme implementation for form controls in WebCore.
+ *
+ * Copyright (C) 2005, 2006, 2007, 2008 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RenderTheme.h"
+
+#include "CSSValueKeywords.h"
+#include "Document.h"
+#include "FocusController.h"
+#include "FontSelector.h"
+#include "Frame.h"
+#include "GraphicsContext.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "Page.h"
+#include "RenderStyle.h"
+#include "RenderView.h"
+#include "SelectionController.h"
+#include "Settings.h"
+
+// The methods in this file are shared by all themes on every platform.
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderTheme::RenderTheme()
+#if USE(NEW_THEME)
+    : m_theme(platformTheme())
+#endif
+{
+}
+
+void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e,
+                              bool UAHasAppearance, const BorderData& border, const FillLayer& background, const Color& backgroundColor)
+{
+    // Force inline and table display styles to be inline-block (except for table- which is block)
+    ControlPart part = style->appearance();
+    if (style->display() == INLINE || style->display() == INLINE_TABLE || style->display() == TABLE_ROW_GROUP ||
+        style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_FOOTER_GROUP ||
+        style->display() == TABLE_ROW || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_COLUMN ||
+        style->display() == TABLE_CELL || style->display() == TABLE_CAPTION)
+        style->setDisplay(INLINE_BLOCK);
+    else if (style->display() == COMPACT || style->display() == RUN_IN || style->display() == LIST_ITEM || style->display() == TABLE)
+        style->setDisplay(BLOCK);
+
+    if (UAHasAppearance && theme()->isControlStyled(style, border, background, backgroundColor)) {
+        if (part == MenulistPart) {
+            style->setAppearance(MenulistButtonPart);
+            part = MenulistButtonPart;
+        } else
+            style->setAppearance(NoControlPart);
+    }
+
+    if (!style->hasAppearance())
+        return;
+
+    // Never support box-shadow on native controls.
+    style->setBoxShadow(0);
+    
+#if USE(NEW_THEME)
+    switch (part) {
+        case CheckboxPart:
+        case RadioPart:
+        case PushButtonPart:
+        case SquareButtonPart:
+        case DefaultButtonPart:
+        case ButtonPart: {
+            // Border
+            LengthBox borderBox(style->borderTopWidth(), style->borderRightWidth(), style->borderBottomWidth(), style->borderLeftWidth());
+            borderBox = m_theme->controlBorder(part, style->font(), borderBox, style->effectiveZoom());
+            if (borderBox.top().value() != style->borderTopWidth()) {
+                if (borderBox.top().value())
+                    style->setBorderTopWidth(borderBox.top().value());
+                else
+                    style->resetBorderTop();
+            }
+            if (borderBox.right().value() != style->borderRightWidth()) {
+                if (borderBox.right().value())
+                    style->setBorderRightWidth(borderBox.right().value());
+                else
+                    style->resetBorderRight();
+            }
+            if (borderBox.bottom().value() != style->borderBottomWidth()) {
+                style->setBorderBottomWidth(borderBox.bottom().value());
+                if (borderBox.bottom().value())
+                    style->setBorderBottomWidth(borderBox.bottom().value());
+                else
+                    style->resetBorderBottom();
+            }
+            if (borderBox.left().value() != style->borderLeftWidth()) {
+                style->setBorderLeftWidth(borderBox.left().value());
+                if (borderBox.left().value())
+                    style->setBorderLeftWidth(borderBox.left().value());
+                else
+                    style->resetBorderLeft();
+            }
+
+            // Padding
+            LengthBox paddingBox = m_theme->controlPadding(part, style->font(), style->paddingBox(), style->effectiveZoom());
+            if (paddingBox != style->paddingBox())
+                style->setPaddingBox(paddingBox);
+
+            // Whitespace
+            if (m_theme->controlRequiresPreWhiteSpace(part))
+                style->setWhiteSpace(PRE);
+            
+            // Width / Height
+            // The width and height here are affected by the zoom.
+            // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
+            LengthSize controlSize = m_theme->controlSize(part, style->font(), LengthSize(style->width(), style->height()), style->effectiveZoom());
+            if (controlSize.width() != style->width())
+                style->setWidth(controlSize.width());
+            if (controlSize.height() != style->height())
+                style->setHeight(controlSize.height());
+                
+            // Min-Width / Min-Height
+            LengthSize minControlSize = m_theme->minimumControlSize(part, style->font(), style->effectiveZoom());
+            if (minControlSize.width() != style->minWidth())
+                style->setMinWidth(minControlSize.width());
+            if (minControlSize.height() != style->minHeight())
+                style->setMinHeight(minControlSize.height());
+                
+            // Font
+            FontDescription controlFont = m_theme->controlFont(part, style->font(), style->effectiveZoom());
+            if (controlFont != style->font().fontDescription()) {
+                // Reset our line-height
+                style->setLineHeight(RenderStyle::initialLineHeight());
+                
+                // Now update our font.
+                if (style->setFontDescription(controlFont))
+                    style->font().update(0);
+            }
+        }
+        default:
+            break;
+    }
+#endif
+
+    // Call the appropriate style adjustment method based off the appearance value.
+    switch (style->appearance()) {
+#if !USE(NEW_THEME)
+        case CheckboxPart:
+            return adjustCheckboxStyle(selector, style, e);
+        case RadioPart:
+            return adjustRadioStyle(selector, style, e);
+        case PushButtonPart:
+        case SquareButtonPart:
+        case DefaultButtonPart:
+        case ButtonPart:
+            return adjustButtonStyle(selector, style, e);
+#endif
+        case TextFieldPart:
+            return adjustTextFieldStyle(selector, style, e);
+        case TextAreaPart:
+            return adjustTextAreaStyle(selector, style, e);
+#ifdef ANDROID_LISTBOX_USES_MENU_LIST
+        case ListboxPart:
+            return adjustListboxStyle(selector, style, e);
+#endif
+        case MenulistPart:
+            return adjustMenuListStyle(selector, style, e);
+        case MenulistButtonPart:
+            return adjustMenuListButtonStyle(selector, style, e);
+        case MediaSliderPart:
+        case SliderHorizontalPart:
+        case SliderVerticalPart:
+            return adjustSliderTrackStyle(selector, style, e);
+        case SliderThumbHorizontalPart:
+        case SliderThumbVerticalPart:
+            return adjustSliderThumbStyle(selector, style, e);
+        case SearchFieldPart:
+            return adjustSearchFieldStyle(selector, style, e);
+        case SearchFieldCancelButtonPart:
+            return adjustSearchFieldCancelButtonStyle(selector, style, e);
+        case SearchFieldDecorationPart:
+            return adjustSearchFieldDecorationStyle(selector, style, e);
+        case SearchFieldResultsDecorationPart:
+            return adjustSearchFieldResultsDecorationStyle(selector, style, e);
+        case SearchFieldResultsButtonPart:
+            return adjustSearchFieldResultsButtonStyle(selector, style, e);
+        default:
+            break;
+    }
+}
+
+#if !PLATFORM(QT)
+void RenderTheme::adjustDefaultStyleSheet(CSSStyleSheet*)
+{
+}
+#endif
+
+bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    // If painting is disabled, but we aren't updating control tints, then just bail.
+    // If we are updating control tints, just schedule a repaint if the theme supports tinting
+    // for that control.
+    if (paintInfo.context->updatingControlTints()) {
+        if (controlSupportsTints(o))
+            o->repaint();
+        return false;
+    }
+    if (paintInfo.context->paintingDisabled())
+        return false;
+
+    ControlPart part = o->style()->appearance();
+
+#if USE(NEW_THEME)
+    switch (part) {
+        case CheckboxPart:
+        case RadioPart:
+        case PushButtonPart:
+        case SquareButtonPart:
+        case DefaultButtonPart:
+        case ButtonPart:
+            m_theme->paint(part, controlStatesForRenderer(o), const_cast<GraphicsContext*>(paintInfo.context), r, o->style()->effectiveZoom(), o->view()->frameView());
+            return false;
+        default:
+            break;
+    }
+#endif
+
+    // Call the appropriate paint method based off the appearance value.
+    switch (part) {
+#if !USE(NEW_THEME)
+        case CheckboxPart:
+            return paintCheckbox(o, paintInfo, r);
+        case RadioPart:
+            return paintRadio(o, paintInfo, r);
+        case PushButtonPart:
+        case SquareButtonPart:
+        case DefaultButtonPart:
+        case ButtonPart:
+            return paintButton(o, paintInfo, r);
+#endif
+        case MenulistPart:
+            return paintMenuList(o, paintInfo, r);
+        case SliderHorizontalPart:
+        case SliderVerticalPart:
+            return paintSliderTrack(o, paintInfo, r);
+        case SliderThumbHorizontalPart:
+        case SliderThumbVerticalPart:
+            if (o->parent()->isSlider())
+                return paintSliderThumb(o, paintInfo, r);
+            // We don't support drawing a slider thumb without a parent slider
+            break;
+        case MediaFullscreenButtonPart:
+            return paintMediaFullscreenButton(o, paintInfo, r);
+        case MediaPlayButtonPart:
+            return paintMediaPlayButton(o, paintInfo, r);
+        case MediaMuteButtonPart:
+            return paintMediaMuteButton(o, paintInfo, r);
+        case MediaSeekBackButtonPart:
+            return paintMediaSeekBackButton(o, paintInfo, r);
+        case MediaSeekForwardButtonPart:
+            return paintMediaSeekForwardButton(o, paintInfo, r);
+        case MediaSliderPart:
+            return paintMediaSliderTrack(o, paintInfo, r);
+        case MediaSliderThumbPart:
+            if (o->parent()->isSlider())
+                return paintMediaSliderThumb(o, paintInfo, r);
+            break;
+        case MenulistButtonPart:
+        case TextFieldPart:
+        case TextAreaPart:
+        case ListboxPart:
+            return true;
+        case SearchFieldPart:
+            return paintSearchField(o, paintInfo, r);
+        case SearchFieldCancelButtonPart:
+            return paintSearchFieldCancelButton(o, paintInfo, r);
+        case SearchFieldDecorationPart:
+            return paintSearchFieldDecoration(o, paintInfo, r);
+        case SearchFieldResultsDecorationPart:
+            return paintSearchFieldResultsDecoration(o, paintInfo, r);
+        case SearchFieldResultsButtonPart:
+            return paintSearchFieldResultsButton(o, paintInfo, r);
+        default:
+            break;
+    }
+
+    return true; // We don't support the appearance, so let the normal background/border paint.
+}
+
+bool RenderTheme::paintBorderOnly(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    if (paintInfo.context->paintingDisabled())
+        return false;
+
+    // Call the appropriate paint method based off the appearance value.
+    switch (o->style()->appearance()) {
+        case TextFieldPart:
+            return paintTextField(o, paintInfo, r);
+        case ListboxPart:
+        case TextAreaPart:
+            return paintTextArea(o, paintInfo, r);
+        case MenulistButtonPart:
+            return true;
+        case CheckboxPart:
+        case RadioPart:
+        case PushButtonPart:
+        case SquareButtonPart:
+        case DefaultButtonPart:
+        case ButtonPart:
+        case MenulistPart:
+        case SliderHorizontalPart:
+        case SliderVerticalPart:
+        case SliderThumbHorizontalPart:
+        case SliderThumbVerticalPart:
+        case SearchFieldPart:
+        case SearchFieldCancelButtonPart:
+        case SearchFieldDecorationPart:
+        case SearchFieldResultsDecorationPart:
+        case SearchFieldResultsButtonPart:
+        default:
+            break;
+    }
+
+    return false;
+}
+
+bool RenderTheme::paintDecorations(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    if (paintInfo.context->paintingDisabled())
+        return false;
+
+    // Call the appropriate paint method based off the appearance value.
+    switch (o->style()->appearance()) {
+        case MenulistButtonPart:
+            return paintMenuListButton(o, paintInfo, r);
+        case TextFieldPart:
+        case TextAreaPart:
+        case ListboxPart:
+        case CheckboxPart:
+        case RadioPart:
+        case PushButtonPart:
+        case SquareButtonPart:
+        case DefaultButtonPart:
+        case ButtonPart:
+        case MenulistPart:
+        case SliderHorizontalPart:
+        case SliderVerticalPart:
+        case SliderThumbHorizontalPart:
+        case SliderThumbVerticalPart:
+        case SearchFieldPart:
+        case SearchFieldCancelButtonPart:
+        case SearchFieldDecorationPart:
+        case SearchFieldResultsDecorationPart:
+        case SearchFieldResultsButtonPart:
+        default:
+            break;
+    }
+
+    return false;
+}
+
+Color RenderTheme::activeSelectionBackgroundColor() const
+{
+    if (!m_activeSelectionColor.isValid())
+        m_activeSelectionColor = platformActiveSelectionBackgroundColor().blendWithWhite();
+    return m_activeSelectionColor;
+}
+
+Color RenderTheme::inactiveSelectionBackgroundColor() const
+{
+    if (!m_inactiveSelectionColor.isValid())
+        m_inactiveSelectionColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
+    return m_inactiveSelectionColor;
+}
+
+Color RenderTheme::platformActiveSelectionBackgroundColor() const
+{
+    // Use a blue color by default if the platform theme doesn't define anything.
+    return Color(0, 0, 255);
+}
+
+Color RenderTheme::platformInactiveSelectionBackgroundColor() const
+{
+    // Use a grey color by default if the platform theme doesn't define anything.
+    return Color(128, 128, 128);
+}
+
+Color RenderTheme::platformActiveSelectionForegroundColor() const
+{
+    return Color();
+}
+
+Color RenderTheme::platformInactiveSelectionForegroundColor() const
+{
+    return Color();
+}
+
+Color RenderTheme::activeListBoxSelectionBackgroundColor() const
+{
+    return activeSelectionBackgroundColor();
+}
+
+Color RenderTheme::activeListBoxSelectionForegroundColor() const
+{
+    // Use a white color by default if the platform theme doesn't define anything.
+    return Color(255, 255, 255);
+}
+
+Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
+{
+    return inactiveSelectionBackgroundColor();
+}
+
+Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
+{
+    // Use a black color by default if the platform theme doesn't define anything.
+    return Color(0, 0, 0);
+}
+
+int RenderTheme::baselinePosition(const RenderObject* o) const
+{
+#if USE(NEW_THEME)
+    return o->height() + o->marginTop() + m_theme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom();
+#else
+    return o->height() + o->marginTop();
+#endif
+}
+
+bool RenderTheme::isControlContainer(ControlPart appearance) const
+{
+    // There are more leaves than this, but we'll patch this function as we add support for
+    // more controls.
+    return appearance != CheckboxPart && appearance != RadioPart;
+}
+
+bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& background,
+                                  const Color& backgroundColor) const
+{
+    switch (style->appearance()) {
+        case PushButtonPart:
+        case SquareButtonPart:
+        case DefaultButtonPart:
+        case ButtonPart:
+        case ListboxPart:
+        case MenulistPart:
+        // FIXME: Uncomment this when making search fields style-able.
+        // case SearchFieldPart:
+        case TextFieldPart:
+        case TextAreaPart:
+            // Test the style to see if the UA border and background match.
+            return (style->border() != border ||
+                    *style->backgroundLayers() != background ||
+                    style->backgroundColor() != backgroundColor);
+        default:
+            return false;
+    }
+}
+
+void RenderTheme::adjustRepaintRect(const RenderObject* o, IntRect& r)
+{
+#if USE(NEW_THEME)
+    m_theme->inflateControlPaintRect(o->style()->appearance(), controlStatesForRenderer(o), r, o->style()->effectiveZoom());
+#endif
+}
+
+bool RenderTheme::supportsFocusRing(const RenderStyle* style) const
+{
+    return (style->hasAppearance() && style->appearance() != TextFieldPart && style->appearance() != TextAreaPart && style->appearance() != MenulistButtonPart && style->appearance() != ListboxPart);
+}
+
+bool RenderTheme::stateChanged(RenderObject* o, ControlState state) const
+{
+    // Default implementation assumes the controls dont respond to changes in :hover state
+    if (state == HoverState && !supportsHover(o->style()))
+        return false;
+
+    // Assume pressed state is only responded to if the control is enabled.
+    if (state == PressedState && !isEnabled(o))
+        return false;
+
+    // Repaint the control.
+    o->repaint();
+    return true;
+}
+
+ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const
+{
+    ControlStates result = 0;
+    if (isHovered(o))
+        result |= HoverState;
+    if (isPressed(o))
+        result |= PressedState;
+    if (isFocused(o) && o->style()->outlineStyleIsAuto())
+        result |= FocusState;
+    if (isEnabled(o))
+        result |= EnabledState;
+    if (isChecked(o))
+        result |= CheckedState;
+    if (isReadOnlyControl(o))
+        result |= ReadOnlyState;
+    if (isDefault(o))
+        result |= DefaultState;
+    if (!isActive(o))
+        result |= WindowInactiveState;
+    if (isIndeterminate(o))
+        result |= IndeterminateState;
+    return result;
+}
+
+bool RenderTheme::isActive(const RenderObject* o) const
+{
+    Node* node = o->element();
+    if (!node)
+        return false;
+
+    Frame* frame = node->document()->frame();
+    if (!frame)
+        return false;
+
+    Page* page = frame->page();
+    if (!page)
+        return false;
+
+    return page->focusController()->isActive();
+}
+
+bool RenderTheme::isChecked(const RenderObject* o) const
+{
+    if (!o->element())
+        return false;
+    return o->element()->isChecked();
+}
+
+bool RenderTheme::isIndeterminate(const RenderObject* o) const
+{
+    if (!o->element())
+        return false;
+    return o->element()->isIndeterminate();
+}
+
+bool RenderTheme::isEnabled(const RenderObject* o) const
+{
+    if (!o->element())
+        return true;
+    return o->element()->isEnabled();
+}
+
+bool RenderTheme::isFocused(const RenderObject* o) const
+{
+    Node* node = o->element();
+    if (!node)
+        return false;
+    Document* document = node->document();
+    Frame* frame = document->frame();
+    return node == document->focusedNode() && frame && frame->selection()->isFocusedAndActive();
+}
+
+bool RenderTheme::isPressed(const RenderObject* o) const
+{
+    if (!o->element())
+        return false;
+    return o->element()->active();
+}
+
+bool RenderTheme::isReadOnlyControl(const RenderObject* o) const
+{
+    if (!o->element())
+        return false;
+    return o->element()->isReadOnlyControl();
+}
+
+bool RenderTheme::isHovered(const RenderObject* o) const
+{
+    if (!o->element())
+        return false;
+    return o->element()->hovered();
+}
+
+bool RenderTheme::isDefault(const RenderObject* o) const
+{
+    if (!o->document())
+        return false;
+
+    Settings* settings = o->document()->settings();
+    if (!settings || !settings->inApplicationChromeMode())
+        return false;
+    
+    return o->style()->appearance() == DefaultButtonPart;
+}
+
+#if !USE(NEW_THEME)
+void RenderTheme::adjustCheckboxStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    // A summary of the rules for checkbox designed to match WinIE:
+    // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
+    // font-size - not honored (control has no text), but we use it to decide which control size to use.
+    setCheckboxSize(style);
+
+    // padding - not honored by WinIE, needs to be removed.
+    style->resetPadding();
+
+    // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
+    // for now, we will not honor it.
+    style->resetBorder();
+
+    style->setBoxShadow(0);
+}
+
+void RenderTheme::adjustRadioStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    // A summary of the rules for checkbox designed to match WinIE:
+    // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
+    // font-size - not honored (control has no text), but we use it to decide which control size to use.
+    setRadioSize(style);
+
+    // padding - not honored by WinIE, needs to be removed.
+    style->resetPadding();
+
+    // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
+    // for now, we will not honor it.
+    style->resetBorder();
+
+    style->setBoxShadow(0);
+}
+
+void RenderTheme::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    // Most platforms will completely honor all CSS, and so we have no need to adjust the style
+    // at all by default.  We will still allow the theme a crack at setting up a desired vertical size.
+    setButtonSize(style);
+}
+#endif
+
+void RenderTheme::adjustTextFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
+void RenderTheme::adjustTextAreaStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
+void RenderTheme::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
+void RenderTheme::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
+void RenderTheme::adjustSliderTrackStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
+void RenderTheme::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
+void RenderTheme::adjustSliderThumbSize(RenderObject*) const
+{
+}
+
+void RenderTheme::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
+void RenderTheme::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
+void RenderTheme::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
+void RenderTheme::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
+void RenderTheme::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
+void RenderTheme::platformColorsDidChange()
+{
+    m_activeSelectionColor = Color();
+    m_inactiveSelectionColor = Color();
+}
+
+Color RenderTheme::systemColor(int cssValueId) const
+{
+    switch (cssValueId) {
+        case CSSValueActiveborder:
+            return 0xFFFFFFFF;
+        case CSSValueActivecaption:
+            return 0xFFCCCCCC;
+        case CSSValueAppworkspace:
+            return 0xFFFFFFFF;
+        case CSSValueBackground:
+            return 0xFF6363CE;
+        case CSSValueButtonface:
+            return 0xFFC0C0C0;
+        case CSSValueButtonhighlight:
+            return 0xFFDDDDDD;
+        case CSSValueButtonshadow:
+            return 0xFF888888;
+        case CSSValueButtontext:
+            return 0xFF000000;
+        case CSSValueCaptiontext:
+            return 0xFF000000;
+        case CSSValueGraytext:
+            return 0xFF808080;
+        case CSSValueHighlight:
+            return 0xFFB5D5FF;
+        case CSSValueHighlighttext:
+            return 0xFF000000;
+        case CSSValueInactiveborder:
+            return 0xFFFFFFFF;
+        case CSSValueInactivecaption:
+            return 0xFFFFFFFF;
+        case CSSValueInactivecaptiontext:
+            return 0xFF7F7F7F;
+        case CSSValueInfobackground:
+            return 0xFFFBFCC5;
+        case CSSValueInfotext:
+            return 0xFF000000;
+        case CSSValueMenu:
+            return 0xFFC0C0C0;
+        case CSSValueMenutext:
+            return 0xFF000000;
+        case CSSValueScrollbar:
+            return 0xFFFFFFFF;
+        case CSSValueText:
+            return 0xFF000000;
+        case CSSValueThreeddarkshadow:
+            return 0xFF666666;
+        case CSSValueThreedface:
+            return 0xFFC0C0C0;
+        case CSSValueThreedhighlight:
+            return 0xFFDDDDDD;
+        case CSSValueThreedlightshadow:
+            return 0xFFC0C0C0;
+        case CSSValueThreedshadow:
+            return 0xFF888888;
+        case CSSValueWindow:
+            return 0xFFFFFFFF;
+        case CSSValueWindowframe:
+            return 0xFFCCCCCC;
+        case CSSValueWindowtext:
+            return 0xFF000000;
+    }
+    return Color();
+}
+
+Color RenderTheme::platformTextSearchHighlightColor() const
+{
+    return Color(255, 255, 0);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h
new file mode 100644
index 0000000..2935d42
--- /dev/null
+++ b/WebCore/rendering/RenderTheme.h
@@ -0,0 +1,228 @@
+/*
+ * This file is part of the theme implementation for form controls in WebCore.
+ *
+ * Copyright (C) 2005, 2006, 2007, 2008 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderTheme_h
+#define RenderTheme_h
+
+#include "RenderObject.h"
+#if USE(NEW_THEME)
+#include "Theme.h"
+#else
+#include "ThemeTypes.h"
+#endif
+
+namespace WebCore {
+
+class Element;
+class PopupMenu;
+class RenderMenuList;
+class CSSStyleSheet;
+
+class RenderTheme {
+public:
+    RenderTheme();
+    virtual ~RenderTheme() { }
+
+    // This method is called whenever style has been computed for an element and the appearance
+    // property has been set to a value other than "none".  The theme should map in all of the appropriate
+    // metrics and defaults given the contents of the style.  This includes sophisticated operations like
+    // selection of control size based off the font, the disabling of appearance when certain other properties like
+    // "border" are set, or if the appearance is not supported by the theme.
+    void adjustStyle(CSSStyleSelector*, RenderStyle*, Element*,  bool UAHasAppearance,
+                     const BorderData&, const FillLayer&, const Color& backgroundColor);
+
+    // This method is called once, from CSSStyleSelector::loadDefaultStyle(), to let each platform adjust
+    // the default CSS rules in html4.css.
+    static void adjustDefaultStyleSheet(CSSStyleSheet*);
+
+    // This method is called to paint the widget as a background of the RenderObject.  A widget's foreground, e.g., the
+    // text of a button, is always rendered by the engine itself.  The boolean return value indicates
+    // whether the CSS border/background should also be painted.
+    bool paint(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    bool paintBorderOnly(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    bool paintDecorations(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    // The remaining methods should be implemented by the platform-specific portion of the theme, e.g.,
+    // RenderThemeMac.cpp for Mac OS X.
+
+    // A method to obtain the baseline position for a "leaf" control.  This will only be used if a baseline
+    // position cannot be determined by examining child content. Checkboxes and radio buttons are examples of
+    // controls that need to do this.
+    virtual int baselinePosition(const RenderObject*) const;
+
+    // A method for asking if a control is a container or not.  Leaf controls have to have some special behavior (like
+    // the baseline position API above).
+    bool isControlContainer(ControlPart) const;
+
+    // A method asking if the control changes its tint when the window has focus or not.
+    virtual bool controlSupportsTints(const RenderObject*) const { return false; }
+
+    // Whether or not the control has been styled enough by the author to disable the native appearance.
+    virtual bool isControlStyled(const RenderStyle*, const BorderData&, const FillLayer&, const Color& backgroundColor) const;
+
+    // A general method asking if any control tinting is supported at all.
+    virtual bool supportsControlTints() const { return false; }
+
+    // Some controls may spill out of their containers (e.g., the check on an OS X checkbox).  When these controls repaint,
+    // the theme needs to communicate this inflated rect to the engine so that it can invalidate the whole control.
+    virtual void adjustRepaintRect(const RenderObject*, IntRect&);
+
+    // This method is called whenever a relevant state changes on a particular themed object, e.g., the mouse becomes pressed
+    // or a control becomes disabled.
+    virtual bool stateChanged(RenderObject*, ControlState) const;
+
+    // This method is called whenever the theme changes on the system in order to flush cached resources from the
+    // old theme.
+    virtual void themeChanged() { }
+
+    // A method asking if the theme is able to draw the focus ring.
+    virtual bool supportsFocusRing(const RenderStyle*) const;
+
+    // A method asking if the theme's controls actually care about redrawing when hovered.
+    virtual bool supportsHover(const RenderStyle*) const { return false; }
+
+    // The selection color.
+    Color activeSelectionBackgroundColor() const;
+    Color inactiveSelectionBackgroundColor() const;
+
+    virtual Color platformTextSearchHighlightColor() const;
+
+    // The platform selection color.
+    virtual Color platformActiveSelectionBackgroundColor() const;
+    virtual Color platformInactiveSelectionBackgroundColor() const;
+    virtual Color platformActiveSelectionForegroundColor() const;
+    virtual Color platformInactiveSelectionForegroundColor() const;
+
+    // List Box selection color
+    virtual Color activeListBoxSelectionBackgroundColor() const;
+    virtual Color activeListBoxSelectionForegroundColor() const;
+    virtual Color inactiveListBoxSelectionBackgroundColor() const;
+    virtual Color inactiveListBoxSelectionForegroundColor() const;
+
+    virtual void platformColorsDidChange();
+
+    virtual double caretBlinkFrequency() const { return 0.5; }
+
+    // System fonts and colors for CSS.
+    virtual void systemFont(int cssValueId, FontDescription&) const = 0;
+    virtual Color systemColor(int cssValueId) const;
+
+    virtual int minimumMenuListSize(RenderStyle*) const { return 0; }
+
+    virtual void adjustSliderThumbSize(RenderObject*) const;
+
+    virtual int popupInternalPaddingLeft(RenderStyle*) const { return 0; }
+    virtual int popupInternalPaddingRight(RenderStyle*) const { return 0; }
+    virtual int popupInternalPaddingTop(RenderStyle*) const { return 0; }
+    virtual int popupInternalPaddingBottom(RenderStyle*) const { return 0; }
+    
+    // Method for painting the caps lock indicator
+    virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return 0; };
+
+protected:
+#if !USE(NEW_THEME)
+    // Methods for each appearance value.
+    virtual void adjustCheckboxStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintCheckbox(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+    virtual void setCheckboxSize(RenderStyle*) const { }
+
+    virtual void adjustRadioStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintRadio(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+    virtual void setRadioSize(RenderStyle*) const { }
+
+    virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+    virtual void setButtonSize(RenderStyle*) const { }
+#endif
+
+    virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+#ifdef ANDROID_LISTBOX_USES_MENU_LIST
+    virtual void adjustListboxStyle(CSSStyleSelector*, RenderStyle*, Element*) const {}
+#endif
+    virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+    virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaSeekBackButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+
+public:
+    // Methods for state querying
+    ControlStates controlStatesForRenderer(const RenderObject* o) const;
+    bool isActive(const RenderObject*) const;
+    bool isChecked(const RenderObject*) const;
+    bool isIndeterminate(const RenderObject*) const;
+    bool isEnabled(const RenderObject*) const;
+    bool isFocused(const RenderObject*) const;
+    bool isPressed(const RenderObject*) const;
+    bool isHovered(const RenderObject*) const;
+    bool isReadOnlyControl(const RenderObject*) const;
+    bool isDefault(const RenderObject*) const;
+
+private:
+    mutable Color m_activeSelectionColor;
+    mutable Color m_inactiveSelectionColor;
+#if USE(NEW_THEME)
+    Theme* m_theme; // The platform-specific theme.
+#endif
+};
+
+// Function to obtain the theme.  This is implemented in your platform-specific theme implementation to hand
+// back the appropriate platform theme.
+RenderTheme* theme();
+
+} // namespace WebCore
+
+#endif // RenderTheme_h
diff --git a/WebCore/rendering/RenderThemeMac.h b/WebCore/rendering/RenderThemeMac.h
new file mode 100644
index 0000000..1a49898
--- /dev/null
+++ b/WebCore/rendering/RenderThemeMac.h
@@ -0,0 +1,175 @@
+/*
+ * This file is part of the theme implementation for form controls in WebCore.
+ *
+ * Copyright (C) 2005 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderThemeMac_h
+#define RenderThemeMac_h
+
+#import "RenderTheme.h"
+#import <wtf/HashMap.h>
+#import <wtf/RetainPtr.h>
+
+#ifdef __OBJC__
+@class WebCoreRenderThemeNotificationObserver;
+#else
+class WebCoreRenderThemeNotificationObserver;
+#endif
+
+namespace WebCore {
+
+class RenderStyle;
+
+class RenderThemeMac : public RenderTheme {
+public:
+    RenderThemeMac();
+    virtual ~RenderThemeMac();
+
+    // A method asking if the control changes its tint when the window has focus or not.
+    virtual bool controlSupportsTints(const RenderObject*) const;
+
+    // A general method asking if any control tinting is supported at all.
+    virtual bool supportsControlTints() const { return true; }
+
+    virtual void adjustRepaintRect(const RenderObject*, IntRect&);
+
+    virtual bool isControlStyled(const RenderStyle*, const BorderData&,
+                                 const FillLayer&, const Color& backgroundColor) const;
+
+    virtual Color platformActiveSelectionBackgroundColor() const;
+    virtual Color platformInactiveSelectionBackgroundColor() const;
+    virtual Color activeListBoxSelectionBackgroundColor() const;
+    
+    virtual void platformColorsDidChange();
+
+    // System fonts.
+    virtual void systemFont(int cssValueId, FontDescription&) const;
+
+    virtual int minimumMenuListSize(RenderStyle*) const;
+
+    virtual void adjustSliderThumbSize(RenderObject*) const;
+    
+    virtual int popupInternalPaddingLeft(RenderStyle*) const;
+    virtual int popupInternalPaddingRight(RenderStyle*) const;
+    virtual int popupInternalPaddingTop(RenderStyle*) const;
+    virtual int popupInternalPaddingBottom(RenderStyle*) const;
+    
+    virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual Color systemColor(int cssValueId) const;
+
+protected:
+    virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSeekBackButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+private:
+    IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const;
+
+    // Get the control size based off the font.  Used by some of the controls (like buttons).
+    NSControlSize controlSizeForFont(RenderStyle*) const;
+    NSControlSize controlSizeForSystemFont(RenderStyle*) const;
+    void setControlSize(NSCell*, const IntSize* sizes, const IntSize& minSize, float zoomLevel = 1.0f);
+    void setSizeFromFont(RenderStyle*, const IntSize* sizes) const;
+    IntSize sizeForFont(RenderStyle*, const IntSize* sizes) const;
+    IntSize sizeForSystemFont(RenderStyle*, const IntSize* sizes) const;
+    void setFontFromControlSize(CSSStyleSelector*, RenderStyle*, NSControlSize) const;
+
+    void updateCheckedState(NSCell*, const RenderObject*);
+    void updateEnabledState(NSCell*, const RenderObject*);
+    void updateFocusedState(NSCell*, const RenderObject*);
+    void updatePressedState(NSCell*, const RenderObject*);
+
+    // Helpers for adjusting appearance and for painting
+
+    void setPopupButtonCellState(const RenderObject*, const IntRect&);
+    const IntSize* popupButtonSizes() const;
+    const int* popupButtonMargins() const;
+    const int* popupButtonPadding(NSControlSize) const;
+    void paintMenuListButtonGradients(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    const IntSize* menuListSizes() const;
+
+    const IntSize* searchFieldSizes() const;
+    const IntSize* cancelButtonSizes() const;
+    const IntSize* resultsButtonSizes() const;
+    void setSearchCellState(RenderObject*, const IntRect&);
+    void setSearchFieldSize(RenderStyle*) const;
+    
+    NSPopUpButtonCell* popupButton() const;
+    NSSearchFieldCell* search() const;
+    NSMenu* searchMenuTemplate() const;
+    NSSliderCell* sliderThumbHorizontal() const;
+    NSSliderCell* sliderThumbVertical() const;
+
+private:
+    mutable RetainPtr<NSPopUpButtonCell> m_popupButton;
+    mutable RetainPtr<NSSearchFieldCell> m_search;
+    mutable RetainPtr<NSMenu> m_searchMenuTemplate;
+    mutable RetainPtr<NSSliderCell> m_sliderThumbHorizontal;
+    mutable RetainPtr<NSSliderCell> m_sliderThumbVertical;
+
+    bool m_isSliderThumbHorizontalPressed;
+    bool m_isSliderThumbVerticalPressed;
+
+    mutable HashMap<int, RGBA32> m_systemColorCache;
+
+    RetainPtr<WebCoreRenderThemeNotificationObserver> m_notificationObserver;
+};
+
+} // namespace WebCore
+
+#endif // RenderThemeMac_h
diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm
new file mode 100644
index 0000000..699b74a
--- /dev/null
+++ b/WebCore/rendering/RenderThemeMac.mm
@@ -0,0 +1,1515 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#import "config.h"
+#import "RenderThemeMac.h"
+
+#import "BitmapImage.h"
+#import "CSSStyleSelector.h"
+#import "CSSValueKeywords.h"
+#import "Document.h"
+#import "Element.h"
+#import "FoundationExtras.h"
+#import "FrameView.h"
+#import "GraphicsContext.h"
+#import "HTMLInputElement.h"
+#import "HTMLMediaElement.h"
+#import "HTMLNames.h"
+#import "Image.h"
+#import "LocalCurrentGraphicsContext.h"
+#import "RenderSlider.h"
+#import "RenderView.h"
+#import "SharedBuffer.h"
+#import "WebCoreSystemInterface.h"
+#import <Carbon/Carbon.h>
+#import <Cocoa/Cocoa.h>
+#import <wtf/RetainPtr.h>
+#import <math.h>
+
+#ifdef BUILDING_ON_TIGER
+typedef int NSInteger;
+typedef unsigned NSUInteger;
+#endif
+
+using std::min;
+
+// The methods in this file are specific to the Mac OS X platform.
+
+// FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari. 
+
+@interface WebCoreRenderThemeNotificationObserver : NSObject
+{
+    WebCore::RenderTheme *_theme;
+}
+
+- (id)initWithTheme:(WebCore::RenderTheme *)theme;
+- (void)systemColorsDidChange:(NSNotification *)notification;
+
+@end
+
+@implementation WebCoreRenderThemeNotificationObserver
+
+- (id)initWithTheme:(WebCore::RenderTheme *)theme
+{
+    [super init];
+    _theme = theme;
+    
+    return self;
+}
+
+- (void)systemColorsDidChange:(NSNotification *)notification
+{
+    ASSERT([[notification name] isEqualToString:NSSystemColorsDidChangeNotification]);
+    _theme->platformColorsDidChange();
+}
+
+@end
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+enum {
+    topMargin,
+    rightMargin,
+    bottomMargin,
+    leftMargin
+};
+
+enum {
+    topPadding,
+    rightPadding,
+    bottomPadding,
+    leftPadding
+};
+
+RenderTheme* theme()
+{
+    static RenderThemeMac* macTheme = new RenderThemeMac;
+    return macTheme;
+}
+
+RenderThemeMac::RenderThemeMac()
+    : m_isSliderThumbHorizontalPressed(false)
+    , m_isSliderThumbVerticalPressed(false)
+    , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this])
+{
+    [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get()
+                                                        selector:@selector(systemColorsDidChange:)
+                                                            name:NSSystemColorsDidChangeNotification
+                                                          object:nil];
+}
+
+RenderThemeMac::~RenderThemeMac()
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
+}
+
+Color RenderThemeMac::platformActiveSelectionBackgroundColor() const
+{
+    NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+    return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
+}
+
+Color RenderThemeMac::platformInactiveSelectionBackgroundColor() const
+{
+    NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+    return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
+}
+
+Color RenderThemeMac::activeListBoxSelectionBackgroundColor() const
+{
+    NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+    return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
+}
+
+static FontWeight toFontWeight(NSInteger appKitFontWeight)
+{
+    ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
+    if (appKitFontWeight > 14)
+        appKitFontWeight = 14;
+    else if (appKitFontWeight < 1)
+        appKitFontWeight = 1;
+
+    static FontWeight fontWeights[] = {
+        FontWeight100,
+        FontWeight100,
+        FontWeight200,
+        FontWeight300,
+        FontWeight400,
+        FontWeight500,
+        FontWeight600,
+        FontWeight600,
+        FontWeight700,
+        FontWeight800,
+        FontWeight800,
+        FontWeight900,
+        FontWeight900,
+        FontWeight900
+    };
+    return fontWeights[appKitFontWeight - 1];
+}
+
+void RenderThemeMac::systemFont(int cssValueId, FontDescription& fontDescription) const
+{
+    static FontDescription systemFont;
+    static FontDescription smallSystemFont;
+    static FontDescription menuFont;
+    static FontDescription labelFont;
+    static FontDescription miniControlFont;
+    static FontDescription smallControlFont;
+    static FontDescription controlFont;
+
+    FontDescription* cachedDesc;
+    NSFont* font = nil;
+    switch (cssValueId) {
+        case CSSValueSmallCaption:
+            cachedDesc = &smallSystemFont;
+            if (!smallSystemFont.isAbsoluteSize())
+                font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
+            break;
+        case CSSValueMenu:
+            cachedDesc = &menuFont;
+            if (!menuFont.isAbsoluteSize())
+                font = [NSFont menuFontOfSize:[NSFont systemFontSize]];
+            break;
+        case CSSValueStatusBar:
+            cachedDesc = &labelFont;
+            if (!labelFont.isAbsoluteSize())
+                font = [NSFont labelFontOfSize:[NSFont labelFontSize]];
+            break;
+        case CSSValueWebkitMiniControl:
+            cachedDesc = &miniControlFont;
+            if (!miniControlFont.isAbsoluteSize())
+                font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
+            break;
+        case CSSValueWebkitSmallControl:
+            cachedDesc = &smallControlFont;
+            if (!smallControlFont.isAbsoluteSize())
+                font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
+            break;
+        case CSSValueWebkitControl:
+            cachedDesc = &controlFont;
+            if (!controlFont.isAbsoluteSize())
+                font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
+            break;
+        default:
+            cachedDesc = &systemFont;
+            if (!systemFont.isAbsoluteSize())
+                font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
+    }
+
+    if (font) {
+        NSFontManager *fontManager = [NSFontManager sharedFontManager];
+        cachedDesc->setIsAbsoluteSize(true);
+        cachedDesc->setGenericFamily(FontDescription::NoFamily);
+        cachedDesc->firstFamily().setFamily([font familyName]);
+        cachedDesc->setSpecifiedSize([font pointSize]);
+        cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font]));
+        cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask);
+    }
+    fontDescription = *cachedDesc;
+}
+
+static RGBA32 convertNSColorToColor(NSColor *color)
+{
+    NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+    if (colorInColorSpace) {
+        static const double scaleFactor = nextafter(256.0, 0.0);
+        return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
+            static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]),
+            static_cast<int>(scaleFactor * [colorInColorSpace blueComponent]));
+    }
+
+    // This conversion above can fail if the NSColor in question is an NSPatternColor 
+    // (as many system colors are). These colors are actually a repeating pattern
+    // not just a solid color. To work around this we simply draw a 1x1 image of
+    // the color and use that pixel's color. It might be better to use an average of
+    // the colors in the pattern instead.
+    NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
+                                                                             pixelsWide:1
+                                                                             pixelsHigh:1
+                                                                          bitsPerSample:8
+                                                                        samplesPerPixel:4
+                                                                               hasAlpha:YES
+                                                                               isPlanar:NO
+                                                                         colorSpaceName:NSCalibratedRGBColorSpace
+                                                                            bytesPerRow:4
+                                                                           bitsPerPixel:32];
+
+    [NSGraphicsContext saveGraphicsState];
+    [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]];
+    NSEraseRect(NSMakeRect(0, 0, 1, 1));
+    [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
+    [NSGraphicsContext restoreGraphicsState];
+
+    NSUInteger pixel[4];
+    [offscreenRep getPixel:pixel atX:0 y:0];
+
+    [offscreenRep release];
+
+    return makeRGB(pixel[0], pixel[1], pixel[2]);
+}
+
+static RGBA32 menuBackgroundColor()
+{
+    NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
+                                                                             pixelsWide:1
+                                                                             pixelsHigh:1
+                                                                          bitsPerSample:8
+                                                                        samplesPerPixel:4
+                                                                               hasAlpha:YES
+                                                                               isPlanar:NO
+                                                                         colorSpaceName:NSCalibratedRGBColorSpace
+                                                                            bytesPerRow:4
+                                                                           bitsPerPixel:32];
+
+    CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]);
+    CGRect rect = CGRectMake(0, 0, 1, 1);
+    HIThemeMenuDrawInfo drawInfo;
+    drawInfo.version =  0;
+    drawInfo.menuType = kThemeMenuTypePopUp;
+    HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted);
+
+    NSUInteger pixel[4];
+    [offscreenRep getPixel:pixel atX:0 y:0];
+
+    [offscreenRep release];
+
+    return makeRGB(pixel[0], pixel[1], pixel[2]);
+}
+
+void RenderThemeMac::platformColorsDidChange()
+{
+    m_systemColorCache.clear();
+    RenderTheme::platformColorsDidChange();
+}
+
+Color RenderThemeMac::systemColor(int cssValueId) const
+{
+    if (m_systemColorCache.contains(cssValueId))
+        return m_systemColorCache.get(cssValueId);
+    
+    Color color;
+    switch (cssValueId) {
+        case CSSValueActiveborder:
+            color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
+            break;
+        case CSSValueActivecaption:
+            color = convertNSColorToColor([NSColor windowFrameTextColor]);
+            break;
+        case CSSValueAppworkspace:
+            color = convertNSColorToColor([NSColor headerColor]);
+            break;
+        case CSSValueBackground:
+            // Use theme independent default
+            break;
+        case CSSValueButtonface:
+            // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
+            // We may want to change this to use the NSColor in future.
+            color = 0xFFC0C0C0;
+            break;
+        case CSSValueButtonhighlight:
+            color = convertNSColorToColor([NSColor controlHighlightColor]);
+            break;
+        case CSSValueButtonshadow:
+            color = convertNSColorToColor([NSColor controlShadowColor]);
+            break;
+        case CSSValueButtontext:
+            color = convertNSColorToColor([NSColor controlTextColor]);
+            break;
+        case CSSValueCaptiontext:
+            color = convertNSColorToColor([NSColor textColor]);
+            break;
+        case CSSValueGraytext:
+            color = convertNSColorToColor([NSColor disabledControlTextColor]);
+            break;
+        case CSSValueHighlight:
+            color = convertNSColorToColor([NSColor selectedTextBackgroundColor]);
+            break;
+        case CSSValueHighlighttext:
+            color = convertNSColorToColor([NSColor selectedTextColor]);
+            break;
+        case CSSValueInactiveborder:
+            color = convertNSColorToColor([NSColor controlBackgroundColor]);
+            break;
+        case CSSValueInactivecaption:
+            color = convertNSColorToColor([NSColor controlBackgroundColor]);
+            break;
+        case CSSValueInactivecaptiontext:
+            color = convertNSColorToColor([NSColor textColor]);
+            break;
+        case CSSValueInfobackground:
+            // There is no corresponding NSColor for this so we use a hard coded value.
+            color = 0xFFFBFCC5;
+            break;
+        case CSSValueInfotext:
+            color = convertNSColorToColor([NSColor textColor]);
+            break;
+        case CSSValueMenu:
+            color = menuBackgroundColor();
+            break;
+        case CSSValueMenutext:
+            color = convertNSColorToColor([NSColor selectedMenuItemTextColor]);
+            break;
+        case CSSValueScrollbar:
+            color = convertNSColorToColor([NSColor scrollBarColor]);
+            break;
+        case CSSValueText:
+            color = convertNSColorToColor([NSColor textColor]);
+            break;
+        case CSSValueThreeddarkshadow:
+            color = convertNSColorToColor([NSColor controlDarkShadowColor]);
+            break;
+        case CSSValueThreedshadow:
+            color = convertNSColorToColor([NSColor shadowColor]);
+            break;
+        case CSSValueThreedface:
+            // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
+            // We may want to change this to use the NSColor in future.
+            color = 0xFFC0C0C0;
+            break;
+        case CSSValueThreedhighlight:
+            color = convertNSColorToColor([NSColor highlightColor]);
+            break;
+        case CSSValueThreedlightshadow:
+            color = convertNSColorToColor([NSColor controlLightHighlightColor]);
+            break;
+        case CSSValueWindow:
+            color = convertNSColorToColor([NSColor windowBackgroundColor]);
+            break;
+        case CSSValueWindowframe:
+            color = convertNSColorToColor([NSColor windowFrameColor]);
+            break;
+        case CSSValueWindowtext:
+            color = convertNSColorToColor([NSColor windowFrameTextColor]);
+            break;
+    }
+
+    if (!color.isValid())
+        color = RenderTheme::systemColor(cssValueId);
+
+    if (color.isValid())
+        m_systemColorCache.set(cssValueId, color.rgb());
+
+    return color;
+}
+
+bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& border,
+                                     const FillLayer& background, const Color& backgroundColor) const
+{
+    if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
+        return style->border() != border;
+    return RenderTheme::isControlStyled(style, border, background, backgroundColor);
+}
+
+void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
+{
+    ControlPart part = o->style()->appearance();
+    
+#if USE(NEW_THEME)
+    switch (part) {
+        case CheckboxPart:
+        case RadioPart:
+        case PushButtonPart:
+        case SquareButtonPart:
+        case DefaultButtonPart:
+        case ButtonPart:
+            return RenderTheme::adjustRepaintRect(o, r);
+        default:
+            break;
+    }
+#endif
+
+    float zoomLevel = o->style()->effectiveZoom();
+
+    if (part == MenulistPart) {
+        setPopupButtonCellState(o, r);
+        IntSize size = popupButtonSizes()[[popupButton() controlSize]];
+        size.setHeight(size.height() * zoomLevel);
+        size.setWidth(r.width());
+        r = inflateRect(r, size, popupButtonMargins(), zoomLevel);
+    }
+}
+
+IntRect RenderThemeMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const
+{
+    // Only do the inflation if the available width/height are too small.  Otherwise try to
+    // fit the glow/check space into the available box's width/height.
+    int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel);
+    int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel);
+    IntRect result(r);
+    if (widthDelta < 0) {
+        result.setX(result.x() - margins[leftMargin] * zoomLevel);
+        result.setWidth(result.width() - widthDelta);
+    }
+    if (heightDelta < 0) {
+        result.setY(result.y() - margins[topMargin] * zoomLevel);
+        result.setHeight(result.height() - heightDelta);
+    }
+    return result;
+}
+
+void RenderThemeMac::updateCheckedState(NSCell* cell, const RenderObject* o)
+{
+    bool oldIndeterminate = [cell state] == NSMixedState;
+    bool indeterminate = isIndeterminate(o);
+    bool checked = isChecked(o);
+
+    if (oldIndeterminate != indeterminate) {
+        [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
+        return;
+    }
+
+    bool oldChecked = [cell state] == NSOnState;
+    if (checked != oldChecked)
+        [cell setState:checked ? NSOnState : NSOffState];
+}
+
+void RenderThemeMac::updateEnabledState(NSCell* cell, const RenderObject* o)
+{
+    bool oldEnabled = [cell isEnabled];
+    bool enabled = isEnabled(o);
+    if (enabled != oldEnabled)
+        [cell setEnabled:enabled];
+}
+
+void RenderThemeMac::updateFocusedState(NSCell* cell, const RenderObject* o)
+{
+    bool oldFocused = [cell showsFirstResponder];
+    bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
+    if (focused != oldFocused)
+        [cell setShowsFirstResponder:focused];
+}
+
+void RenderThemeMac::updatePressedState(NSCell* cell, const RenderObject* o)
+{
+    bool oldPressed = [cell isHighlighted];
+    bool pressed = (o->element() && o->element()->active());
+    if (pressed != oldPressed)
+        [cell setHighlighted:pressed];
+}
+
+bool RenderThemeMac::controlSupportsTints(const RenderObject* o) const
+{
+    // An alternate way to implement this would be to get the appropriate cell object
+    // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of
+    // that would be that we would match AppKit behavior more closely, but a disadvantage
+    // would be that we would rely on an AppKit SPI method.
+
+    if (!isEnabled(o))
+        return false;
+
+    // Checkboxes only have tint when checked.
+    if (o->style()->appearance() == CheckboxPart)
+        return isChecked(o);
+
+    // For now assume other controls have tint if enabled.
+    return true;
+}
+
+NSControlSize RenderThemeMac::controlSizeForFont(RenderStyle* style) const
+{
+    int fontSize = style->fontSize();
+    if (fontSize >= 16)
+        return NSRegularControlSize;
+    if (fontSize >= 11)
+        return NSSmallControlSize;
+    return NSMiniControlSize;
+}
+
+void RenderThemeMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel)
+{
+    NSControlSize size;
+    if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) &&
+        minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel))
+        size = NSRegularControlSize;
+    else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) &&
+             minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel))
+        size = NSSmallControlSize;
+    else
+        size = NSMiniControlSize;
+    if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
+        [cell setControlSize:size];
+}
+
+IntSize RenderThemeMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const
+{
+    if (style->effectiveZoom() != 1.0f) {
+        IntSize result = sizes[controlSizeForFont(style)];
+        return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
+    }
+    return sizes[controlSizeForFont(style)];
+}
+
+IntSize RenderThemeMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
+{
+    if (style->effectiveZoom() != 1.0f) {
+        IntSize result = sizes[controlSizeForSystemFont(style)];
+        return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
+    }
+    return sizes[controlSizeForSystemFont(style)];
+}
+
+void RenderThemeMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
+{
+    // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
+    IntSize size = sizeForFont(style, sizes);
+    if (style->width().isIntrinsicOrAuto() && size.width() > 0)
+        style->setWidth(Length(size.width(), Fixed));
+    if (style->height().isAuto() && size.height() > 0)
+        style->setHeight(Length(size.height(), Fixed));
+}
+
+void RenderThemeMac::setFontFromControlSize(CSSStyleSelector* selector, RenderStyle* style, NSControlSize controlSize) const
+{
+    FontDescription fontDescription;
+    fontDescription.setIsAbsoluteSize(true);
+    fontDescription.setGenericFamily(FontDescription::SerifFamily);
+
+    NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]];
+    fontDescription.firstFamily().setFamily([font familyName]);
+    fontDescription.setComputedSize([font pointSize] * style->effectiveZoom());
+    fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom());
+
+    // Reset line height
+    style->setLineHeight(RenderStyle::initialLineHeight());
+
+    if (style->setFontDescription(fontDescription))
+        style->font().update(0);
+}
+
+NSControlSize RenderThemeMac::controlSizeForSystemFont(RenderStyle* style) const
+{
+    int fontSize = style->fontSize();
+    if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize])
+        return NSRegularControlSize;
+    if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize])
+        return NSSmallControlSize;
+    return NSMiniControlSize;
+}
+
+bool RenderThemeMac::paintTextField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o));
+    return false;
+}
+
+void RenderThemeMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderThemeMac::paintCapsLockIndicator(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    if (paintInfo.context->paintingDisabled())
+        return true;
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    wkDrawCapsLockIndicator(paintInfo.context->platformContext(), r);
+    
+    return false;
+}
+
+bool RenderThemeMac::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    wkDrawBezeledTextArea(r, isEnabled(o) && !isReadOnlyControl(o));
+    return false;
+}
+
+void RenderThemeMac::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+{
+}
+
+const int* RenderThemeMac::popupButtonMargins() const
+{
+    static const int margins[3][4] =
+    {
+        { 0, 3, 1, 3 },
+        { 0, 3, 2, 3 },
+        { 0, 1, 0, 1 }
+    };
+    return margins[[popupButton() controlSize]];
+}
+
+const IntSize* RenderThemeMac::popupButtonSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
+    return sizes;
+}
+
+const int* RenderThemeMac::popupButtonPadding(NSControlSize size) const
+{
+    static const int padding[3][4] =
+    {
+        { 2, 26, 3, 8 },
+        { 2, 23, 3, 8 },
+        { 2, 22, 3, 10 }
+    };
+    return padding[size];
+}
+
+bool RenderThemeMac::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    setPopupButtonCellState(o, r);
+
+    NSPopUpButtonCell* popupButton = this->popupButton();
+
+    float zoomLevel = o->style()->effectiveZoom();
+    IntSize size = popupButtonSizes()[[popupButton controlSize]];
+    size.setHeight(size.height() * zoomLevel);
+    size.setWidth(r.width());
+
+    // Now inflate it to account for the shadow.
+    IntRect inflatedRect = r;
+    if (r.width() >= minimumMenuListSize(o->style()))
+        inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel);
+
+    paintInfo.context->save();
+    
+#ifndef BUILDING_ON_TIGER
+    // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect
+    paintInfo.context->clip(inflatedRect);
+#endif
+
+    if (zoomLevel != 1.0f) {
+        inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
+        inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
+        paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
+        paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+        paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
+    }
+
+    [popupButton drawWithFrame:inflatedRect inView:o->view()->frameView()->documentView()];
+    [popupButton setControlView:nil];
+
+    paintInfo.context->restore();
+
+    return false;
+}
+
+const float baseFontSize = 11.0f;
+const float baseArrowHeight = 4.0f;
+const float baseArrowWidth = 5.0f;
+const float baseSpaceBetweenArrows = 2.0f;
+const int arrowPaddingLeft = 6;
+const int arrowPaddingRight = 6;
+const int paddingBeforeSeparator = 4;
+const int baseBorderRadius = 5;
+const int styledPopupPaddingLeft = 8;
+const int styledPopupPaddingTop = 1;
+const int styledPopupPaddingBottom = 2;
+
+static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+    static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
+    static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
+    float a = inData[0];
+    int i = 0;
+    for (i = 0; i < 4; i++)
+        outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+    static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
+    static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
+    float a = inData[0];
+    int i = 0;
+    for (i = 0; i < 4; i++)
+        outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+    static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
+    static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+    float a = inData[0];
+    int i = 0;
+    for (i = 0; i < 4; i++)
+        outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+    static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
+    static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
+    float a = inData[0];
+    int i = 0;
+    for (i = 0; i < 4; i++)
+        outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    CGContextRef context = paintInfo.context->platformContext();
+
+    paintInfo.context->save();
+
+    int radius = o->style()->borderTopLeftRadius().width();
+
+    RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+
+    FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
+    struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
+    RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
+    RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.bottom()), topFunction.get(), false, false));
+
+    FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
+    struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
+    RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
+    RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(bottomGradient.x(),  bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.bottom()), bottomFunction.get(), false, false));
+
+    struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
+    RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
+    RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x(), r.bottom()), mainFunction.get(), false, false));
+
+    RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
+
+    RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(),  r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false));
+    paintInfo.context->save();
+    CGContextClipToRect(context, r);
+    paintInfo.context->addRoundedRectClip(r,
+        o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
+        o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
+    CGContextDrawShading(context, mainShading.get());
+    paintInfo.context->restore();
+
+    paintInfo.context->save();
+    CGContextClipToRect(context, topGradient);
+    paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient),
+        o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
+        IntSize(), IntSize());
+    CGContextDrawShading(context, topShading.get());
+    paintInfo.context->restore();
+
+    paintInfo.context->save();
+    CGContextClipToRect(context, bottomGradient);
+    paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient),
+        IntSize(), IntSize(),
+        o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
+    CGContextDrawShading(context, bottomShading.get());
+    paintInfo.context->restore();
+
+    paintInfo.context->save();
+    CGContextClipToRect(context, r);
+    paintInfo.context->addRoundedRectClip(r,
+        o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
+        o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
+    CGContextDrawShading(context, leftShading.get());
+    CGContextDrawShading(context, rightShading.get());
+    paintInfo.context->restore();
+
+    paintInfo.context->restore();
+}
+
+bool RenderThemeMac::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    paintInfo.context->save();
+
+    IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
+                             r.y() + o->style()->borderTopWidth(),
+                             r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
+                             r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
+    // Draw the gradients to give the styled popup menu a button appearance
+    paintMenuListButtonGradients(o, paintInfo, bounds);
+
+    // Since we actually know the size of the control here, we restrict the font scale to make sure the arrows will fit vertically in the bounds
+    float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
+    float centerY = bounds.y() + bounds.height() / 2.0f;
+    float arrowHeight = baseArrowHeight * fontScale;
+    float arrowWidth = baseArrowWidth * fontScale;
+    float leftEdge = bounds.right() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth;
+    float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
+
+    if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom())
+        return false;
+    
+    paintInfo.context->setFillColor(o->style()->color());
+    paintInfo.context->setStrokeStyle(NoStroke);
+
+    FloatPoint arrow1[3];
+    arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f);
+    arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f);
+    arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight);
+
+    // Draw the top arrow
+    paintInfo.context->drawConvexPolygon(3, arrow1, true);
+
+    FloatPoint arrow2[3];
+    arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f);
+    arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f);
+    arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight);
+
+    // Draw the bottom arrow
+    paintInfo.context->drawConvexPolygon(3, arrow2, true);
+
+    Color leftSeparatorColor(0, 0, 0, 40);
+    Color rightSeparatorColor(255, 255, 255, 40);
+
+    // FIXME: Should the separator thickness and space be scaled up by fontScale?
+    int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin.
+    int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round?
+
+    // Draw the separator to the left of the arrows
+    paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin.
+    paintInfo.context->setStrokeStyle(SolidStroke);
+    paintInfo.context->setStrokeColor(leftSeparatorColor);
+    paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
+                                IntPoint(leftEdgeOfSeparator, bounds.bottom()));
+
+    paintInfo.context->setStrokeColor(rightSeparatorColor);
+    paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
+                                IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom()));
+
+    paintInfo.context->restore();
+    return false;
+}
+
+static const IntSize* menuListButtonSizes()
+{
+    static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
+    return sizes;
+}
+
+void RenderThemeMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    NSControlSize controlSize = controlSizeForFont(style);
+
+    style->resetBorder();
+    style->resetPadding();
+    
+    // Height is locked to auto.
+    style->setHeight(Length(Auto));
+
+    // White-space is locked to pre
+    style->setWhiteSpace(PRE);
+
+    // Set the foreground color to black or gray when we have the aqua look.
+    // Cast to RGB32 is to work around a compiler bug.
+    style->setColor(e->isEnabled() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
+
+    // Set the button's vertical size.
+    setSizeFromFont(style, menuListButtonSizes());
+
+    // Our font is locked to the appropriate system font size for the control.  To clarify, we first use the CSS-specified font to figure out
+    // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
+    // system font for the control size instead.
+    setFontFromControlSize(selector, style, controlSize);
+
+    style->setBoxShadow(0);
+}
+
+int RenderThemeMac::popupInternalPaddingLeft(RenderStyle* style) const
+{
+    if (style->appearance() == MenulistPart)
+        return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom();
+    if (style->appearance() == MenulistButtonPart)
+        return styledPopupPaddingLeft * style->effectiveZoom();
+    return 0;
+}
+
+int RenderThemeMac::popupInternalPaddingRight(RenderStyle* style) const
+{
+    if (style->appearance() == MenulistPart)
+        return popupButtonPadding(controlSizeForFont(style))[rightPadding] * style->effectiveZoom();
+    if (style->appearance() == MenulistButtonPart) {
+        float fontScale = style->fontSize() / baseFontSize;
+        float arrowWidth = baseArrowWidth * fontScale;
+        return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom()));
+    }
+    return 0;
+}
+
+int RenderThemeMac::popupInternalPaddingTop(RenderStyle* style) const
+{
+    if (style->appearance() == MenulistPart)
+        return popupButtonPadding(controlSizeForFont(style))[topPadding] * style->effectiveZoom();
+    if (style->appearance() == MenulistButtonPart)
+        return styledPopupPaddingTop * style->effectiveZoom();
+    return 0;
+}
+
+int RenderThemeMac::popupInternalPaddingBottom(RenderStyle* style) const
+{
+    if (style->appearance() == MenulistPart)
+        return popupButtonPadding(controlSizeForFont(style))[bottomPadding] * style->effectiveZoom();
+    if (style->appearance() == MenulistButtonPart)
+        return styledPopupPaddingBottom * style->effectiveZoom();
+    return 0;
+}
+
+void RenderThemeMac::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    float fontScale = style->fontSize() / baseFontSize;
+
+    style->resetPadding();
+    style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
+
+    const int minHeight = 15;
+    style->setMinHeight(Length(minHeight, Fixed));
+    
+    style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
+{
+    NSPopUpButtonCell* popupButton = this->popupButton();
+
+    // Set the control size based off the rectangle we're painting into.
+    setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom());
+
+    // Update the various states we respond to.
+    updateCheckedState(popupButton, o);
+    updateEnabledState(popupButton, o);
+    updatePressedState(popupButton, o);
+    updateFocusedState(popupButton, o);
+}
+
+const IntSize* RenderThemeMac::menuListSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
+    return sizes;
+}
+
+int RenderThemeMac::minimumMenuListSize(RenderStyle* style) const
+{
+    return sizeForSystemFont(style, menuListSizes()).width();
+}
+
+const int trackWidth = 5;
+const int trackRadius = 2;
+
+void RenderThemeMac::adjustSliderTrackStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    style->setBoxShadow(0);
+}
+
+bool RenderThemeMac::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    IntRect bounds = r;
+    float zoomLevel = o->style()->effectiveZoom();
+    float zoomedTrackWidth = trackWidth * zoomLevel;
+
+    if (o->style()->appearance() ==  SliderHorizontalPart || o->style()->appearance() ==  MediaSliderPart) {
+        bounds.setHeight(zoomedTrackWidth);
+        bounds.setY(r.y() + r.height() / 2 - zoomedTrackWidth / 2);
+    } else if (o->style()->appearance() == SliderVerticalPart) {
+        bounds.setWidth(zoomedTrackWidth);
+        bounds.setX(r.x() + r.width() / 2 - zoomedTrackWidth / 2);
+    }
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    CGContextRef context = paintInfo.context->platformContext();
+    RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+
+    paintInfo.context->save();
+    CGContextClipToRect(context, bounds);
+
+    struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
+    RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
+    RetainPtr<CGShadingRef> mainShading;
+    if (o->style()->appearance() == SliderVerticalPart)
+        mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.bottom()), CGPointMake(bounds.right(), bounds.bottom()), mainFunction.get(), false, false));
+    else
+        mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.y()), CGPointMake(bounds.x(), bounds.bottom()), mainFunction.get(), false, false));
+
+    IntSize radius(trackRadius, trackRadius);
+    paintInfo.context->addRoundedRectClip(bounds,
+        radius, radius,
+        radius, radius);
+    CGContextDrawShading(context, mainShading.get());
+    paintInfo.context->restore();
+    
+    return false;
+}
+
+void RenderThemeMac::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    style->setBoxShadow(0);
+}
+
+const float verticalSliderHeightPadding = 0.1f;
+
+bool RenderThemeMac::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    ASSERT(o->parent()->isSlider());
+
+    NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart
+        ? sliderThumbVertical()
+        : sliderThumbHorizontal();
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+    // Update the various states we respond to.
+    updateEnabledState(sliderThumbCell, o->parent());
+    updateFocusedState(sliderThumbCell, o->parent());
+
+    // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it.
+    bool oldPressed;
+    if (o->style()->appearance() == SliderThumbVerticalPart)
+        oldPressed = m_isSliderThumbVerticalPressed;
+    else
+        oldPressed = m_isSliderThumbHorizontalPressed;
+
+    bool pressed = static_cast<RenderSlider*>(o->parent())->inDragMode();
+
+    if (o->style()->appearance() == SliderThumbVerticalPart)
+        m_isSliderThumbVerticalPressed = pressed;
+    else
+        m_isSliderThumbHorizontalPressed = pressed;
+
+    if (pressed != oldPressed) {
+        if (pressed)
+            [sliderThumbCell startTrackingAt:NSPoint() inView:nil];
+        else
+            [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES];
+    }
+
+    FloatRect bounds = r;
+    // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider.
+    if (o->style()->appearance() == SliderThumbVerticalPart)
+        bounds.setHeight(bounds.height() + verticalSliderHeightPadding * o->style()->effectiveZoom());
+
+    paintInfo.context->save();
+    float zoomLevel = o->style()->effectiveZoom();
+    
+    FloatRect unzoomedRect = bounds;
+    if (zoomLevel != 1.0f) {
+        unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+        unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+        paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+        paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+        paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+    }
+
+    [sliderThumbCell drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()];
+    [sliderThumbCell setControlView:nil];
+
+    paintInfo.context->restore();
+
+    return false;
+}
+
+const int sliderThumbWidth = 15;
+const int sliderThumbHeight = 15;
+const int mediaSliderThumbWidth = 13;
+const int mediaSliderThumbHeight = 14;
+
+void RenderThemeMac::adjustSliderThumbSize(RenderObject* o) const
+{
+    float zoomLevel = o->style()->effectiveZoom();
+    if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) {
+        o->style()->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed));
+        o->style()->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed));
+    } else if (o->style()->appearance() == MediaSliderThumbPart) {
+        o->style()->setWidth(Length(mediaSliderThumbWidth, Fixed));
+        o->style()->setHeight(Length(mediaSliderThumbHeight, Fixed));
+    }
+}
+
+bool RenderThemeMac::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    NSSearchFieldCell* search = this->search();
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+    setSearchCellState(o, r);
+
+    paintInfo.context->save();
+
+    float zoomLevel = o->style()->effectiveZoom();
+
+    IntRect unzoomedRect = r;
+    
+    if (zoomLevel != 1.0f) {
+        unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+        unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+        paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+        paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+        paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+    }
+
+    // Set the search button to nil before drawing.  Then reset it so we can draw it later.
+    [search setSearchButtonCell:nil];
+
+    [search drawWithFrame:NSRect(unzoomedRect) inView:o->view()->frameView()->documentView()];
+#ifdef BUILDING_ON_TIGER
+    if ([search showsFirstResponder])
+        wkDrawTextFieldCellFocusRing(search, NSRect(unzoomedRect));
+#endif
+
+    [search setControlView:nil];
+    [search resetSearchButtonCell];
+
+    paintInfo.context->restore();
+
+    return false;
+}
+
+void RenderThemeMac::setSearchCellState(RenderObject* o, const IntRect& r)
+{
+    NSSearchFieldCell* search = this->search();
+
+    [search setControlSize:controlSizeForFont(o->style())];
+
+    // Update the various states we respond to.
+    updateEnabledState(search, o);
+    updateFocusedState(search, o);
+}
+
+const IntSize* RenderThemeMac::searchFieldSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) };
+    return sizes;
+}
+
+void RenderThemeMac::setSearchFieldSize(RenderStyle* style) const
+{
+    // If the width and height are both specified, then we have nothing to do.
+    if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+        return;
+    
+    // Use the font size to determine the intrinsic width of the control.
+    setSizeFromFont(style, searchFieldSizes());
+}
+
+void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    // Override border.
+    style->resetBorder();
+    const short borderWidth = 2 * style->effectiveZoom();
+    style->setBorderLeftWidth(borderWidth);
+    style->setBorderLeftStyle(INSET);
+    style->setBorderRightWidth(borderWidth);
+    style->setBorderRightStyle(INSET);
+    style->setBorderBottomWidth(borderWidth);
+    style->setBorderBottomStyle(INSET);
+    style->setBorderTopWidth(borderWidth);
+    style->setBorderTopStyle(INSET);    
+    
+    // Override height.
+    style->setHeight(Length(Auto));
+    setSearchFieldSize(style);
+    
+    // Override padding size to match AppKit text positioning.
+    const int padding = 1 * style->effectiveZoom();
+    style->setPaddingLeft(Length(padding, Fixed));
+    style->setPaddingRight(Length(padding, Fixed));
+    style->setPaddingTop(Length(padding, Fixed));
+    style->setPaddingBottom(Length(padding, Fixed));
+    
+    NSControlSize controlSize = controlSizeForFont(style);
+    setFontFromControlSize(selector, style, controlSize);
+
+    style->setBoxShadow(0);
+}
+
+bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* input = o->node()->shadowAncestorNode();
+    setSearchCellState(input->renderer(), r);
+
+    NSSearchFieldCell* search = this->search();
+
+    updatePressedState([search cancelButtonCell], o);
+
+    paintInfo.context->save();
+
+    float zoomLevel = o->style()->effectiveZoom();
+
+    NSRect bounds = [search cancelButtonRectForBounds:NSRect(input->renderer()->absoluteBoundingBoxRect())];
+    
+    IntRect unzoomedRect(bounds);
+    if (zoomLevel != 1.0f) {
+        unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+        unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+        paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+        paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+        paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+    }
+
+    [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()];
+    [[search cancelButtonCell] setControlView:nil];
+
+    paintInfo.context->restore();
+    return false;
+}
+
+const IntSize* RenderThemeMac::cancelButtonSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
+    return sizes;
+}
+
+void RenderThemeMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize size = sizeForSystemFont(style, cancelButtonSizes());
+    style->setWidth(Length(size.width(), Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+    style->setBoxShadow(0);
+}
+
+const IntSize* RenderThemeMac::resultsButtonSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
+    return sizes;
+}
+
+const int emptyResultsOffset = 9;
+void RenderThemeMac::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+    style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+    style->setBoxShadow(0);
+}
+
+bool RenderThemeMac::paintSearchFieldDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    return false;
+}
+
+void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+    style->setWidth(Length(size.width(), Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+    style->setBoxShadow(0);
+}
+
+bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* input = o->node()->shadowAncestorNode();
+    setSearchCellState(input->renderer(), r);
+
+    NSSearchFieldCell* search = this->search();
+
+    if ([search searchMenuTemplate] != nil)
+        [search setSearchMenuTemplate:nil];
+
+    NSRect bounds = [search searchButtonRectForBounds:NSRect(input->renderer()->absoluteBoundingBoxRect())];
+    [[search searchButtonCell] drawWithFrame:bounds inView:o->view()->frameView()->documentView()];
+    [[search searchButtonCell] setControlView:nil];
+    return false;
+}
+
+const int resultsArrowWidth = 5;
+void RenderThemeMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+    style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+    style->setBoxShadow(0);
+}
+
+bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* input = o->node()->shadowAncestorNode();
+    setSearchCellState(input->renderer(), r);
+
+    NSSearchFieldCell* search = this->search();
+
+    if (![search searchMenuTemplate])
+        [search setSearchMenuTemplate:searchMenuTemplate()];
+
+    paintInfo.context->save();
+
+    float zoomLevel = o->style()->effectiveZoom();
+
+    NSRect bounds = [search searchButtonRectForBounds:NSRect(input->renderer()->absoluteBoundingBoxRect())];
+    
+    IntRect unzoomedRect(bounds);
+    if (zoomLevel != 1.0f) {
+        unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+        unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+        paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+        paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+        paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+    }
+
+    [[search searchButtonCell] drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()];
+    [[search searchButtonCell] setControlView:nil];
+    
+    paintInfo.context->restore();
+
+    return false;
+}
+
+bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* node = o->element();
+    if (!node)
+        return false;
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    wkDrawMediaFullscreenButton(paintInfo.context->platformContext(), r, node->active());
+    return false;
+}
+
+bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* node = o->element();
+    Node* mediaNode = node ? node->shadowAncestorNode() : 0;
+    if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
+        return false;
+
+    HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
+    if (!mediaElement)
+        return false;
+    
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    if (mediaElement->muted())
+        wkDrawMediaUnMuteButton(paintInfo.context->platformContext(), r, node->active());
+    else
+        wkDrawMediaMuteButton(paintInfo.context->platformContext(), r, node->active());        
+    return false;
+}
+
+bool RenderThemeMac::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* node = o->element();
+    Node* mediaNode = node ? node->shadowAncestorNode() : 0;
+    if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
+        return false;
+
+    HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
+    if (!mediaElement)
+        return false;
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    if (mediaElement->canPlay())
+        wkDrawMediaPlayButton(paintInfo.context->platformContext(), r, node->active());
+    else
+        wkDrawMediaPauseButton(paintInfo.context->platformContext(), r, node->active());        
+    return false;
+}
+
+bool RenderThemeMac::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* node = o->element();
+    if (!node)
+        return false;
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    wkDrawMediaSeekBackButton(paintInfo.context->platformContext(), r, node->active());
+    return false;
+}
+
+bool RenderThemeMac::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* node = o->element();
+    if (!node)
+        return false;
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    wkDrawMediaSeekForwardButton(paintInfo.context->platformContext(), r, node->active());
+    return false;
+}
+
+bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* node = o->element();
+    Node* mediaNode = node ? node->shadowAncestorNode() : 0;
+    if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
+        return false;
+
+    HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
+    if (!mediaElement)
+        return false;
+
+    float percentLoaded = 0;
+    if (MediaPlayer* player = mediaElement->player())
+        if (player->duration())
+            percentLoaded = player->maxTimeBuffered() / player->duration();
+
+    wkDrawMediaSliderTrack(paintInfo.context->platformContext(), r, percentLoaded);
+    return false;
+}
+
+bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* node = o->element();
+    if (!node)
+        return false;
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    wkDrawMediaSliderThumb(paintInfo.context->platformContext(), r, node->active());
+    return false;
+}
+
+NSPopUpButtonCell* RenderThemeMac::popupButton() const
+{
+    if (!m_popupButton) {
+        m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
+        [m_popupButton.get() setUsesItemFromMenu:NO];
+        [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior];
+    }
+    
+    return m_popupButton.get();
+}
+
+NSSearchFieldCell* RenderThemeMac::search() const
+{
+    if (!m_search) {
+        m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]);
+        [m_search.get() setBezelStyle:NSTextFieldRoundedBezel];
+        [m_search.get() setBezeled:YES];
+        [m_search.get() setEditable:YES];
+        [m_search.get() setFocusRingType:NSFocusRingTypeExterior];
+    }
+
+    return m_search.get();
+}
+
+NSMenu* RenderThemeMac::searchMenuTemplate() const
+{
+    if (!m_searchMenuTemplate)
+        m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
+
+    return m_searchMenuTemplate.get();
+}
+
+NSSliderCell* RenderThemeMac::sliderThumbHorizontal() const
+{
+    if (!m_sliderThumbHorizontal) {
+        m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]);
+        [m_sliderThumbHorizontal.get() setTitle:nil];
+        [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider];
+        [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize];
+        [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior];
+    }
+    
+    return m_sliderThumbHorizontal.get();
+}
+
+NSSliderCell* RenderThemeMac::sliderThumbVertical() const
+{
+    if (!m_sliderThumbVertical) {
+        m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]);
+        [m_sliderThumbVertical.get() setTitle:nil];
+        [m_sliderThumbVertical.get() setSliderType:NSLinearSlider];
+        [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize];
+        [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior];
+    }
+    
+    return m_sliderThumbVertical.get();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderThemeSafari.cpp b/WebCore/rendering/RenderThemeSafari.cpp
new file mode 100644
index 0000000..31315bc
--- /dev/null
+++ b/WebCore/rendering/RenderThemeSafari.cpp
@@ -0,0 +1,1235 @@
+/*
+ * Copyright (C) 2007, 2008 Apple 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderThemeSafari.h"
+#include "RenderThemeWin.h"
+#include "Settings.h"
+
+#if USE(SAFARI_THEME)
+
+#include "CSSValueKeywords.h"
+#include "Document.h"
+#include "Element.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLInputElement.h"
+#include "HTMLMediaElement.h"
+#include "HTMLNames.h"
+#include "RenderSlider.h"
+#include "RenderView.h"
+#include "RetainPtr.h"
+#include "SoftLinking.h"
+#include "cssstyleselector.h"
+#include <CoreGraphics/CoreGraphics.h>
+ 
+using std::min;
+
+// FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeMac. 
+ 
+namespace WebCore {
+
+using namespace HTMLNames;
+using namespace SafariTheme;
+
+enum {
+    topMargin,
+    rightMargin,
+    bottomMargin,
+    leftMargin
+};
+
+enum {
+    topPadding,
+    rightPadding,
+    bottomPadding,
+    leftPadding
+};
+
+RenderTheme* theme()
+{
+    static RenderThemeSafari safariTheme;
+    static RenderThemeWin windowsTheme;
+    if (Settings::shouldPaintNativeControls())
+        return &windowsTheme;
+    return &safariTheme;
+}
+
+#if !defined(NDEBUG) && defined(USE_DEBUG_SAFARI_THEME)
+SOFT_LINK_DEBUG_LIBRARY(SafariTheme)
+#else
+SOFT_LINK_LIBRARY(SafariTheme)
+#endif
+
+SOFT_LINK(SafariTheme, paintThemePart, void, __stdcall, (ThemePart part, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state), (part, context, rect, size, state))
+#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
+SOFT_LINK(SafariTheme, STPaintProgressIndicator, void, APIENTRY, (ProgressIndicatorType type, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state, float value), (type, context, rect, size, state, value))
+#endif
+
+ThemeControlState RenderThemeSafari::determineState(RenderObject* o) const
+{
+    ThemeControlState result = 0;
+    if (isActive(o))
+        result |= SafariTheme::ActiveState;
+    if (isEnabled(o) && !isReadOnlyControl(o))
+        result |= SafariTheme::EnabledState;
+    if (isPressed(o))
+        result |= SafariTheme::PressedState;
+    if (isChecked(o))
+        result |= SafariTheme::CheckedState;
+    if (isIndeterminate(o))
+        result |= SafariTheme::IndeterminateCheckedState;
+    if (isFocused(o))
+        result |= SafariTheme::FocusedState;
+    if (isDefault(o))
+        result |= SafariTheme::DefaultState;
+    return result;
+}
+
+static NSControlSize controlSizeFromRect(const IntRect& rect, const IntSize sizes[])
+{
+    if (sizes[NSRegularControlSize].height() == rect.height())
+        return NSRegularControlSize;
+    else if (sizes[NSMiniControlSize].height() == rect.height())
+        return NSMiniControlSize;
+    
+    return NSSmallControlSize;
+}
+
+RenderThemeSafari::RenderThemeSafari()
+{
+}
+
+RenderThemeSafari::~RenderThemeSafari()
+{
+}
+
+Color RenderThemeSafari::platformActiveSelectionBackgroundColor() const
+{
+    return Color(181, 213, 255);
+}
+
+Color RenderThemeSafari::platformInactiveSelectionBackgroundColor() const
+{
+    return Color(212, 212, 212);
+}
+
+Color RenderThemeSafari::activeListBoxSelectionBackgroundColor() const
+{
+    // FIXME: This should probably just be a darker version of the platformActiveSelectionBackgroundColor
+    return Color(56, 117, 215);
+}
+
+static float systemFontSizeForControlSize(NSControlSize controlSize)
+{
+    static float sizes[] = { 13.0f, 11.0f, 9.0f };
+    
+    return sizes[controlSize];
+}
+
+void RenderThemeSafari::systemFont(int propId, FontDescription& fontDescription) const
+{
+    static FontDescription systemFont;
+    static FontDescription smallSystemFont;
+    static FontDescription menuFont;
+    static FontDescription labelFont;
+    static FontDescription miniControlFont;
+    static FontDescription smallControlFont;
+    static FontDescription controlFont;
+
+    FontDescription* cachedDesc;
+    float fontSize = 0;
+    switch (propId) {
+        case CSSValueSmallCaption:
+            cachedDesc = &smallSystemFont;
+            if (!smallSystemFont.isAbsoluteSize())
+                fontSize = systemFontSizeForControlSize(NSSmallControlSize);
+            break;
+        case CSSValueMenu:
+            cachedDesc = &menuFont;
+            if (!menuFont.isAbsoluteSize())
+                fontSize = systemFontSizeForControlSize(NSRegularControlSize);
+            break;
+        case CSSValueStatusBar:
+            cachedDesc = &labelFont;
+            if (!labelFont.isAbsoluteSize())
+                fontSize = 10.0f;
+            break;
+        case CSSValueWebkitMiniControl:
+            cachedDesc = &miniControlFont;
+            if (!miniControlFont.isAbsoluteSize())
+                fontSize = systemFontSizeForControlSize(NSMiniControlSize);
+            break;
+        case CSSValueWebkitSmallControl:
+            cachedDesc = &smallControlFont;
+            if (!smallControlFont.isAbsoluteSize())
+                fontSize = systemFontSizeForControlSize(NSSmallControlSize);
+            break;
+        case CSSValueWebkitControl:
+            cachedDesc = &controlFont;
+            if (!controlFont.isAbsoluteSize())
+                fontSize = systemFontSizeForControlSize(NSRegularControlSize);
+            break;
+        default:
+            cachedDesc = &systemFont;
+            if (!systemFont.isAbsoluteSize())
+                fontSize = 13.0f;
+    }
+
+    if (fontSize) {
+        cachedDesc->setIsAbsoluteSize(true);
+        cachedDesc->setGenericFamily(FontDescription::NoFamily);
+        cachedDesc->firstFamily().setFamily("Lucida Grande");
+        cachedDesc->setSpecifiedSize(fontSize);
+        cachedDesc->setWeight(FontWeightNormal);
+        cachedDesc->setItalic(false);
+    }
+    fontDescription = *cachedDesc;
+}
+
+bool RenderThemeSafari::isControlStyled(const RenderStyle* style, const BorderData& border,
+                                     const FillLayer& background, const Color& backgroundColor) const
+{
+    // If we didn't find SafariTheme.dll we won't be able to paint any themed controls.
+    if (!SafariThemeLibrary())
+        return true;
+
+    if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
+        return style->border() != border;
+    return RenderTheme::isControlStyled(style, border, background, backgroundColor);
+}
+
+void RenderThemeSafari::adjustRepaintRect(const RenderObject* o, IntRect& r)
+{
+    NSControlSize controlSize = controlSizeForFont(o->style());
+
+    switch (o->style()->appearance()) {
+        case CheckboxPart: {
+            // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
+            // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
+            r = inflateRect(r, checkboxSizes()[controlSize], checkboxMargins(controlSize));
+            break;
+        }
+        case RadioPart: {
+            // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
+            // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
+            r = inflateRect(r, radioSizes()[controlSize], radioMargins(controlSize));
+            break;
+        }
+        case PushButtonPart:
+        case DefaultButtonPart:
+        case ButtonPart: {
+            // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
+            // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
+            if (r.height() <= buttonSizes()[NSRegularControlSize].height())
+                r = inflateRect(r, buttonSizes()[controlSize], buttonMargins(controlSize));
+            break;
+        }
+        case MenulistPart: {
+            r = inflateRect(r, popupButtonSizes()[controlSize], popupButtonMargins(controlSize));
+            break;
+        }
+        default:
+            break;
+    }
+}
+
+IntRect RenderThemeSafari::inflateRect(const IntRect& r, const IntSize& size, const int* margins) const
+{
+    // Only do the inflation if the available width/height are too small.  Otherwise try to
+    // fit the glow/check space into the available box's width/height.
+    int widthDelta = r.width() - (size.width() + margins[leftMargin] + margins[rightMargin]);
+    int heightDelta = r.height() - (size.height() + margins[topMargin] + margins[bottomMargin]);
+    IntRect result(r);
+    if (widthDelta < 0) {
+        result.setX(result.x() - margins[leftMargin]);
+        result.setWidth(result.width() - widthDelta);
+    }
+    if (heightDelta < 0) {
+        result.setY(result.y() - margins[topMargin]);
+        result.setHeight(result.height() - heightDelta);
+    }
+    return result;
+}
+
+int RenderThemeSafari::baselinePosition(const RenderObject* o) const
+{
+    if (o->style()->appearance() == CheckboxPart || o->style()->appearance() == RadioPart)
+        return o->marginTop() + o->height() - 2; // The baseline is 2px up from the bottom of the checkbox/radio in AppKit.
+    return RenderTheme::baselinePosition(o);
+}
+
+bool RenderThemeSafari::controlSupportsTints(const RenderObject* o) const
+{
+    if (!isEnabled(o))
+        return false;
+
+    // Checkboxes only have tint when checked.
+    if (o->style()->appearance() == CheckboxPart)
+        return isChecked(o);
+
+    // For now assume other controls have tint if enabled.
+    return true;
+}
+
+NSControlSize RenderThemeSafari::controlSizeForFont(RenderStyle* style) const
+{
+    int fontSize = style->fontSize();
+    if (fontSize >= 16)
+        return NSRegularControlSize;
+    if (fontSize >= 11)
+        return NSSmallControlSize;
+    return NSMiniControlSize;
+}
+/*
+void RenderThemeSafari::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize)
+{
+    NSControlSize size;
+    if (minSize.width() >= sizes[NSRegularControlSize].width() &&
+        minSize.height() >= sizes[NSRegularControlSize].height())
+        size = NSRegularControlSize;
+    else if (minSize.width() >= sizes[NSSmallControlSize].width() &&
+             minSize.height() >= sizes[NSSmallControlSize].height())
+        size = NSSmallControlSize;
+    else
+        size = NSMiniControlSize;
+    if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
+        [cell setControlSize:size];
+}
+*/
+IntSize RenderThemeSafari::sizeForFont(RenderStyle* style, const IntSize* sizes) const
+{
+    return sizes[controlSizeForFont(style)];
+}
+
+IntSize RenderThemeSafari::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
+{
+    return sizes[controlSizeForSystemFont(style)];
+}
+
+void RenderThemeSafari::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
+{
+    // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
+    IntSize size = sizeForFont(style, sizes);
+    if (style->width().isIntrinsicOrAuto() && size.width() > 0)
+        style->setWidth(Length(size.width(), Fixed));
+    if (style->height().isAuto() && size.height() > 0)
+        style->setHeight(Length(size.height(), Fixed));
+}
+
+void RenderThemeSafari::setFontFromControlSize(CSSStyleSelector* selector, RenderStyle* style, NSControlSize controlSize) const
+{
+    FontDescription fontDescription;
+    fontDescription.setIsAbsoluteSize(true);
+    fontDescription.setGenericFamily(FontDescription::SerifFamily);
+
+    float fontSize = systemFontSizeForControlSize(controlSize);
+    fontDescription.firstFamily().setFamily("Lucida Grande");
+    fontDescription.setComputedSize(fontSize);
+    fontDescription.setSpecifiedSize(fontSize);
+
+    // Reset line height
+    style->setLineHeight(RenderStyle::initialLineHeight());
+
+    if (style->setFontDescription(fontDescription))
+        style->font().update(selector->fontSelector());
+}
+
+NSControlSize RenderThemeSafari::controlSizeForSystemFont(RenderStyle* style) const
+{
+    int fontSize = style->fontSize();
+    if (fontSize >= 13)
+        return NSRegularControlSize;
+    if (fontSize >= 11)
+        return NSSmallControlSize;
+    return NSMiniControlSize;
+}
+
+bool RenderThemeSafari::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    ASSERT(SafariThemeLibrary());
+
+    NSControlSize controlSize = controlSizeForFont(o->style());
+
+    IntRect inflatedRect = inflateRect(r, checkboxSizes()[controlSize], checkboxMargins(controlSize));  
+    paintThemePart(SafariTheme::CheckboxPart, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o));
+
+    return false;
+}
+
+const IntSize* RenderThemeSafari::checkboxSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(14, 14), IntSize(12, 12), IntSize(10, 10) };
+    return sizes;
+}
+
+const int* RenderThemeSafari::checkboxMargins(NSControlSize controlSize) const
+{
+    static const int margins[3][4] =
+    {
+        { 2, 2, 2, 2 },
+        { 2, 2, 2, 1 },
+        { 1, 0, 0, 0 },
+    };
+    return margins[controlSize];
+}
+
+void RenderThemeSafari::setCheckboxSize(RenderStyle* style) const
+{
+    // If the width and height are both specified, then we have nothing to do.
+    if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+        return;
+
+    // Use the font size to determine the intrinsic width of the control.
+    setSizeFromFont(style, checkboxSizes());
+}
+
+bool RenderThemeSafari::paintRadio(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    ASSERT(SafariThemeLibrary());
+
+    NSControlSize controlSize = controlSizeForFont(o->style());
+ 
+    IntRect inflatedRect = inflateRect(r, radioSizes()[controlSize], radioMargins(controlSize));    
+    paintThemePart(RadioButtonPart, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o));
+
+    return false;
+}
+
+const IntSize* RenderThemeSafari::radioSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(14, 15), IntSize(12, 13), IntSize(10, 10) };
+    return sizes;
+}
+
+const int* RenderThemeSafari::radioMargins(NSControlSize controlSize) const
+{
+    static const int margins[3][4] =
+    {
+        { 1, 2, 2, 2 },
+        { 0, 1, 2, 1 },
+        { 0, 0, 1, 0 },
+     };
+    return margins[controlSize];
+}
+
+void RenderThemeSafari::setRadioSize(RenderStyle* style) const
+{
+    // If the width and height are both specified, then we have nothing to do.
+    if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+        return;
+
+    // Use the font size to determine the intrinsic width of the control.
+    setSizeFromFont(style, radioSizes());
+}
+
+void RenderThemeSafari::setButtonPaddingFromControlSize(RenderStyle* style, NSControlSize size) const
+{
+    // Just use 8px.  AppKit wants to use 11px for mini buttons, but that padding is just too large
+    // for real-world Web sites (creating a huge necessary minimum width for buttons whose space is
+    // by definition constrained, since we select mini only for small cramped environments.
+    // This also guarantees the HTML4 <button> will match our rendering by default, since we're using a consistent
+    // padding.
+    const int padding = 8;
+    style->setPaddingLeft(Length(padding, Fixed));
+    style->setPaddingRight(Length(padding, Fixed));
+    style->setPaddingTop(Length(0, Fixed));
+    style->setPaddingBottom(Length(0, Fixed));
+}
+
+void RenderThemeSafari::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    // There are three appearance constants for buttons.
+    // (1) Push-button is the constant for the default Aqua system button.  Push buttons will not scale vertically and will not allow
+    // custom fonts or colors.  <input>s use this constant.  This button will allow custom colors and font weights/variants but won't
+    // scale vertically.
+    // (2) square-button is the constant for the square button.  This button will allow custom fonts and colors and will scale vertically.
+    // (3) Button is the constant that means "pick the best button as appropriate."  <button>s use this constant.  This button will
+    // also scale vertically and allow custom fonts and colors.  It will attempt to use Aqua if possible and will make this determination
+    // solely on the rectangle of the control.
+
+    // Determine our control size based off our font.
+    NSControlSize controlSize = controlSizeForFont(style);
+
+    if (style->appearance() == PushButtonPart) {
+        // Ditch the border.
+        style->resetBorder();
+
+        // Height is locked to auto.
+        style->setHeight(Length(Auto));
+
+        // White-space is locked to pre
+        style->setWhiteSpace(PRE);
+
+        // Set the button's vertical size.
+        setButtonSize(style);
+
+        // Add in the padding that we'd like to use.
+        setButtonPaddingFromControlSize(style, controlSize);
+
+        // Our font is locked to the appropriate system font size for the control.  To clarify, we first use the CSS-specified font to figure out
+        // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
+        // system font for the control size instead.
+        setFontFromControlSize(selector, style, controlSize);
+    } else {
+        // Set a min-height so that we can't get smaller than the mini button.
+        style->setMinHeight(Length(15, Fixed));
+
+        // Reset the top and bottom borders.
+        style->resetBorderTop();
+        style->resetBorderBottom();
+    }
+}
+
+const IntSize* RenderThemeSafari::buttonSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
+    return sizes;
+}
+
+const int* RenderThemeSafari::buttonMargins(NSControlSize controlSize) const
+{
+    static const int margins[3][4] =
+    {
+        { 4, 6, 7, 6 },
+        { 4, 5, 6, 5 },
+        { 0, 1, 1, 1 },
+    };
+    return margins[controlSize];
+}
+
+void RenderThemeSafari::setButtonSize(RenderStyle* style) const
+{
+    // If the width and height are both specified, then we have nothing to do.
+    if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+        return;
+
+    // Use the font size to determine the intrinsic width of the control.
+    setSizeFromFont(style, buttonSizes());
+}
+
+bool RenderThemeSafari::paintButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    ASSERT(SafariThemeLibrary());
+
+    // We inflate the rect as needed to account for padding included in the cell to accommodate the button
+    // shadow.  We don't consider this part of the bounds of the control in WebKit.
+
+    NSControlSize controlSize = controlSizeFromRect(r, buttonSizes());
+    IntRect inflatedRect = r;
+
+    ThemePart part;
+    if (r.height() <= buttonSizes()[NSRegularControlSize].height()) {
+        // Push button
+        part = SafariTheme::PushButtonPart;
+
+        IntSize size = buttonSizes()[controlSize];
+        size.setWidth(r.width());
+
+        // Center the button within the available space.
+        if (inflatedRect.height() > size.height()) {
+            inflatedRect.setY(inflatedRect.y() + (inflatedRect.height() - size.height()) / 2);
+            inflatedRect.setHeight(size.height());
+        }
+
+        // Now inflate it to account for the shadow.
+        inflatedRect = inflateRect(inflatedRect, size, buttonMargins(controlSize));
+    } else
+        part = SafariTheme::SquareButtonPart;
+
+    paintThemePart(part, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o));
+    return false;
+}
+
+bool RenderThemeSafari::paintTextField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    ASSERT(SafariThemeLibrary());
+
+    paintThemePart(SafariTheme::TextFieldPart, paintInfo.context->platformContext(), r, (NSControlSize)0, determineState(o) & ~FocusedState);
+    return false;
+}
+
+void RenderThemeSafari::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderThemeSafari::paintCapsLockIndicator(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{    
+#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 1
+    ASSERT(SafariThemeLibrary());
+
+    if (paintInfo.context->paintingDisabled())
+        return true;
+
+    paintThemePart(CapsLockPart, paintInfo.context->platformContext(), r, (NSControlSize)0, (ThemeControlState)0);
+
+    return false;
+#else
+    return true;
+#endif
+}
+
+bool RenderThemeSafari::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    ASSERT(SafariThemeLibrary());
+
+    paintThemePart(SafariTheme::TextAreaPart, paintInfo.context->platformContext(), r, (NSControlSize)0, determineState(o) & ~FocusedState);
+    return false;
+}
+
+void RenderThemeSafari::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+{
+}
+
+const int* RenderThemeSafari::popupButtonMargins(NSControlSize size) const
+{
+    static const int margins[3][4] =
+    {
+        { 2, 3, 3, 3 },
+        { 1, 3, 3, 3 },
+        { 0, 1, 0, 1 }
+    };
+    return margins[size];
+}
+
+const IntSize* RenderThemeSafari::popupButtonSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
+    return sizes;
+}
+
+const int* RenderThemeSafari::popupButtonPadding(NSControlSize size) const
+{
+    static const int padding[3][4] =
+    {
+        { 2, 26, 3, 8 },
+        { 2, 23, 3, 8 },
+        { 2, 22, 3, 10 }
+    };
+    return padding[size];
+}
+
+bool RenderThemeSafari::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& info, const IntRect& r)
+{
+    ASSERT(SafariThemeLibrary());
+
+    NSControlSize controlSize = controlSizeFromRect(r, popupButtonSizes());
+    IntRect inflatedRect = r;
+    IntSize size = popupButtonSizes()[controlSize];
+    size.setWidth(r.width());
+
+    // Now inflate it to account for the shadow.
+    if (r.width() >= minimumMenuListSize(o->style()))
+        inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(controlSize));
+
+    paintThemePart(DropDownButtonPart, info.context->platformContext(), inflatedRect, controlSize, determineState(o));
+
+    return false;
+}
+
+const float baseFontSize = 11.0f;
+const float baseArrowHeight = 5.0f;
+const float baseArrowWidth = 7.0f;
+const int arrowPaddingLeft = 5;
+const int arrowPaddingRight = 5;
+const int paddingBeforeSeparator = 4;
+const int baseBorderRadius = 5;
+const int styledPopupPaddingLeft = 8;
+const int styledPopupPaddingTop = 1;
+const int styledPopupPaddingBottom = 2;
+
+static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+    static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
+    static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
+    float a = inData[0];
+    int i = 0;
+    for (i = 0; i < 4; i++)
+        outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+    static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
+    static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
+    float a = inData[0];
+    int i = 0;
+    for (i = 0; i < 4; i++)
+        outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+    static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
+    static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+    float a = inData[0];
+    int i = 0;
+    for (i = 0; i < 4; i++)
+        outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+    static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
+    static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
+    float a = inData[0];
+    int i = 0;
+    for (i = 0; i < 4; i++)
+        outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+void RenderThemeSafari::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    CGContextRef context = paintInfo.context->platformContext();
+
+    paintInfo.context->save();
+
+    int radius = o->style()->borderTopLeftRadius().width();
+
+    RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+
+    FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
+    struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
+    RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
+    RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.bottom()), topFunction.get(), false, false));
+
+    FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
+    struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
+    RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
+    RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(bottomGradient.x(),  bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.bottom()), bottomFunction.get(), false, false));
+
+    struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
+    RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
+    RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x(), r.bottom()), mainFunction.get(), false, false));
+
+    RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
+
+    RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(),  r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false));
+    paintInfo.context->save();
+    CGContextClipToRect(context, r);
+    paintInfo.context->addRoundedRectClip(r,
+        o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
+        o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
+    CGContextDrawShading(context, mainShading.get());
+    paintInfo.context->restore();
+
+    paintInfo.context->save();
+    CGContextClipToRect(context, topGradient);
+    paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient),
+        o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
+        IntSize(), IntSize());
+    CGContextDrawShading(context, topShading.get());
+    paintInfo.context->restore();
+
+    paintInfo.context->save();
+    CGContextClipToRect(context, bottomGradient);
+    paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient),
+        IntSize(), IntSize(),
+        o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
+    CGContextDrawShading(context, bottomShading.get());
+    paintInfo.context->restore();
+
+    paintInfo.context->save();
+    CGContextClipToRect(context, r);
+    paintInfo.context->addRoundedRectClip(r,
+        o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
+        o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
+    CGContextDrawShading(context, leftShading.get());
+    CGContextDrawShading(context, rightShading.get());
+    paintInfo.context->restore();
+
+    paintInfo.context->restore();
+}
+
+bool RenderThemeSafari::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    paintInfo.context->save();
+
+    IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
+                             r.y() + o->style()->borderTopWidth(),
+                             r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
+                             r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
+    // Draw the gradients to give the styled popup menu a button appearance
+    paintMenuListButtonGradients(o, paintInfo, bounds);
+    
+    // Since we actually know the size of the control here, we restrict the font scale to make sure the arrow will fit vertically in the bounds
+    float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / baseArrowHeight);
+    float centerY = bounds.y() + bounds.height() / 2.0f;
+    float arrowHeight = baseArrowHeight * fontScale;
+    float arrowWidth = baseArrowWidth * fontScale;
+    float leftEdge = bounds.right() - arrowPaddingRight - arrowWidth;
+
+    if (bounds.width() < arrowWidth + arrowPaddingLeft)
+        return false;
+
+    paintInfo.context->setFillColor(o->style()->color());
+    paintInfo.context->setStrokeColor(NoStroke);
+
+    FloatPoint arrow[3];
+    arrow[0] = FloatPoint(leftEdge, centerY - arrowHeight / 2.0f);
+    arrow[1] = FloatPoint(leftEdge + arrowWidth, centerY - arrowHeight / 2.0f);
+    arrow[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + arrowHeight / 2.0f);
+
+    // Draw the arrow
+    paintInfo.context->drawConvexPolygon(3, arrow, true);
+
+    Color leftSeparatorColor(0, 0, 0, 40);
+    Color rightSeparatorColor(255, 255, 255, 40);
+    
+    // FIXME: Should the separator thickness and space be scaled up by fontScale?
+    int separatorSpace = 2;
+    int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft); // FIXME: Round?
+
+    // Draw the separator to the left of the arrows
+    paintInfo.context->setStrokeThickness(1.0f);
+    paintInfo.context->setStrokeStyle(SolidStroke);
+    paintInfo.context->setStrokeColor(leftSeparatorColor);
+    paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
+                                IntPoint(leftEdgeOfSeparator, bounds.bottom()));
+
+    paintInfo.context->setStrokeColor(rightSeparatorColor);
+    paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
+                                IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom()));
+
+    paintInfo.context->restore();
+    return false;
+}
+
+void RenderThemeSafari::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    NSControlSize controlSize = controlSizeForFont(style);
+
+    style->resetBorder();
+    style->resetPadding();
+    
+    // Height is locked to auto.
+    style->setHeight(Length(Auto));
+
+    // White-space is locked to pre
+    style->setWhiteSpace(PRE);
+
+    // Set the foreground color to black or gray when we have the aqua look.
+    // Cast to RGB32 is to work around a compiler bug.
+    style->setColor(e->isEnabled() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
+
+    // Set the button's vertical size.
+    setButtonSize(style);
+
+    // Our font is locked to the appropriate system font size for the control.  To clarify, we first use the CSS-specified font to figure out
+    // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
+    // system font for the control size instead.
+    setFontFromControlSize(selector, style, controlSize);
+}
+
+int RenderThemeSafari::popupInternalPaddingLeft(RenderStyle* style) const
+{
+    if (style->appearance() == MenulistPart)
+        return popupButtonPadding(controlSizeForFont(style))[leftPadding];
+    if (style->appearance() == MenulistButtonPart)
+        return styledPopupPaddingLeft;
+    return 0;
+}
+
+int RenderThemeSafari::popupInternalPaddingRight(RenderStyle* style) const
+{
+    if (style->appearance() == MenulistPart)
+        return popupButtonPadding(controlSizeForFont(style))[rightPadding];
+    if (style->appearance() == MenulistButtonPart) {
+        float fontScale = style->fontSize() / baseFontSize;
+        float arrowWidth = baseArrowWidth * fontScale;
+        return static_cast<int>(ceilf(arrowWidth + arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator));
+    }
+    return 0;
+}
+
+int RenderThemeSafari::popupInternalPaddingTop(RenderStyle* style) const
+{
+    if (style->appearance() == MenulistPart)
+        return popupButtonPadding(controlSizeForFont(style))[topPadding];
+    if (style->appearance() == MenulistButtonPart)
+        return styledPopupPaddingTop;
+    return 0;
+}
+
+int RenderThemeSafari::popupInternalPaddingBottom(RenderStyle* style) const
+{
+    if (style->appearance() == MenulistPart)
+        return popupButtonPadding(controlSizeForFont(style))[bottomPadding];
+    if (style->appearance() == MenulistButtonPart)
+        return styledPopupPaddingBottom;
+    return 0;
+}
+
+void RenderThemeSafari::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    float fontScale = style->fontSize() / baseFontSize;
+    
+    style->resetPadding();
+    style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
+
+    const int minHeight = 15;
+    style->setMinHeight(Length(minHeight, Fixed));
+    
+    style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+const IntSize* RenderThemeSafari::menuListSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
+    return sizes;
+}
+
+int RenderThemeSafari::minimumMenuListSize(RenderStyle* style) const
+{
+    return sizeForSystemFont(style, menuListSizes()).width();
+}
+
+const int trackWidth = 5;
+const int trackRadius = 2;
+
+bool RenderThemeSafari::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    IntRect bounds = r;
+
+    if (o->style()->appearance() ==  SliderHorizontalPart || 
+        o->style()->appearance() == MediaSliderPart) {
+        bounds.setHeight(trackWidth);
+        bounds.setY(r.y() + r.height() / 2 - trackWidth / 2);
+    } else if (o->style()->appearance() == SliderVerticalPart) {
+        bounds.setWidth(trackWidth);
+        bounds.setX(r.x() + r.width() / 2 - trackWidth / 2);
+    }
+
+    CGContextRef context = paintInfo.context->platformContext();
+    RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+
+    paintInfo.context->save();
+    CGContextClipToRect(context, bounds);
+
+    struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
+    RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
+    RetainPtr<CGShadingRef> mainShading;
+    if (o->style()->appearance() == SliderVerticalPart)
+        mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.bottom()), CGPointMake(bounds.right(), bounds.bottom()), mainFunction.get(), false, false));
+    else
+        mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.y()), CGPointMake(bounds.x(), bounds.bottom()), mainFunction.get(), false, false));
+
+    IntSize radius(trackRadius, trackRadius);
+    paintInfo.context->addRoundedRectClip(bounds,
+        radius, radius,
+        radius, radius);
+    CGContextDrawShading(context, mainShading.get());
+    paintInfo.context->restore();
+    
+    return false;
+}
+
+void RenderThemeSafari::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const 
+{ 
+    style->setBoxShadow(0); 
+} 
+
+const float verticalSliderHeightPadding = 0.1f;
+
+bool RenderThemeSafari::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    ASSERT(SafariThemeLibrary());
+
+    ASSERT(o->parent()->isSlider());
+
+    bool pressed = static_cast<RenderSlider*>(o->parent())->inDragMode();
+    ThemeControlState state = determineState(o->parent());
+    state &= ~SafariTheme::PressedState;
+    if (pressed)
+        state |= SafariTheme::PressedState;
+
+    paintThemePart(SliderThumbPart, paintInfo.context->platformContext(), r, NSSmallControlSize, state);
+    return false;
+}
+
+const int sliderThumbWidth = 15;
+const int sliderThumbHeight = 15;
+const int mediaSliderThumbWidth = 13;
+const int mediaSliderThumbHeight = 14;
+
+void RenderThemeSafari::adjustSliderThumbSize(RenderObject* o) const
+{
+    if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) {
+        o->style()->setWidth(Length(sliderThumbWidth, Fixed));
+        o->style()->setHeight(Length(sliderThumbHeight, Fixed));
+    } else if (o->style()->appearance() == MediaSliderThumbPart) {
+        o->style()->setWidth(Length(mediaSliderThumbWidth, Fixed));
+        o->style()->setHeight(Length(mediaSliderThumbHeight, Fixed));
+    }
+
+}
+
+bool RenderThemeSafari::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    ASSERT(SafariThemeLibrary());
+
+    paintThemePart(SafariTheme::SearchFieldPart, paintInfo.context->platformContext(), r, controlSizeFromRect(r, searchFieldSizes()), determineState(o));
+    return false;
+}
+
+const IntSize* RenderThemeSafari::searchFieldSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 15) };
+    return sizes;
+}
+
+void RenderThemeSafari::setSearchFieldSize(RenderStyle* style) const
+{
+    // If the width and height are both specified, then we have nothing to do.
+    if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+        return;
+    
+    // Use the font size to determine the intrinsic width of the control.
+    setSizeFromFont(style, searchFieldSizes());
+}
+
+void RenderThemeSafari::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    // Override border.
+    style->resetBorder();
+    const short borderWidth = 2;
+    style->setBorderLeftWidth(borderWidth);
+    style->setBorderLeftStyle(INSET);
+    style->setBorderRightWidth(borderWidth);
+    style->setBorderRightStyle(INSET);
+    style->setBorderBottomWidth(borderWidth);
+    style->setBorderBottomStyle(INSET);
+    style->setBorderTopWidth(borderWidth);
+    style->setBorderTopStyle(INSET);    
+    
+    // Override height.
+    style->setHeight(Length(Auto));
+    setSearchFieldSize(style);
+    
+    // Override padding size to match AppKit text positioning.
+    const int padding = 1;
+    style->setPaddingLeft(Length(padding, Fixed));
+    style->setPaddingRight(Length(padding, Fixed));
+    style->setPaddingTop(Length(padding, Fixed));
+    style->setPaddingBottom(Length(padding, Fixed));
+    
+    NSControlSize controlSize = controlSizeForFont(style);
+    setFontFromControlSize(selector, style, controlSize);
+}
+
+bool RenderThemeSafari::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect&)
+{
+    ASSERT(SafariThemeLibrary());
+
+    Node* input = o->node()->shadowAncestorNode();
+    ASSERT(input);
+    RenderObject* renderer = input->renderer();
+    ASSERT(renderer);
+
+    IntRect searchRect = renderer->absoluteBoundingBoxRect();
+
+    paintThemePart(SafariTheme::SearchFieldCancelButtonPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o));
+    return false;
+}
+
+const IntSize* RenderThemeSafari::cancelButtonSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
+    return sizes;
+}
+
+void RenderThemeSafari::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize size = sizeForSystemFont(style, cancelButtonSizes());
+    style->setWidth(Length(size.width(), Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+}
+
+const IntSize* RenderThemeSafari::resultsButtonSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
+    return sizes;
+}
+
+const int emptyResultsOffset = 9;
+void RenderThemeSafari::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+    style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+}
+
+bool RenderThemeSafari::paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&)
+{
+    return false;
+}
+
+void RenderThemeSafari::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+    style->setWidth(Length(size.width(), Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+}
+
+bool RenderThemeSafari::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect&)
+{
+    ASSERT(SafariThemeLibrary());
+
+    Node* input = o->node()->shadowAncestorNode();
+    ASSERT(input);
+    RenderObject* renderer = input->renderer();
+    ASSERT(renderer);
+
+    IntRect searchRect = renderer->absoluteBoundingBoxRect();
+
+    paintThemePart(SafariTheme::SearchFieldResultsDecorationPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o));
+    return false;
+}
+
+const int resultsArrowWidth = 5;
+void RenderThemeSafari::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+    style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+}
+
+bool RenderThemeSafari::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect&)
+{
+    ASSERT(SafariThemeLibrary());
+
+    Node* input = o->node()->shadowAncestorNode();
+    ASSERT(input);
+    RenderObject* renderer = input->renderer();
+    ASSERT(renderer);
+
+    IntRect searchRect = renderer->absoluteBoundingBoxRect();
+
+    paintThemePart(SafariTheme::SearchFieldResultsButtonPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o));
+    return false;
+}
+#if ENABLE(VIDEO)
+bool RenderThemeSafari::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
+    ASSERT(SafariThemeLibrary());
+    paintThemePart(SafariTheme::MediaFullscreenButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+#endif
+
+    return false;
+}
+
+bool RenderThemeSafari::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* node = o->element();
+    Node* mediaNode = node ? node->shadowAncestorNode() : 0;
+    if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
+        return false;
+
+    HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
+    if (!mediaElement)
+        return false;
+
+#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
+    ASSERT(SafariThemeLibrary());
+    paintThemePart(mediaElement->muted() ? SafariTheme::MediaUnMuteButtonPart : SafariTheme::MediaMuteButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+#endif
+
+    return false;
+}
+
+bool RenderThemeSafari::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* node = o->element();
+    Node* mediaNode = node ? node->shadowAncestorNode() : 0;
+    if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
+        return false;
+
+    HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
+    if (!mediaElement)
+        return false;
+
+#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
+    ASSERT(SafariThemeLibrary());
+    paintThemePart(mediaElement->canPlay() ? SafariTheme::MediaPlayButtonPart : SafariTheme::MediaPauseButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+#endif
+
+    return false;
+}
+
+bool RenderThemeSafari::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
+    ASSERT(SafariThemeLibrary());
+    paintThemePart(SafariTheme::MediaSeekBackButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+#endif
+
+    return false;
+}
+
+bool RenderThemeSafari::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
+    ASSERT(SafariThemeLibrary());
+    paintThemePart(SafariTheme::MediaSeekForwardButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+#endif
+
+    return false;
+}
+
+bool RenderThemeSafari::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* node = o->element();
+    Node* mediaNode = node ? node->shadowAncestorNode() : 0;
+    if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
+        return false;
+
+    HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
+    if (!mediaElement)
+        return false;
+
+    float percentLoaded = 0;
+    if (MediaPlayer* player = mediaElement->player())
+        if (player->duration())
+            percentLoaded = player->maxTimeBuffered() / player->duration();
+
+#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
+    ASSERT(SafariThemeLibrary());
+    STPaintProgressIndicator(SafariTheme::MediaType, paintInfo.context->platformContext(), r, NSRegularControlSize, 0, percentLoaded);
+#endif
+    return false;
+}
+
+bool RenderThemeSafari::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    ASSERT(SafariThemeLibrary());
+
+#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
+    paintThemePart(SafariTheme::MediaSliderThumbPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+#endif
+
+    return false;
+}
+#endif
+
+} // namespace WebCore
+
+#endif // #if USE(SAFARI_THEME)
diff --git a/WebCore/rendering/RenderThemeSafari.h b/WebCore/rendering/RenderThemeSafari.h
new file mode 100644
index 0000000..8ac5acf
--- /dev/null
+++ b/WebCore/rendering/RenderThemeSafari.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2007, 2008 Apple 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderThemeSafari_h
+#define RenderThemeSafari_h
+
+#if USE(SAFARI_THEME)
+
+#include "RenderTheme.h"
+
+// If you have an empty placeholder SafariThemeConstants.h, then include SafariTheme.h
+// This is a workaround until a version of WebKitSupportLibrary is released with an updated SafariThemeConstants.h 
+#include <SafariTheme/SafariThemeConstants.h>
+#ifndef SafariThemeConstants_h
+#include <SafariTheme/SafariTheme.h>
+#endif
+
+#if PLATFORM(WIN)
+typedef void* HANDLE;
+typedef struct HINSTANCE__* HINSTANCE;
+typedef HINSTANCE HMODULE;
+#endif
+
+namespace WebCore {
+
+using namespace SafariTheme;
+
+class RenderStyle;
+
+class RenderThemeSafari : public RenderTheme {
+public:
+    RenderThemeSafari();
+    virtual ~RenderThemeSafari();
+
+    // A method to obtain the baseline position for a "leaf" control.  This will only be used if a baseline
+    // position cannot be determined by examining child content. Checkboxes and radio buttons are examples of
+    // controls that need to do this.
+    virtual int baselinePosition(const RenderObject*) const;
+
+    // A method asking if the control changes its tint when the window has focus or not.
+    virtual bool controlSupportsTints(const RenderObject*) const;
+
+    // A general method asking if any control tinting is supported at all.
+    virtual bool supportsControlTints() const { return true; }
+
+    virtual void adjustRepaintRect(const RenderObject*, IntRect&);
+
+    virtual bool isControlStyled(const RenderStyle*, const BorderData&,
+                                 const FillLayer&, const Color& backgroundColor) const;
+
+    virtual Color platformActiveSelectionBackgroundColor() const;
+    virtual Color platformInactiveSelectionBackgroundColor() const;
+    virtual Color activeListBoxSelectionBackgroundColor() const;
+
+    // System fonts.
+    virtual void systemFont(int propId, FontDescription&) const;
+
+    virtual int minimumMenuListSize(RenderStyle*) const;
+
+    virtual void adjustSliderThumbSize(RenderObject*) const;
+    virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const; 
+    
+    virtual int popupInternalPaddingLeft(RenderStyle*) const;
+    virtual int popupInternalPaddingRight(RenderStyle*) const;
+    virtual int popupInternalPaddingTop(RenderStyle*) const;
+    virtual int popupInternalPaddingBottom(RenderStyle*) const;
+
+protected:
+    // Methods for each appearance value.
+    virtual bool paintCheckbox(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void setCheckboxSize(RenderStyle*) const;
+
+    virtual bool paintRadio(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void setRadioSize(RenderStyle*) const;
+
+    virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, WebCore::Element*) const;
+    virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void setButtonSize(RenderStyle*) const;
+
+    virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+    virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ 
+    virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+#if ENABLE(VIDEO)
+    virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSeekBackButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+#endif
+
+private:
+    IntRect inflateRect(const IntRect&, const IntSize&, const int* margins) const;
+
+    // Get the control size based off the font.  Used by some of the controls (like buttons).
+
+    NSControlSize controlSizeForFont(RenderStyle*) const;
+    NSControlSize controlSizeForSystemFont(RenderStyle*) const;
+    //void setControlSize(NSCell*, const IntSize* sizes, const IntSize& minSize);
+    void setSizeFromFont(RenderStyle*, const IntSize* sizes) const;
+    IntSize sizeForFont(RenderStyle*, const IntSize* sizes) const;
+    IntSize sizeForSystemFont(RenderStyle*, const IntSize* sizes) const;
+    void setFontFromControlSize(CSSStyleSelector*, RenderStyle*, NSControlSize) const;
+
+    // Helpers for adjusting appearance and for painting
+    const IntSize* checkboxSizes() const;
+    const int* checkboxMargins(NSControlSize) const;
+
+    const IntSize* radioSizes() const;
+    const int* radioMargins(NSControlSize) const;
+
+    void setButtonPaddingFromControlSize(RenderStyle*, NSControlSize) const;
+    const IntSize* buttonSizes() const;
+    const int* buttonMargins(NSControlSize) const;
+
+    const IntSize* popupButtonSizes() const;
+    const int* popupButtonMargins(NSControlSize) const;
+    const int* popupButtonPadding(NSControlSize) const;
+    void paintMenuListButtonGradients(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    const IntSize* menuListSizes() const;
+
+    const IntSize* searchFieldSizes() const;
+    const IntSize* cancelButtonSizes() const;
+    const IntSize* resultsButtonSizes() const;
+    void setSearchFieldSize(RenderStyle*) const;
+
+    ThemeControlState determineState(RenderObject*) const;
+};
+
+} // namespace WebCore
+
+#endif // #if USE(SAFARI_THEME)
+
+#endif // RenderThemeSafari_h
diff --git a/WebCore/rendering/RenderThemeWin.cpp b/WebCore/rendering/RenderThemeWin.cpp
new file mode 100644
index 0000000..14dcbf1
--- /dev/null
+++ b/WebCore/rendering/RenderThemeWin.cpp
@@ -0,0 +1,810 @@
+/*
+ * Copyright (C) 2006, 2007 Apple 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, or (at your option) any later version.
+ *
+ * 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 "RenderThemeWin.h"
+
+#include "CSSValueKeywords.h"
+#include "Document.h"
+#include "GraphicsContext.h"
+#include "HTMLElement.h"
+#include "HTMLSelectElement.h"
+#include "Icon.h"
+#include "RenderSlider.h"
+#include "SoftLinking.h"
+
+#include <tchar.h>
+
+/* 
+ * The following constants are used to determine how a widget is drawn using
+ * Windows' Theme API. For more information on theme parts and states see
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp
+ */
+
+// Generic state constants
+#define TS_NORMAL    1
+#define TS_HOVER     2
+#define TS_ACTIVE    3
+#define TS_DISABLED  4
+#define TS_FOCUSED   5
+
+// Button constants
+#define BP_BUTTON    1
+#define BP_RADIO     2
+#define BP_CHECKBOX  3
+
+// Textfield constants
+#define TFP_TEXTFIELD 1
+#define TFS_READONLY  6
+
+// ComboBox constants (from tmschema.h)
+#define CP_DROPDOWNBUTTON 1
+
+// TrackBar (slider) parts
+#define TKP_TRACK       1
+#define TKP_TRACKVERT   2
+
+// TrackBar (slider) thumb parts
+#define TKP_THUMBBOTTOM 4
+#define TKP_THUMBTOP    5
+#define TKP_THUMBLEFT   7
+#define TKP_THUMBRIGHT  8
+
+// Trackbar (slider) thumb states
+#define TUS_NORMAL      1
+#define TUS_HOT         2
+#define TUS_PRESSED     3
+#define TUS_FOCUSED     4
+#define TUS_DISABLED    5
+
+// button states
+#define PBS_NORMAL      1
+#define PBS_HOT         2
+#define PBS_PRESSED     3
+#define PBS_DISABLED    4
+#define PBS_DEFAULTED   5
+
+// This is the fixed width IE and Firefox use for buttons on dropdown menus
+static const int dropDownButtonWidth = 17;
+
+static const int shell32MagnifierIconIndex = 22;
+
+SOFT_LINK_LIBRARY(uxtheme)
+SOFT_LINK(uxtheme, OpenThemeData, HANDLE, WINAPI, (HWND hwnd, LPCWSTR pszClassList), (hwnd, pszClassList))
+SOFT_LINK(uxtheme, CloseThemeData, HRESULT, WINAPI, (HANDLE hTheme), (hTheme))
+SOFT_LINK(uxtheme, DrawThemeBackground, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc, int iPartId, int iStateId, const RECT* pRect, const RECT* pClipRect), (hTheme, hdc, iPartId, iStateId, pRect, pClipRect))
+SOFT_LINK(uxtheme, IsThemeActive, BOOL, WINAPI, (), ())
+SOFT_LINK(uxtheme, IsThemeBackgroundPartiallyTransparent, BOOL, WINAPI, (HANDLE hTheme, int iPartId, int iStateId), (hTheme, iPartId, iStateId))
+
+static bool haveTheme;
+
+namespace WebCore {
+
+static bool gWebKitIsBeingUnloaded;
+
+void RenderThemeWin::setWebKitIsBeingUnloaded()
+{
+    gWebKitIsBeingUnloaded = true;
+}
+
+#if !USE(SAFARI_THEME)
+RenderTheme* theme()
+{
+    static RenderThemeWin winTheme;
+    return &winTheme;
+}
+#endif
+
+RenderThemeWin::RenderThemeWin()
+    : m_buttonTheme(0)
+    , m_textFieldTheme(0)
+    , m_menuListTheme(0)
+    , m_sliderTheme(0)
+{
+    haveTheme = uxthemeLibrary() && IsThemeActive();
+}
+
+RenderThemeWin::~RenderThemeWin()
+{
+    // If WebKit is being unloaded, then uxtheme.dll is no longer available.
+    if (gWebKitIsBeingUnloaded || !uxthemeLibrary())
+        return;
+    close();
+}
+
+HANDLE RenderThemeWin::buttonTheme() const
+{
+    if (haveTheme && !m_buttonTheme)
+        m_buttonTheme = OpenThemeData(0, L"Button");
+    return m_buttonTheme;
+}
+
+HANDLE RenderThemeWin::textFieldTheme() const
+{
+    if (haveTheme && !m_textFieldTheme)
+        m_textFieldTheme = OpenThemeData(0, L"Edit");
+    return m_textFieldTheme;
+}
+
+HANDLE RenderThemeWin::menuListTheme() const
+{
+    if (haveTheme && !m_menuListTheme)
+        m_menuListTheme = OpenThemeData(0, L"ComboBox");
+    return m_menuListTheme;
+}
+
+HANDLE RenderThemeWin::sliderTheme() const
+{
+    if (haveTheme && !m_sliderTheme)
+        m_sliderTheme = OpenThemeData(0, L"TrackBar");
+    return m_sliderTheme;
+}
+
+void RenderThemeWin::close()
+{
+    // This method will need to be called when the OS theme changes to flush our cached themes.
+    if (m_buttonTheme)
+        CloseThemeData(m_buttonTheme);
+    if (m_textFieldTheme)
+        CloseThemeData(m_textFieldTheme);
+    if (m_menuListTheme)
+        CloseThemeData(m_menuListTheme);
+    if (m_sliderTheme)
+        CloseThemeData(m_sliderTheme);
+    m_buttonTheme = m_textFieldTheme = m_menuListTheme = m_sliderTheme = 0;
+
+    haveTheme = uxthemeLibrary() && IsThemeActive();
+}
+
+void RenderThemeWin::themeChanged()
+{
+    close();
+}
+
+bool RenderThemeWin::supportsHover(const RenderStyle*) const
+{
+    // The Classic/2k look has no hover effects.
+    return haveTheme;
+}
+
+Color RenderThemeWin::platformActiveSelectionBackgroundColor() const
+{
+    COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
+    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+}
+
+Color RenderThemeWin::platformInactiveSelectionBackgroundColor() const
+{
+    COLORREF color = GetSysColor(COLOR_GRAYTEXT);
+    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+}
+
+Color RenderThemeWin::platformActiveSelectionForegroundColor() const
+{
+    COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
+    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+}
+
+Color RenderThemeWin::platformInactiveSelectionForegroundColor() const
+{
+    return Color::white;
+}
+
+static void fillFontDescription(FontDescription& fontDescription, LOGFONT& logFont)
+{    
+    fontDescription.setIsAbsoluteSize(true);
+    fontDescription.setGenericFamily(FontDescription::NoFamily);
+    fontDescription.firstFamily().setFamily(String(logFont.lfFaceName));
+    fontDescription.setSpecifiedSize(abs(logFont.lfHeight));
+    fontDescription.setWeight(logFont.lfWeight >= 700 ? FontWeightBold : FontWeightNormal); // FIXME: Use real weight.
+    fontDescription.setItalic(logFont.lfItalic);
+}
+
+void RenderThemeWin::systemFont(int propId, FontDescription& fontDescription) const
+{
+    static FontDescription captionFont;
+    static FontDescription smallCaptionFont;
+    static FontDescription menuFont;
+    static FontDescription iconFont;
+    static FontDescription messageBoxFont;
+    static FontDescription statusBarFont;
+    static FontDescription systemFont;
+    
+    static bool initialized;
+    static NONCLIENTMETRICS ncm;
+
+    if (!initialized) {
+        initialized = true;
+        ncm.cbSize = sizeof(NONCLIENTMETRICS);
+        ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
+    }
+ 
+    switch (propId) {
+        case CSSValueIcon: {
+            if (!iconFont.isAbsoluteSize()) {
+                LOGFONT logFont;
+                ::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(logFont), &logFont, 0);
+                fillFontDescription(iconFont, logFont);
+            }
+            fontDescription = iconFont;
+            break;
+        }
+        case CSSValueMenu:
+            if (!menuFont.isAbsoluteSize())
+                fillFontDescription(menuFont, ncm.lfMenuFont);
+            fontDescription = menuFont;
+            break;
+        case CSSValueMessageBox:
+            if (!messageBoxFont.isAbsoluteSize())
+                fillFontDescription(messageBoxFont, ncm.lfMessageFont);
+            fontDescription = messageBoxFont;
+            break;
+        case CSSValueStatusBar:
+            if (!statusBarFont.isAbsoluteSize())
+                fillFontDescription(statusBarFont, ncm.lfStatusFont);
+            fontDescription = statusBarFont;
+            break;
+        case CSSValueCaption:
+            if (!captionFont.isAbsoluteSize())
+                fillFontDescription(captionFont, ncm.lfCaptionFont);
+            fontDescription = captionFont;
+            break;
+        case CSSValueSmallCaption:
+        case CSSValueWebkitSmallControl: // Equivalent to small-caption.
+        case CSSValueWebkitMiniControl: // Just map to small.
+        case CSSValueWebkitControl: // Just map to small.
+            if (!smallCaptionFont.isAbsoluteSize())
+                fillFontDescription(smallCaptionFont, ncm.lfSmCaptionFont);
+            fontDescription = smallCaptionFont;
+            break;
+        default: { // Everything else uses the stock GUI font.
+            if (!systemFont.isAbsoluteSize()) {
+                HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT);
+                if (hGDI) {
+                    LOGFONT logFont;
+                    if (::GetObject(hGDI, sizeof(logFont), &logFont) > 0)
+                        fillFontDescription(systemFont, logFont);
+                }
+            }
+            fontDescription = systemFont;
+        }
+    }
+}
+
+bool RenderThemeWin::supportsFocus(ControlPart appearance)
+{
+    switch (appearance) {
+        case PushButtonPart:
+        case ButtonPart:
+        case DefaultButtonPart:
+        case TextFieldPart:
+        case TextAreaPart:
+            return true;
+        case MenulistPart:
+            return false;
+        default:
+            return false;
+    }
+}
+
+unsigned RenderThemeWin::determineClassicState(RenderObject* o)
+{
+    unsigned state = 0;
+    switch (o->style()->appearance()) {
+        case PushButtonPart:
+        case ButtonPart:
+        case DefaultButtonPart:
+            state = DFCS_BUTTONPUSH;
+            if (!isEnabled(o))
+                state |= DFCS_INACTIVE;
+            else if (isPressed(o))
+                state |= DFCS_PUSHED;
+            break;
+        case RadioPart:
+        case CheckboxPart:
+            state = (o->style()->appearance() == RadioPart) ? DFCS_BUTTONRADIO : DFCS_BUTTONCHECK;
+            if (isChecked(o))
+                state |= DFCS_CHECKED;
+            if (!isEnabled(o))
+                state |= DFCS_INACTIVE;
+            else if (isPressed(o))
+                state |= DFCS_PUSHED;
+            break;
+        case MenulistPart:
+            state = DFCS_SCROLLCOMBOBOX;
+            if (!isEnabled(o))
+                state |= DFCS_INACTIVE;
+            else if (isPressed(o))
+                state |= DFCS_PUSHED;
+        default:
+            break;
+    }
+    return state;
+}
+
+unsigned RenderThemeWin::determineState(RenderObject* o)
+{
+    unsigned result = TS_NORMAL;
+    ControlPart appearance = o->style()->appearance();
+    if (!isEnabled(o))
+        result = TS_DISABLED;
+    else if (isReadOnlyControl(o) && (TextFieldPart == appearance || TextAreaPart == appearance))
+        result = TFS_READONLY; // Readonly is supported on textfields.
+    else if (isPressed(o)) // Active overrides hover and focused.
+        result = TS_ACTIVE;
+    else if (supportsFocus(appearance) && isFocused(o))
+        result = TS_FOCUSED;
+    else if (isHovered(o))
+        result = TS_HOVER;
+    if (isChecked(o))
+        result += 4; // 4 unchecked states, 4 checked states.
+    return result;
+}
+
+unsigned RenderThemeWin::determineSliderThumbState(RenderObject* o)
+{
+    unsigned result = TUS_NORMAL;
+    if (!isEnabled(o->parent()))
+        result = TUS_DISABLED;
+    else if (supportsFocus(o->style()->appearance()) && isFocused(o->parent()))
+        result = TUS_FOCUSED;
+    else if (static_cast<RenderSlider*>(o->parent())->inDragMode())
+        result = TUS_PRESSED;
+    else if (isHovered(o))
+        result = TUS_HOT;
+    return result;
+}
+
+unsigned RenderThemeWin::determineButtonState(RenderObject* o)
+{
+    unsigned result = PBS_NORMAL;
+    if (!isEnabled(o))
+        result = PBS_DISABLED;
+    else if (isPressed(o))
+        result = PBS_PRESSED;
+    else if (supportsFocus(o->style()->appearance()) && isFocused(o))
+        result = PBS_DEFAULTED;
+    else if (isHovered(o))
+        result = PBS_HOT;
+    else if (isDefault(o))
+        result = PBS_DEFAULTED;
+    return result;
+}
+
+ThemeData RenderThemeWin::getClassicThemeData(RenderObject* o)
+{
+    ThemeData result;
+    switch (o->style()->appearance()) {
+        case PushButtonPart:
+        case ButtonPart:
+        case DefaultButtonPart:
+        case CheckboxPart:
+        case RadioPart:
+            result.m_part = DFC_BUTTON;
+            result.m_state = determineClassicState(o);
+            break;
+        case MenulistPart:
+            result.m_part = DFC_SCROLL;
+            result.m_state = determineClassicState(o);
+            break;
+        case TextFieldPart:
+        case TextAreaPart:
+            result.m_part = TFP_TEXTFIELD;
+            result.m_state = determineState(o);
+            break;
+        case SliderHorizontalPart:
+            result.m_part = TKP_TRACK;
+            result.m_state = TS_NORMAL;
+            break;
+        case SliderVerticalPart:
+            result.m_part = TKP_TRACKVERT;
+            result.m_state = TS_NORMAL;
+            break;
+        case SliderThumbHorizontalPart:
+            result.m_part = TKP_THUMBBOTTOM;
+            result.m_state = determineSliderThumbState(o);
+            break;
+        case SliderThumbVerticalPart:
+            result.m_part = TKP_THUMBRIGHT;
+            result.m_state = determineSliderThumbState(o);
+            break;
+        default:
+            break;
+    }
+    return result;
+}
+
+ThemeData RenderThemeWin::getThemeData(RenderObject* o)
+{
+    if (!haveTheme)
+        return getClassicThemeData(o);
+
+    ThemeData result;
+    switch (o->style()->appearance()) {
+        case PushButtonPart:
+        case ButtonPart:
+        case DefaultButtonPart:
+            result.m_part = BP_BUTTON;
+            result.m_state = determineButtonState(o);
+            break;
+        case CheckboxPart:
+            result.m_part = BP_CHECKBOX;
+            result.m_state = determineState(o);
+            break;
+        case MenulistPart:
+        case MenulistButtonPart:
+            result.m_part = CP_DROPDOWNBUTTON;
+            result.m_state = determineState(o);
+            break;
+        case RadioPart:
+            result.m_part = BP_RADIO;
+            result.m_state = determineState(o);
+            break;
+        case TextFieldPart:
+        case TextAreaPart:
+            result.m_part = TFP_TEXTFIELD;
+            result.m_state = determineState(o);
+            break;
+        case SliderHorizontalPart:
+            result.m_part = TKP_TRACK;
+            result.m_state = TS_NORMAL;
+            break;
+        case SliderVerticalPart:
+            result.m_part = TKP_TRACKVERT;
+            result.m_state = TS_NORMAL;
+            break;
+        case SliderThumbHorizontalPart:
+            result.m_part = TKP_THUMBBOTTOM;
+            result.m_state = determineSliderThumbState(o);
+            break;
+        case SliderThumbVerticalPart:
+            result.m_part = TKP_THUMBRIGHT;
+            result.m_state = determineSliderThumbState(o);
+            break;
+    }
+
+    return result;
+}
+
+static void drawControl(GraphicsContext* context, RenderObject* o, HANDLE theme, const ThemeData& themeData, const IntRect& r)
+{
+    bool alphaBlend = false;
+    if (theme)
+        alphaBlend = IsThemeBackgroundPartiallyTransparent(theme, themeData.m_part, themeData.m_state);
+    HDC hdc = context->getWindowsContext(r, alphaBlend);
+    RECT widgetRect = r;
+    if (theme)
+        DrawThemeBackground(theme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL);
+    else {
+        if (themeData.m_part == TFP_TEXTFIELD) {
+            ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
+            if (themeData.m_state == TS_DISABLED || themeData.m_state ==  TFS_READONLY)
+                ::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_BTNFACE+1));
+            else
+                ::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_WINDOW+1));
+        } else if (themeData.m_part == TKP_TRACK || themeData.m_part == TKP_TRACKVERT) {
+            ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
+            ::FillRect(hdc, &widgetRect, (HBRUSH)GetStockObject(GRAY_BRUSH));
+        } else if ((o->style()->appearance() == SliderThumbHorizontalPart ||
+                    o->style()->appearance() == SliderThumbVerticalPart) && 
+                   (themeData.m_part == TKP_THUMBBOTTOM || themeData.m_part == TKP_THUMBTOP || 
+                    themeData.m_part == TKP_THUMBLEFT || themeData.m_part == TKP_THUMBRIGHT)) {
+            ::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
+            if (themeData.m_state == TUS_DISABLED) {
+                static WORD patternBits[8] = {0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55};
+                HBITMAP patternBmp = ::CreateBitmap(8, 8, 1, 1, patternBits);
+                if (patternBmp) {
+                    HBRUSH brush = (HBRUSH) ::CreatePatternBrush(patternBmp);
+                    COLORREF oldForeColor = ::SetTextColor(hdc, ::GetSysColor(COLOR_3DFACE));
+                    COLORREF oldBackColor = ::SetBkColor(hdc, ::GetSysColor(COLOR_3DHILIGHT));
+                    POINT p;
+                    ::GetViewportOrgEx(hdc, &p);
+                    ::SetBrushOrgEx(hdc, p.x + widgetRect.left, p.y + widgetRect.top, NULL);
+                    HBRUSH oldBrush = (HBRUSH) ::SelectObject(hdc, brush);
+                    ::FillRect(hdc, &widgetRect, brush);
+                    ::SetTextColor(hdc, oldForeColor);
+                    ::SetBkColor(hdc, oldBackColor);
+                    ::SelectObject(hdc, oldBrush);
+                    ::DeleteObject(brush); 
+                } else
+                    ::FillRect(hdc, &widgetRect, (HBRUSH)COLOR_3DHILIGHT);
+                ::DeleteObject(patternBmp);
+            }
+        } else {
+            // Push buttons, buttons, checkboxes and radios, and the dropdown arrow in menulists.
+            if (o->style()->appearance() == DefaultButtonPart) {
+                HBRUSH brush = ::GetSysColorBrush(COLOR_3DDKSHADOW);
+                ::FrameRect(hdc, &widgetRect, brush);
+                ::InflateRect(&widgetRect, -1, -1);
+                ::DrawEdge(hdc, &widgetRect, BDR_RAISEDOUTER, BF_RECT | BF_MIDDLE);
+            }
+            ::DrawFrameControl(hdc, &widgetRect, themeData.m_part, themeData.m_state);
+        }
+    }
+    context->releaseWindowsContext(hdc, r, alphaBlend);
+}
+
+bool RenderThemeWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{  
+    drawControl(i.context,  o, buttonTheme(), getThemeData(o), r);
+    return false;
+}
+
+void RenderThemeWin::setCheckboxSize(RenderStyle* style) const
+{
+    // If the width and height are both specified, then we have nothing to do.
+    if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+        return;
+
+    // FIXME:  A hard-coded size of 13 is used.  This is wrong but necessary for now.  It matches Firefox.
+    // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for
+    // the higher DPI.  Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's
+    // metrics.
+    if (style->width().isIntrinsicOrAuto())
+        style->setWidth(Length(13, Fixed));
+    if (style->height().isAuto())
+        style->setHeight(Length(13, Fixed));
+}
+
+bool RenderThemeWin::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+    drawControl(i.context,  o, textFieldTheme(), getThemeData(o), r);
+    return false;
+}
+
+bool RenderThemeWin::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+    // The outer box of a menu list is just a text field.  Paint it first.
+    drawControl(i.context,  o, textFieldTheme(), ThemeData(TFP_TEXTFIELD, determineState(o)), r);
+    
+    return paintMenuListButton(o, i, r);
+}
+
+void RenderThemeWin::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    style->resetBorder();
+    adjustMenuListButtonStyle(selector, style, e);
+}
+
+void RenderThemeWin::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    // These are the paddings needed to place the text correctly in the <select> box
+    const int dropDownBoxPaddingTop    = 2;
+    const int dropDownBoxPaddingRight  = style->direction() == LTR ? 4 + dropDownButtonWidth : 4;
+    const int dropDownBoxPaddingBottom = 2;
+    const int dropDownBoxPaddingLeft   = style->direction() == LTR ? 4 : 4 + dropDownButtonWidth;
+    // The <select> box must be at least 12px high for the button to render nicely on Windows
+    const int dropDownBoxMinHeight = 12;
+    
+    // Position the text correctly within the select box and make the box wide enough to fit the dropdown button
+    style->setPaddingTop(Length(dropDownBoxPaddingTop, Fixed));
+    style->setPaddingRight(Length(dropDownBoxPaddingRight, Fixed));
+    style->setPaddingBottom(Length(dropDownBoxPaddingBottom, Fixed));
+    style->setPaddingLeft(Length(dropDownBoxPaddingLeft, Fixed));
+
+    // Height is locked to auto
+    style->setHeight(Length(Auto));
+
+    // Calculate our min-height
+    int minHeight = style->font().height();
+    minHeight = max(minHeight, dropDownBoxMinHeight);
+
+    style->setMinHeight(Length(minHeight, Fixed));
+    
+    // White-space is locked to pre
+    style->setWhiteSpace(PRE);
+}
+
+bool RenderThemeWin::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+    // FIXME: Don't make hardcoded assumptions about the thickness of the textfield border.
+    int borderThickness = haveTheme ? 1 : 2;
+
+    // Paint the dropdown button on the inner edge of the text field,
+    // leaving space for the text field's 1px border
+    IntRect buttonRect(r);
+    buttonRect.inflate(-borderThickness);
+    if (o->style()->direction() == LTR)
+        buttonRect.setX(buttonRect.right() - dropDownButtonWidth);
+    buttonRect.setWidth(dropDownButtonWidth);
+
+    drawControl(i.context, o, menuListTheme(), getThemeData(o), buttonRect);
+
+    return false;
+}
+
+const int trackWidth = 4;
+
+bool RenderThemeWin::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+    IntRect bounds = r;
+    
+    if (o->style()->appearance() ==  SliderHorizontalPart) {
+        bounds.setHeight(trackWidth);
+        bounds.setY(r.y() + r.height() / 2 - trackWidth / 2);
+    } else if (o->style()->appearance() == SliderVerticalPart) {
+        bounds.setWidth(trackWidth);
+        bounds.setX(r.x() + r.width() / 2 - trackWidth / 2);
+    }
+    
+    drawControl(i.context,  o, sliderTheme(), getThemeData(o), bounds);
+    return false;
+}
+
+bool RenderThemeWin::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{   
+    drawControl(i.context,  o, sliderTheme(), getThemeData(o), r);
+    return false;
+}
+
+const int sliderThumbWidth = 7;
+const int sliderThumbHeight = 15;
+
+void RenderThemeWin::adjustSliderThumbSize(RenderObject* o) const
+{
+    if (o->style()->appearance() == SliderThumbVerticalPart) {
+        o->style()->setWidth(Length(sliderThumbHeight, Fixed));
+        o->style()->setHeight(Length(sliderThumbWidth, Fixed));
+    } else if (o->style()->appearance() == SliderThumbHorizontalPart) {
+        o->style()->setWidth(Length(sliderThumbWidth, Fixed));
+        o->style()->setHeight(Length(sliderThumbHeight, Fixed));
+    }
+ }
+
+bool RenderThemeWin::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+    return paintTextField(o, i, r);
+}
+
+void RenderThemeWin::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{   
+    // Override padding size to match AppKit text positioning.
+    const int padding = 1;
+    style->setPaddingLeft(Length(padding, Fixed));
+    style->setPaddingRight(Length(padding, Fixed));
+    style->setPaddingTop(Length(padding, Fixed));
+    style->setPaddingBottom(Length(padding, Fixed));
+}
+
+bool RenderThemeWin::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    Color buttonColor = (o->element() && o->element()->active()) ? Color(138, 138, 138) : Color(186, 186, 186);
+
+    IntSize cancelSize(10, 10);
+    IntSize cancelRadius(cancelSize.width() / 2, cancelSize.height() / 2);
+    int x = r.x() + (r.width() - cancelSize.width()) / 2;
+    int y = r.y() + (r.height() - cancelSize.height()) / 2 + 1;
+    IntRect cancelBounds(IntPoint(x, y), cancelSize);
+    paintInfo.context->save();
+    paintInfo.context->addRoundedRectClip(cancelBounds, cancelRadius, cancelRadius, cancelRadius, cancelRadius);
+    paintInfo.context->fillRect(cancelBounds, buttonColor);
+
+    // Draw the 'x'
+    IntSize xSize(3, 3);
+    IntRect xBounds(cancelBounds.location() + IntSize(3, 3), xSize);
+    paintInfo.context->setStrokeColor(Color::white);
+    paintInfo.context->drawLine(xBounds.location(),  xBounds.location() + xBounds.size());
+    paintInfo.context->drawLine(IntPoint(xBounds.right(), xBounds.y()),  IntPoint(xBounds.x(), xBounds.bottom()));
+
+    paintInfo.context->restore(); 
+    return false;
+}
+
+void RenderThemeWin::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize cancelSize(13, 11);
+    style->setWidth(Length(cancelSize.width(), Fixed));
+    style->setHeight(Length(cancelSize.height(), Fixed));
+}
+
+void RenderThemeWin::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize emptySize(1, 11);
+    style->setWidth(Length(emptySize.width(), Fixed));
+    style->setHeight(Length(emptySize.height(), Fixed));
+}
+   
+void RenderThemeWin::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize magnifierSize(15, 11);
+    style->setWidth(Length(magnifierSize.width(), Fixed));
+    style->setHeight(Length(magnifierSize.height(), Fixed));
+}
+
+bool RenderThemeWin::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    IntRect bounds = r;
+    bounds.setWidth(bounds.height());
+
+    TCHAR buffer[MAX_PATH];
+    UINT length = ::GetSystemDirectory(buffer, ARRAYSIZE(buffer));
+    if (!length)
+        return 0;
+    
+    if (_tcscat_s(buffer, TEXT("\\shell32.dll")))
+        return 0;
+
+    HICON hIcon;
+    if (!::ExtractIconEx(buffer, shell32MagnifierIconIndex, 0, &hIcon, 1))
+        return 0;
+
+    RefPtr<Icon> icon = Icon::create(hIcon);
+    icon->paint(paintInfo.context, bounds);
+    return false;
+}
+
+void RenderThemeWin::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    IntSize magnifierSize(15, 11);
+    style->setWidth(Length(magnifierSize.width(), Fixed));
+    style->setHeight(Length(magnifierSize.height(), Fixed));
+}
+
+bool RenderThemeWin::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+    paintSearchFieldResultsDecoration(o, paintInfo, r);
+    return false;
+}
+
+// Map a CSSValue* system color to an index understood by GetSysColor
+static int cssValueIdToSysColorIndex(int cssValueId)
+{
+    switch (cssValueId) {
+        case CSSValueActiveborder: return COLOR_ACTIVEBORDER;
+        case CSSValueActivecaption: return COLOR_ACTIVECAPTION;
+        case CSSValueAppworkspace: return COLOR_APPWORKSPACE;
+        case CSSValueBackground: return COLOR_BACKGROUND;
+        case CSSValueButtonface: return COLOR_BTNFACE;
+        case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT;
+        case CSSValueButtonshadow: return COLOR_BTNSHADOW;
+        case CSSValueButtontext: return COLOR_BTNTEXT;
+        case CSSValueCaptiontext: return COLOR_CAPTIONTEXT;
+        case CSSValueGraytext: return COLOR_GRAYTEXT;
+        case CSSValueHighlight: return COLOR_HIGHLIGHT;
+        case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT;
+        case CSSValueInactiveborder: return COLOR_INACTIVEBORDER;
+        case CSSValueInactivecaption: return COLOR_INACTIVECAPTION;
+        case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT;
+        case CSSValueInfobackground: return COLOR_INFOBK;
+        case CSSValueInfotext: return COLOR_INFOTEXT;
+        case CSSValueMenu: return COLOR_MENU;
+        case CSSValueMenutext: return COLOR_MENUTEXT;
+        case CSSValueScrollbar: return COLOR_SCROLLBAR;
+        case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW;
+        case CSSValueThreedface: return COLOR_3DFACE;
+        case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT;
+        case CSSValueThreedlightshadow: return COLOR_3DLIGHT;
+        case CSSValueThreedshadow: return COLOR_3DSHADOW;
+        case CSSValueWindow: return COLOR_WINDOW;
+        case CSSValueWindowframe: return COLOR_WINDOWFRAME;
+        case CSSValueWindowtext: return COLOR_WINDOWTEXT;
+        default: return -1; // Unsupported CSSValue
+    }
+}
+
+Color RenderThemeWin::systemColor(int cssValueId) const
+{
+    int sysColorIndex = cssValueIdToSysColorIndex(cssValueId);
+    ASSERT(sysColorIndex != -1);
+    COLORREF color = GetSysColor(sysColorIndex);
+    return Color(GetRValue(color), GetGValue(color), GetBValue(color));
+}
+
+}
diff --git a/WebCore/rendering/RenderThemeWin.h b/WebCore/rendering/RenderThemeWin.h
new file mode 100644
index 0000000..513f6b5
--- /dev/null
+++ b/WebCore/rendering/RenderThemeWin.h
@@ -0,0 +1,142 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006, 2008 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderThemeWin_h
+#define RenderThemeWin_h
+
+#include "RenderTheme.h"
+
+#if WIN32
+typedef void* HANDLE;
+typedef struct HINSTANCE__* HINSTANCE;
+typedef HINSTANCE HMODULE;
+#endif
+
+namespace WebCore {
+
+struct ThemeData {
+    ThemeData() :m_part(0), m_state(0), m_classicState(0) {}
+    ThemeData(int part, int state)
+        : m_part(part)
+        , m_state(state)
+        , m_classicState(0)
+    { }
+
+    unsigned m_part;
+    unsigned m_state;
+    unsigned m_classicState;
+};
+
+class RenderThemeWin : public RenderTheme {
+public:
+    RenderThemeWin();
+    ~RenderThemeWin();
+       
+    // A method asking if the theme's controls actually care about redrawing when hovered.
+    virtual bool supportsHover(const RenderStyle*) const;
+
+    virtual Color platformActiveSelectionBackgroundColor() const;
+    virtual Color platformInactiveSelectionBackgroundColor() const;
+    virtual Color platformActiveSelectionForegroundColor() const;
+    virtual Color platformInactiveSelectionForegroundColor() const;
+
+    // System fonts.
+    virtual void systemFont(int propId, FontDescription&) const;
+    virtual Color systemColor(int cssValueId) const;
+
+    virtual bool paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+    { return paintButton(o, i, r); }
+    virtual void setCheckboxSize(RenderStyle*) const;
+
+    virtual bool paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+    { return paintButton(o, i, r); }
+    virtual void setRadioSize(RenderStyle* style) const
+    { return setCheckboxSize(style); }
+
+    virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual bool paintTextArea(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+    { return paintTextField(o, i, r); }
+
+    virtual void adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const;
+    virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const;
+
+    virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual bool paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r);
+    virtual bool paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r);
+    virtual void adjustSliderThumbSize(RenderObject*) const;
+
+    virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return false; }
+
+    virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+    virtual void themeChanged();
+
+    virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
+    virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
+    virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
+
+    static void setWebKitIsBeingUnloaded();
+
+private:
+    void addIntrinsicMargins(RenderStyle*) const;
+    void close();
+
+    unsigned determineState(RenderObject*);
+    unsigned determineClassicState(RenderObject*);
+    unsigned determineSliderThumbState(RenderObject*);
+    unsigned determineButtonState(RenderObject*);
+
+    bool supportsFocus(ControlPart);
+
+    ThemeData getThemeData(RenderObject*);
+    ThemeData getClassicThemeData(RenderObject* o);
+
+    HANDLE buttonTheme() const;
+    HANDLE textFieldTheme() const;
+    HANDLE menuListTheme() const;
+    HANDLE sliderTheme() const;
+
+    mutable HANDLE m_buttonTheme;
+    mutable HANDLE m_textFieldTheme;
+    mutable HANDLE m_menuListTheme;
+    mutable HANDLE m_sliderTheme;
+};
+
+};
+
+#endif
diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp
new file mode 100644
index 0000000..346968b
--- /dev/null
+++ b/WebCore/rendering/RenderTreeAsText.cpp
@@ -0,0 +1,512 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderTreeAsText.h"
+
+#include "CharacterNames.h"
+#include "Document.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "HTMLElement.h"
+#include "HTMLNames.h"
+#include "InlineTextBox.h"
+#include "RenderBR.h"
+#include "RenderListMarker.h"
+#include "RenderTableCell.h"
+#include "RenderView.h"
+#include "RenderWidget.h"
+#include "SelectionController.h"
+#include "TextStream.h"
+#include <wtf/Vector.h>
+
+#if ENABLE(SVG)
+#include "RenderSVGRoot.h"
+#include "RenderSVGContainer.h"
+#include "RenderSVGInlineText.h"
+#include "RenderSVGText.h"
+#include "SVGRenderTreeAsText.h"
+#endif
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+static void writeLayers(TextStream&, const RenderLayer* rootLayer, RenderLayer*, const IntRect& paintDirtyRect, int indent = 0);
+
+#if !ENABLE(SVG)
+static TextStream &operator<<(TextStream& ts, const IntRect& r)
+{
+    return ts << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
+}
+#endif
+
+static void writeIndent(TextStream& ts, int indent)
+{
+    for (int i = 0; i != indent; ++i)
+        ts << "  ";
+}
+
+static void printBorderStyle(TextStream& ts, const RenderObject& o, const EBorderStyle borderStyle)
+{
+    switch (borderStyle) {
+        case BNONE:
+            ts << "none";
+            break;
+        case BHIDDEN:
+            ts << "hidden";
+            break;
+        case INSET:
+            ts << "inset";
+            break;
+        case GROOVE:
+            ts << "groove";
+            break;
+        case RIDGE:
+            ts << "ridge";
+            break;
+        case OUTSET:
+            ts << "outset";
+            break;
+        case DOTTED:
+            ts << "dotted";
+            break;
+        case DASHED:
+            ts << "dashed";
+            break;
+        case SOLID:
+            ts << "solid";
+            break;
+        case DOUBLE:
+            ts << "double";
+            break;
+    }
+
+    ts << " ";
+}
+
+static String getTagName(Node* n)
+{
+    if (n->isDocumentNode())
+        return "";
+    if (n->isCommentNode())
+        return "COMMENT";
+    return n->nodeName();
+}
+
+static bool isEmptyOrUnstyledAppleStyleSpan(const Node* node)
+{
+    if (!node || !node->isHTMLElement() || !node->hasTagName(spanTag))
+        return false;
+
+    const HTMLElement* elem = static_cast<const HTMLElement*>(node);
+    if (elem->getAttribute(classAttr) != "Apple-style-span")
+        return false;
+
+    if (!node->hasChildNodes())
+        return true;
+
+    CSSMutableStyleDeclaration* inlineStyleDecl = elem->inlineStyleDecl();
+    return (!inlineStyleDecl || inlineStyleDecl->length() == 0);
+}
+
+String quoteAndEscapeNonPrintables(const String& s)
+{
+    Vector<UChar> result;
+    result.append('"');
+    for (unsigned i = 0; i != s.length(); ++i) {
+        UChar c = s[i];
+        if (c == '\\') {
+            result.append('\\');
+            result.append('\\');
+        } else if (c == '"') {
+            result.append('\\');
+            result.append('"');
+        } else if (c == '\n' || c == noBreakSpace)
+            result.append(' ');
+        else {
+            if (c >= 0x20 && c < 0x7F)
+                result.append(c);
+            else {
+                unsigned u = c;
+                String hex = String::format("\\x{%X}", u);
+                unsigned len = hex.length();
+                for (unsigned i = 0; i < len; ++i)
+                    result.append(hex[i]);
+            }
+        }
+    }
+    result.append('"');
+    return String::adopt(result);
+}
+
+static TextStream &operator<<(TextStream& ts, const RenderObject& o)
+{
+    ts << o.renderName();
+
+    if (o.style() && o.style()->zIndex())
+        ts << " zI: " << o.style()->zIndex();
+
+    if (o.element()) {
+        String tagName = getTagName(o.element());
+        if (!tagName.isEmpty()) {
+            ts << " {" << tagName << "}";
+            // flag empty or unstyled AppleStyleSpan because we never
+            // want to leave them in the DOM
+            if (isEmptyOrUnstyledAppleStyleSpan(o.element()))
+                ts << " *empty or unstyled AppleStyleSpan*";
+        }
+    }
+
+    IntRect r(o.xPos(), o.yPos(), o.width(), o.height());
+    ts << " " << r;
+
+    if (!(o.isText() && !o.isBR())) {
+        if (o.parent() && (o.parent()->style()->color() != o.style()->color()))
+            ts << " [color=" << o.style()->color().name() << "]";
+
+        if (o.parent() && (o.parent()->style()->backgroundColor() != o.style()->backgroundColor()) &&
+            o.style()->backgroundColor().isValid() && o.style()->backgroundColor().rgb())
+            // Do not dump invalid or transparent backgrounds, since that is the default.
+            ts << " [bgcolor=" << o.style()->backgroundColor().name() << "]";
+        
+        if (o.parent() && (o.parent()->style()->textFillColor() != o.style()->textFillColor()) &&
+            o.style()->textFillColor().isValid() && o.style()->textFillColor() != o.style()->color() &&
+            o.style()->textFillColor().rgb())
+            ts << " [textFillColor=" << o.style()->textFillColor().name() << "]";
+
+        if (o.parent() && (o.parent()->style()->textStrokeColor() != o.style()->textStrokeColor()) &&
+            o.style()->textStrokeColor().isValid() && o.style()->textStrokeColor() != o.style()->color() &&
+            o.style()->textStrokeColor().rgb())
+            ts << " [textStrokeColor=" << o.style()->textStrokeColor().name() << "]";
+
+        if (o.parent() && (o.parent()->style()->textStrokeWidth() != o.style()->textStrokeWidth()) &&
+            o.style()->textStrokeWidth() > 0)
+            ts << " [textStrokeWidth=" << o.style()->textStrokeWidth() << "]";
+
+        if (o.borderTop() || o.borderRight() || o.borderBottom() || o.borderLeft()) {
+            ts << " [border:";
+
+            BorderValue prevBorder;
+            if (o.style()->borderTop() != prevBorder) {
+                prevBorder = o.style()->borderTop();
+                if (!o.borderTop())
+                    ts << " none";
+                else {
+                    ts << " (" << o.borderTop() << "px ";
+                    printBorderStyle(ts, o, o.style()->borderTopStyle());
+                    Color col = o.style()->borderTopColor();
+                    if (!col.isValid())
+                        col = o.style()->color();
+                    ts << col.name() << ")";
+                }
+            }
+
+            if (o.style()->borderRight() != prevBorder) {
+                prevBorder = o.style()->borderRight();
+                if (!o.borderRight())
+                    ts << " none";
+                else {
+                    ts << " (" << o.borderRight() << "px ";
+                    printBorderStyle(ts, o, o.style()->borderRightStyle());
+                    Color col = o.style()->borderRightColor();
+                    if (!col.isValid())
+                        col = o.style()->color();
+                    ts << col.name() << ")";
+                }
+            }
+
+            if (o.style()->borderBottom() != prevBorder) {
+                prevBorder = o.style()->borderBottom();
+                if (!o.borderBottom())
+                    ts << " none";
+                else {
+                    ts << " (" << o.borderBottom() << "px ";
+                    printBorderStyle(ts, o, o.style()->borderBottomStyle());
+                    Color col = o.style()->borderBottomColor();
+                    if (!col.isValid())
+                        col = o.style()->color();
+                    ts << col.name() << ")";
+                }
+            }
+
+            if (o.style()->borderLeft() != prevBorder) {
+                prevBorder = o.style()->borderLeft();
+                if (!o.borderLeft())
+                    ts << " none";
+                else {
+                    ts << " (" << o.borderLeft() << "px ";
+                    printBorderStyle(ts, o, o.style()->borderLeftStyle());
+                    Color col = o.style()->borderLeftColor();
+                    if (!col.isValid())
+                        col = o.style()->color();
+                    ts << col.name() << ")";
+                }
+            }
+
+            ts << "]";
+        }
+    }
+
+    if (o.isTableCell()) {
+        const RenderTableCell& c = static_cast<const RenderTableCell&>(o);
+        ts << " [r=" << c.row() << " c=" << c.col() << " rs=" << c.rowSpan() << " cs=" << c.colSpan() << "]";
+    }
+
+    if (o.isListMarker()) {
+        String text = static_cast<const RenderListMarker&>(o).text();
+        if (!text.isEmpty()) {
+            if (text.length() != 1)
+                text = quoteAndEscapeNonPrintables(text);
+            else {
+                switch (text[0]) {
+                    case bullet:
+                        text = "bullet";
+                        break;
+                    case blackSquare:
+                        text = "black square";
+                        break;
+                    case whiteBullet:
+                        text = "white bullet";
+                        break;
+                    default:
+                        text = quoteAndEscapeNonPrintables(text);
+                }
+            }
+            ts << ": " << text;
+        }
+    }
+
+    return ts;
+}
+
+static void writeTextRun(TextStream& ts, const RenderText& o, const InlineTextBox& run)
+{
+    ts << "text run at (" << run.m_x << "," << run.m_y << ") width " << run.m_width;
+    if (run.direction() == RTL || run.m_dirOverride) {
+        ts << (run.direction() == RTL ? " RTL" : " LTR");
+        if (run.m_dirOverride)
+            ts << " override";
+    }
+    ts << ": "
+        << quoteAndEscapeNonPrintables(String(o.text()).substring(run.m_start, run.m_len))
+        << "\n";
+}
+
+void write(TextStream& ts, const RenderObject& o, int indent)
+{
+#if ENABLE(SVG)
+    if (o.isRenderPath()) {
+        write(ts, static_cast<const RenderPath&>(o), indent);
+        return;
+    }
+    if (o.isSVGContainer()) {
+        write(ts, static_cast<const RenderSVGContainer&>(o), indent);
+        return;
+    }
+    if (o.isSVGRoot()) {
+        write(ts, static_cast<const RenderSVGRoot&>(o), indent);
+        return;
+    }
+    if (o.isSVGText()) {
+        if (!o.isText())
+            write(ts, static_cast<const RenderSVGText&>(o), indent);
+        else
+            write(ts, static_cast<const RenderSVGInlineText&>(o), indent);
+        return;
+    }
+#endif
+
+    writeIndent(ts, indent);
+
+    ts << o << "\n";
+
+    if (o.isText() && !o.isBR()) {
+        const RenderText& text = static_cast<const RenderText&>(o);
+        for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox()) {
+            writeIndent(ts, indent + 1);
+            writeTextRun(ts, text, *box);
+        }
+    }
+
+    for (RenderObject* child = o.firstChild(); child; child = child->nextSibling()) {
+        if (child->hasLayer())
+            continue;
+        write(ts, *child, indent + 1);
+    }
+
+    if (o.isWidget()) {
+        Widget* widget = static_cast<const RenderWidget&>(o).widget();
+        if (widget && widget->isFrameView()) {
+            FrameView* view = static_cast<FrameView*>(widget);
+            RenderObject* root = view->frame()->contentRenderer();
+            if (root) {
+                view->layout();
+                RenderLayer* l = root->layer();
+                if (l)
+                    writeLayers(ts, l, l, IntRect(l->xPos(), l->yPos(), l->width(), l->height()), indent + 1);
+            }
+        }
+    }
+}
+
+static void write(TextStream& ts, RenderLayer& l,
+                  const IntRect& layerBounds, const IntRect& backgroundClipRect, const IntRect& clipRect, const IntRect& outlineClipRect,
+                  int layerType = 0, int indent = 0)
+{
+    writeIndent(ts, indent);
+
+    ts << "layer " << layerBounds;
+
+    if (!layerBounds.isEmpty()) {
+        if (!backgroundClipRect.contains(layerBounds))
+            ts << " backgroundClip " << backgroundClipRect;
+        if (!clipRect.contains(layerBounds))
+            ts << " clip " << clipRect;
+        if (!outlineClipRect.contains(layerBounds))
+            ts << " outlineClip " << outlineClipRect;
+    }
+
+    if (l.renderer()->hasOverflowClip()) {
+        if (l.scrollXOffset())
+            ts << " scrollX " << l.scrollXOffset();
+        if (l.scrollYOffset())
+            ts << " scrollY " << l.scrollYOffset();
+        if (l.renderer()->clientWidth() != l.scrollWidth())
+            ts << " scrollWidth " << l.scrollWidth();
+        if (l.renderer()->clientHeight() != l.scrollHeight())
+            ts << " scrollHeight " << l.scrollHeight();
+    }
+
+    if (layerType == -1)
+        ts << " layerType: background only";
+    else if (layerType == 1)
+        ts << " layerType: foreground only";
+
+    ts << "\n";
+
+    if (layerType != -1)
+        write(ts, *l.renderer(), indent + 1);
+}
+
+static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLayer* l,
+                        const IntRect& paintDirtyRect, int indent)
+{
+    // Calculate the clip rects we should use.
+    IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
+    l->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
+
+    // Ensure our lists are up-to-date.
+    l->updateZOrderLists();
+    l->updateOverflowList();
+
+    bool shouldPaint = l->intersectsDamageRect(layerBounds, damageRect, rootLayer);
+    Vector<RenderLayer*>* negList = l->negZOrderList();
+    if (shouldPaint && negList && negList->size() > 0)
+        write(ts, *l, layerBounds, damageRect, clipRectToApply, outlineRect, -1, indent);
+
+    if (negList) {
+        for (unsigned i = 0; i != negList->size(); ++i)
+            writeLayers(ts, rootLayer, negList->at(i), paintDirtyRect, indent);
+    }
+
+    if (shouldPaint)
+        write(ts, *l, layerBounds, damageRect, clipRectToApply, outlineRect, negList && negList->size() > 0, indent);
+
+    Vector<RenderLayer*>* overflowList = l->overflowList();
+    if (overflowList) {
+        for (unsigned i = 0; i != overflowList->size(); ++i)
+            writeLayers(ts, rootLayer, overflowList->at(i), paintDirtyRect, indent);
+    }
+
+    Vector<RenderLayer*>* posList = l->posZOrderList();
+    if (posList) {
+        for (unsigned i = 0; i != posList->size(); ++i)
+            writeLayers(ts, rootLayer, posList->at(i), paintDirtyRect, indent);
+    }
+}
+
+static String nodePosition(Node* node)
+{
+    String result;
+
+    Node* parent;
+    for (Node* n = node; n; n = parent) {
+        parent = n->parentNode();
+        if (!parent)
+            parent = n->shadowParentNode();
+        if (n != node)
+            result += " of ";
+        if (parent)
+            result += "child " + String::number(n->nodeIndex()) + " {" + getTagName(n) + "}";
+        else
+            result += "document";
+    }
+
+    return result;
+}
+
+static void writeSelection(TextStream& ts, const RenderObject* o)
+{
+    Node* n = o->element();
+    if (!n || !n->isDocumentNode())
+        return;
+
+    Document* doc = static_cast<Document*>(n);
+    Frame* frame = doc->frame();
+    if (!frame)
+        return;
+
+    Selection selection = frame->selection()->selection();
+    if (selection.isCaret()) {
+        ts << "caret: position " << selection.start().offset() << " of " << nodePosition(selection.start().node());
+        if (selection.affinity() == UPSTREAM)
+            ts << " (upstream affinity)";
+        ts << "\n";
+    } else if (selection.isRange())
+        ts << "selection start: position " << selection.start().offset() << " of " << nodePosition(selection.start().node()) << "\n"
+           << "selection end:   position " << selection.end().offset() << " of " << nodePosition(selection.end().node()) << "\n";
+}
+
+String externalRepresentation(RenderObject* o)
+{
+    if (!o)
+        return String();
+
+    TextStream ts;
+#if ENABLE(SVG)
+    writeRenderResources(ts, o->document());
+#endif
+    if (o->view()->frameView())
+        o->view()->frameView()->layout();
+    RenderLayer* l = o->layer();
+    if (l) {
+        writeLayers(ts, l, l, IntRect(l->xPos(), l->yPos(), l->width(), l->height()));
+        writeSelection(ts, o);
+    }
+    return ts.release();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderTreeAsText.h b/WebCore/rendering/RenderTreeAsText.h
new file mode 100644
index 0000000..daca253
--- /dev/null
+++ b/WebCore/rendering/RenderTreeAsText.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RenderTreeAsText_h
+#define RenderTreeAsText_h
+
+namespace WebCore {
+
+    class RenderObject;
+    class String;
+    class TextStream;
+
+    String externalRepresentation(RenderObject*);
+    void write(TextStream&, const RenderObject&, int indent = 0);
+
+    // Helper function shared with SVGRenderTreeAsText
+    String quoteAndEscapeNonPrintables(const String&);
+
+} // namespace WebCore
+
+#endif // RenderTreeAsText_h
diff --git a/WebCore/rendering/RenderVideo.cpp b/WebCore/rendering/RenderVideo.cpp
new file mode 100644
index 0000000..d677725
--- /dev/null
+++ b/WebCore/rendering/RenderVideo.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+
+#if ENABLE(VIDEO)
+#include "RenderVideo.h"
+
+#include "Document.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "HTMLVideoElement.h"
+#include "MediaPlayer.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderVideo::RenderVideo(HTMLMediaElement* video)
+    : RenderMedia(video, video->player() ? video->player()->naturalSize() : IntSize(300, 150))
+{
+}
+
+RenderVideo::~RenderVideo()
+{
+    if (MediaPlayer* p = player()) {
+        p->setVisible(false);
+        p->setFrameView(0);
+    }
+}
+    
+void RenderVideo::videoSizeChanged()
+{
+    if (!player())
+        return;
+    IntSize size = player()->naturalSize();
+    if (!size.isEmpty() && size != intrinsicSize()) {
+        setIntrinsicSize(size);
+        setPrefWidthsDirty(true);
+        setNeedsLayout(true);
+    }
+}
+
+IntRect RenderVideo::videoBox() const 
+{
+    IntRect contentRect = contentBox();
+    
+    if (intrinsicSize().isEmpty() || contentRect.isEmpty())
+        return IntRect();
+
+    IntRect resultRect = contentRect;
+    int ratio = contentRect.width() * intrinsicSize().height() - contentRect.height() * intrinsicSize().width();
+    if (ratio > 0) {
+        int newWidth = contentRect.height() * intrinsicSize().width() / intrinsicSize().height();
+        // Just fill the whole area if the difference is one pixel or less (in both sides)
+        if (resultRect.width() - newWidth > 2)
+            resultRect.setWidth(newWidth);
+        resultRect.move((contentRect.width() - resultRect.width()) / 2, 0);
+    } else if (ratio < 0) {
+        int newHeight = contentRect.width() * intrinsicSize().height() / intrinsicSize().width();
+        if (resultRect.height() - newHeight > 2)
+            resultRect.setHeight(newHeight);
+        resultRect.move(0, (contentRect.height() - resultRect.height()) / 2);
+    }
+    return resultRect;
+}
+    
+void RenderVideo::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
+{
+    MediaPlayer* mediaPlayer = player();
+    if (!mediaPlayer)
+        return;
+    updatePlayer();
+    IntRect rect = videoBox();
+    if (rect.isEmpty())
+        return;
+    rect.move(tx, ty);
+    mediaPlayer->paint(paintInfo.context, rect);
+}
+
+void RenderVideo::layout()
+{
+    RenderMedia::layout();
+    updatePlayer();
+}
+    
+void RenderVideo::updateFromElement()
+{
+    RenderMedia::updateFromElement();
+    updatePlayer();
+}
+
+void RenderVideo::updatePlayer()
+{
+    MediaPlayer* mediaPlayer = player();
+    if (!mediaPlayer)
+        return;
+    if (!mediaElement()->inActiveDocument()) {
+        mediaPlayer->setVisible(false);
+        return;
+    }
+    int x;
+    int y;
+    absolutePosition(x, y);
+    IntRect videoBounds = videoBox(); 
+    videoBounds.move(x, y);
+    mediaPlayer->setFrameView(document()->view());
+    mediaPlayer->setRect(videoBounds);
+    mediaPlayer->setVisible(true);
+}
+
+bool RenderVideo::isWidthSpecified() const
+{
+    switch (style()->width().type()) {
+        case Fixed:
+        case Percent:
+            return true;
+        case Auto:
+        case Relative: // FIXME: Shouldn't this case return true? It doesn't for images.
+        case Static:
+        case Intrinsic:
+        case MinIntrinsic:
+            return false;
+    }
+    ASSERT(false);
+    return false;
+}
+
+bool RenderVideo::isHeightSpecified() const
+{
+    switch (style()->height().type()) {
+        case Fixed:
+        case Percent:
+            return true;
+        case Auto:
+        case Relative: // FIXME: Shouldn't this case return true? It doesn't for images.
+        case Static:
+        case Intrinsic:
+        case MinIntrinsic:
+            return false;
+    }
+    ASSERT(false);
+    return false;
+}
+
+int RenderVideo::calcReplacedWidth(bool includeMaxWidth) const
+{
+    int width;
+    if (isWidthSpecified())
+        width = calcReplacedWidthUsing(style()->width());
+    else
+        width = calcAspectRatioWidth();
+
+    int minW = calcReplacedWidthUsing(style()->minWidth());
+    int maxW = !includeMaxWidth || style()->maxWidth().isUndefined() ? width : calcReplacedWidthUsing(style()->maxWidth());
+
+    return max(minW, min(width, maxW));
+}
+
+int RenderVideo::calcReplacedHeight() const
+{
+    int height;
+    if (isHeightSpecified())
+        height = calcReplacedHeightUsing(style()->height());
+    else
+        height = calcAspectRatioHeight();
+
+    int minH = calcReplacedHeightUsing(style()->minHeight());
+    int maxH = style()->maxHeight().isUndefined() ? height : calcReplacedHeightUsing(style()->maxHeight());
+
+    return max(minH, min(height, maxH));
+}
+
+int RenderVideo::calcAspectRatioWidth() const
+{
+    int intrinsicWidth = intrinsicSize().width();
+    int intrinsicHeight = intrinsicSize().height();
+    if (!intrinsicHeight)
+        return 0;
+    return RenderBox::calcReplacedHeight() * intrinsicWidth / intrinsicHeight;
+}
+
+int RenderVideo::calcAspectRatioHeight() const
+{
+    int intrinsicWidth = intrinsicSize().width();
+    int intrinsicHeight = intrinsicSize().height();
+    if (!intrinsicWidth)
+        return 0;
+    return RenderBox::calcReplacedWidth() * intrinsicHeight / intrinsicWidth;
+}
+
+void RenderVideo::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+
+    int paddingAndBorders = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+    m_maxPrefWidth = calcReplacedWidth(false) + paddingAndBorders;
+
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength)
+        m_maxPrefWidth = min(m_maxPrefWidth, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? paddingAndBorders : 0));
+
+    if (style()->width().isPercent() || style()->height().isPercent() || 
+        style()->maxWidth().isPercent() || style()->maxHeight().isPercent() ||
+        style()->minWidth().isPercent() || style()->minHeight().isPercent())
+        m_minPrefWidth = 0;
+    else
+        m_minPrefWidth = m_maxPrefWidth;
+
+    setPrefWidthsDirty(false);
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/rendering/RenderVideo.h b/WebCore/rendering/RenderVideo.h
new file mode 100644
index 0000000..43c1e7b
--- /dev/null
+++ b/WebCore/rendering/RenderVideo.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RenderVideo_h
+#define RenderVideo_h
+
+#if ENABLE(VIDEO)
+
+#include "RenderMedia.h"
+
+namespace WebCore {
+    
+class HTMLMediaElement;
+
+class RenderVideo : public RenderMedia {
+public:
+    RenderVideo(HTMLMediaElement*);
+    virtual ~RenderVideo();
+
+    virtual const char* renderName() const { return "RenderVideo"; }
+
+    virtual void paintReplaced(PaintInfo& paintInfo, int tx, int ty);
+
+    virtual void layout();
+
+    virtual int calcReplacedWidth(bool includeMaxWidth = true) const;
+    virtual int calcReplacedHeight() const;
+
+    virtual void calcPrefWidths();
+    
+    void videoSizeChanged();
+    
+    void updateFromElement();
+
+protected:
+    virtual void intrinsicSizeChanged() { videoSizeChanged(); }
+
+private:
+    int calcAspectRatioWidth() const;
+    int calcAspectRatioHeight() const;
+
+    bool isWidthSpecified() const;
+    bool isHeightSpecified() const;
+    
+    IntRect videoBox() const;
+
+    void updatePlayer();
+};
+
+} // namespace WebCore
+
+#endif
+#endif // RenderVideo_h
diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp
new file mode 100644
index 0000000..a447bc8
--- /dev/null
+++ b/WebCore/rendering/RenderView.cpp
@@ -0,0 +1,588 @@
+/**
+ * This file is part of the HTML widget for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * Copyright (C) 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RenderView.h"
+
+#include "Document.h"
+#include "Element.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "RenderLayer.h"
+
+#ifdef ANDROID_LAYOUT
+#include "Settings.h"
+#endif
+
+namespace WebCore {
+
+RenderView::RenderView(Node* node, FrameView* view)
+    : RenderBlock(node)
+    , m_frameView(view)
+    , m_selectionStart(0)
+    , m_selectionEnd(0)
+    , m_selectionStartPos(-1)
+    , m_selectionEndPos(-1)
+    , m_printImages(true)
+    , m_maximalOutlineSize(0)
+    , m_layoutState(0)
+    , m_layoutStateDisableCount(0)
+{
+    // Clear our anonymous bit, set because RenderObject assumes
+    // any renderer with document as the node is anonymous.
+    setIsAnonymous(false);
+
+    // init RenderObject attributes
+    setInline(false);
+
+    // try to contrain the width to the views width
+    m_width = 0;
+    m_height = 0;
+    m_minPrefWidth = 0;
+    m_maxPrefWidth = 0;
+
+    setPrefWidthsDirty(true, false);
+    
+    setPositioned(true); // to 0,0 :)
+
+    // Create a new root layer for our layer hierarchy.
+    m_layer = new (node->document()->renderArena()) RenderLayer(this);
+    setHasLayer(true);
+}
+
+RenderView::~RenderView()
+{
+}
+
+void RenderView::calcHeight()
+{
+    if (!printing() && m_frameView)
+        m_height = viewHeight();
+}
+
+void RenderView::calcWidth()
+{
+    if (!printing() && m_frameView)
+        m_width = viewWidth();
+#ifdef ANDROID_LAYOUT
+    const Settings * settings = document()->settings();
+    ASSERT(settings);
+    if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
+        m_visibleWidth = m_frameView->screenWidth();
+    if (settings->useWideViewport() && settings->viewportWidth() == -1 && m_width < minPrefWidth())
+        m_width = m_minPrefWidth;
+#endif
+    m_marginLeft = 0;
+    m_marginRight = 0;
+}
+
+void RenderView::calcPrefWidths()
+{
+    ASSERT(prefWidthsDirty());
+
+    RenderBlock::calcPrefWidths();
+
+    m_maxPrefWidth = m_minPrefWidth;
+}
+
+void RenderView::layout()
+{
+    if (printing())
+        m_minPrefWidth = m_maxPrefWidth = m_width;
+
+    // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
+    bool relayoutChildren = !printing() && (!m_frameView || m_width != viewWidth() || m_height != viewHeight());
+    if (relayoutChildren) {
+        setChildNeedsLayout(true, false);
+        for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+            if (child->style()->height().isPercent() || child->style()->minHeight().isPercent() || child->style()->maxHeight().isPercent())
+                child->setChildNeedsLayout(true, false);
+        }
+    }
+
+    ASSERT(!m_layoutState);
+    LayoutState state;
+    // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
+    state.m_clipped = false;
+    m_layoutState = &state;
+
+    if (needsLayout())
+        RenderBlock::layout();
+
+    // Ensure that docWidth() >= width() and docHeight() >= height().
+    setOverflowWidth(m_width);
+    setOverflowHeight(m_height);
+
+    setOverflowWidth(docWidth());
+    setOverflowHeight(docHeight());
+
+    ASSERT(layoutDelta() == IntSize());
+    ASSERT(m_layoutStateDisableCount == 0);
+    ASSERT(m_layoutState == &state);
+    m_layoutState = 0;
+    setNeedsLayout(false);
+}
+
+bool RenderView::absolutePosition(int& xPos, int& yPos, bool fixed) const
+{
+    if (fixed && m_frameView) {
+#ifdef ANDROID_DISABLE_POSITION_FIXED
+        // This disables the css position:fixed to the Browser window. Instead 
+        // the fixed element will be always fixed to the top page.
+        xPos = yPos = 0;
+#else
+        xPos = m_frameView->scrollX();
+        yPos = m_frameView->scrollY();
+#endif
+    } else
+        xPos = yPos = 0;
+    return true;
+}
+
+void RenderView::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
+    ASSERT(!needsLayout());
+
+    // Cache the print rect because the dirty rect could get changed during painting.
+    if (printing())
+        setPrintRect(paintInfo.rect);
+    else
+        setPrintRect(IntRect());
+    paintObject(paintInfo, tx, ty);
+}
+
+void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
+{
+    // Check to see if we are enclosed by a layer that requires complex painting rules.  If so, we cannot blit
+    // when scrolling, and we need to use slow repaints.  Examples of layers that require this are transparent layers,
+    // layers with reflections, or transformed layers.
+    // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being inside
+    // a transform, transparency layer, etc.
+    Element* elt;
+    for (elt = document()->ownerElement(); view() && elt && elt->renderer(); elt = elt->document()->ownerElement()) {
+        RenderLayer* layer = elt->renderer()->enclosingLayer();
+        if (layer->requiresSlowRepaints()) {
+            frameView()->setUseSlowRepaints();
+            break;
+        }
+    }
+
+    if (elt || (firstChild() && firstChild()->style()->visibility() == VISIBLE) || !view())
+        return;
+
+    // This code typically only executes if the root element's visibility has been set to hidden.
+    // Only fill with the base background color (typically white) if we're the root document, 
+    // since iframes/frames with no background in the child document should show the parent's background.
+    if (view()->isTransparent()) // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being transparent.
+        frameView()->setUseSlowRepaints(); // The parent must show behind the child.
+    else {
+        Color baseColor = frameView()->baseBackgroundColor();
+        if (baseColor.alpha() > 0) {
+            paintInfo.context->save();
+            paintInfo.context->setCompositeOperation(CompositeCopy);
+            paintInfo.context->fillRect(paintInfo.rect, baseColor);
+            paintInfo.context->restore();
+        } else
+            paintInfo.context->clearRect(paintInfo.rect);
+    }
+}
+
+void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate)
+{
+    if (printing() || ur.width() == 0 || ur.height() == 0)
+        return;
+
+    if (!m_frameView)
+        return;
+
+    // We always just invalidate the root view, since we could be an iframe that is clipped out
+    // or even invisible.
+    Element* elt = document()->ownerElement();
+    if (!elt)
+        m_frameView->repaintContentRectangle(ur, immediate);
+    else if (RenderObject* obj = elt->renderer()) {
+        IntRect vr = viewRect();
+        IntRect r = intersection(ur, vr);
+        
+        // Subtract out the contentsX and contentsY offsets to get our coords within the viewing
+        // rectangle.
+        r.move(-vr.x(), -vr.y());
+        
+        // FIXME: Hardcoded offsets here are not good.
+        r.move(obj->borderLeft() + obj->paddingLeft(),
+               obj->borderTop() + obj->paddingTop());
+        obj->repaintRectangle(r, immediate);
+    }
+}
+
+void RenderView::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
+{
+    if (printing())
+        return;
+
+    if (fixed && m_frameView)
+        rect.move(m_frameView->scrollX(), m_frameView->scrollY());
+        
+    // Apply our transform if we have one (because of full page zooming).
+    if (m_layer && m_layer->transform())
+        rect = m_layer->transform()->mapRect(rect);
+}
+
+void RenderView::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool)
+{
+    rects.append(IntRect(tx, ty, m_layer->width(), m_layer->height()));
+}
+
+RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
+{
+    if (!object)
+        return 0;
+
+    RenderObject* child = object->childAt(offset);
+    return child ? child : object->nextInPreOrderAfterChildren();
+}
+
+IntRect RenderView::selectionRect(bool clipToVisibleContent) const
+{
+    document()->updateRendering();
+
+    typedef HashMap<RenderObject*, SelectionInfo*> SelectionMap;
+    SelectionMap selectedObjects;
+
+    RenderObject* os = m_selectionStart;
+    RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
+    while (os && os != stop) {
+        if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
+            // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
+            selectedObjects.set(os, new SelectionInfo(os, clipToVisibleContent));
+            RenderBlock* cb = os->containingBlock();
+            while (cb && !cb->isRenderView()) {
+                SelectionInfo* blockInfo = selectedObjects.get(cb);
+                if (blockInfo)
+                    break;
+                selectedObjects.set(cb, new SelectionInfo(cb, clipToVisibleContent));
+                cb = cb->containingBlock();
+            }
+        }
+
+        os = os->nextInPreOrder();
+    }
+
+    // Now create a single bounding box rect that encloses the whole selection.
+    IntRect selRect;
+    SelectionMap::iterator end = selectedObjects.end();
+    for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
+        SelectionInfo* info = i->second;
+        selRect.unite(info->rect());
+        delete info;
+    }
+    return selRect;
+}
+
+void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos)
+{
+    // Make sure both our start and end objects are defined.
+    // Check www.msnbc.com and try clicking around to find the case where this happened.
+    if ((start && !end) || (end && !start))
+        return;
+
+    // Just return if the selection hasn't changed.
+    if (m_selectionStart == start && m_selectionStartPos == startPos &&
+        m_selectionEnd == end && m_selectionEndPos == endPos)
+        return;
+
+    // Record the old selected objects.  These will be used later
+    // when we compare against the new selected objects.
+    int oldStartPos = m_selectionStartPos;
+    int oldEndPos = m_selectionEndPos;
+
+    // Objects each have a single selection rect to examine.
+    typedef HashMap<RenderObject*, SelectionInfo*> SelectedObjectMap;
+    SelectedObjectMap oldSelectedObjects;
+    SelectedObjectMap newSelectedObjects;
+
+    // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
+    // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
+    // the union of those rects might remain the same even when changes have occurred.
+    typedef HashMap<RenderBlock*, BlockSelectionInfo*> SelectedBlockMap;
+    SelectedBlockMap oldSelectedBlocks;
+    SelectedBlockMap newSelectedBlocks;
+
+    RenderObject* os = m_selectionStart;
+    RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
+    while (os && os != stop) {
+        if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
+            // Blocks are responsible for painting line gaps and margin gaps.  They must be examined as well.
+            oldSelectedObjects.set(os, new SelectionInfo(os, true));
+            RenderBlock* cb = os->containingBlock();
+            while (cb && !cb->isRenderView()) {
+                BlockSelectionInfo* blockInfo = oldSelectedBlocks.get(cb);
+                if (blockInfo)
+                    break;
+                oldSelectedBlocks.set(cb, new BlockSelectionInfo(cb));
+                cb = cb->containingBlock();
+            }
+        }
+
+        os = os->nextInPreOrder();
+    }
+
+    // Now clear the selection.
+    SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
+    for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
+        i->first->setSelectionState(SelectionNone);
+
+    // set selection start and end
+    m_selectionStart = start;
+    m_selectionStartPos = startPos;
+    m_selectionEnd = end;
+    m_selectionEndPos = endPos;
+
+    // Update the selection status of all objects between m_selectionStart and m_selectionEnd
+    if (start && start == end)
+        start->setSelectionState(SelectionBoth);
+    else {
+        if (start)
+            start->setSelectionState(SelectionStart);
+        if (end)
+            end->setSelectionState(SelectionEnd);
+    }
+
+    RenderObject* o = start;
+    stop = rendererAfterPosition(end, endPos);
+
+    while (o && o != stop) {
+        if (o != start && o != end && o->canBeSelectionLeaf())
+            o->setSelectionState(SelectionInside);
+        o = o->nextInPreOrder();
+    }
+
+    // Now that the selection state has been updated for the new objects, walk them again and
+    // put them in the new objects list.
+    o = start;
+    while (o && o != stop) {
+        if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
+            newSelectedObjects.set(o, new SelectionInfo(o, true));
+            RenderBlock* cb = o->containingBlock();
+            while (cb && !cb->isRenderView()) {
+                BlockSelectionInfo* blockInfo = newSelectedBlocks.get(cb);
+                if (blockInfo)
+                    break;
+                newSelectedBlocks.set(cb, new BlockSelectionInfo(cb));
+                cb = cb->containingBlock();
+            }
+        }
+
+        o = o->nextInPreOrder();
+    }
+
+    if (!m_frameView) {
+        // We built the maps, but we aren't going to use them.
+        // We need to delete the values, otherwise they'll all leak!
+        deleteAllValues(oldSelectedObjects);
+        deleteAllValues(newSelectedObjects);
+        deleteAllValues(oldSelectedBlocks);
+        deleteAllValues(newSelectedBlocks);
+        return;
+    }
+
+    // Have any of the old selected objects changed compared to the new selection?
+    for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
+        RenderObject* obj = i->first;
+        SelectionInfo* newInfo = newSelectedObjects.get(obj);
+        SelectionInfo* oldInfo = i->second;
+        if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
+            (m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
+            (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
+            repaintViewRectangle(oldInfo->rect());
+            if (newInfo) {
+                repaintViewRectangle(newInfo->rect());
+                newSelectedObjects.remove(obj);
+                delete newInfo;
+            }
+        }
+        delete oldInfo;
+    }
+
+    // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
+    SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
+    for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i) {
+        SelectionInfo* newInfo = i->second;
+        repaintViewRectangle(newInfo->rect());
+        delete newInfo;
+    }
+
+    // Have any of the old blocks changed?
+    SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
+    for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
+        RenderBlock* block = i->first;
+        BlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
+        BlockSelectionInfo* oldInfo = i->second;
+        if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
+            repaintViewRectangle(oldInfo->rects());
+            if (newInfo) {
+                repaintViewRectangle(newInfo->rects());
+                newSelectedBlocks.remove(block);
+                delete newInfo;
+            }
+        }
+        delete oldInfo;
+    }
+
+    // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
+    SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
+    for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i) {
+        BlockSelectionInfo* newInfo = i->second;
+        repaintViewRectangle(newInfo->rects());
+        delete newInfo;
+    }
+}
+
+void RenderView::clearSelection()
+{
+    setSelection(0, -1, 0, -1);
+}
+
+void RenderView::selectionStartEnd(int& startPos, int& endPos) const
+{
+    startPos = m_selectionStartPos;
+    endPos = m_selectionEndPos;
+}
+
+bool RenderView::printing() const
+{
+    return document()->printing();
+}
+
+void RenderView::updateWidgetPositions()
+{
+    RenderObjectSet::iterator end = m_widgets.end();
+    for (RenderObjectSet::iterator it = m_widgets.begin(); it != end; ++it)
+        (*it)->updateWidgetPosition();
+}
+
+void RenderView::addWidget(RenderObject* o)
+{
+    m_widgets.add(o);
+}
+
+void RenderView::removeWidget(RenderObject* o)
+{
+    m_widgets.remove(o);
+}
+
+IntRect RenderView::viewRect() const
+{
+    if (printing())
+        return IntRect(0, 0, m_width, m_height);
+    if (m_frameView)
+        return m_frameView->visibleContentRect();
+    return IntRect();
+}
+
+int RenderView::docHeight() const
+{
+    int h = m_height;
+    int lowestPos = lowestPosition();
+    if (lowestPos > h)
+        h = lowestPos;
+
+    // FIXME: This doesn't do any margin collapsing.
+    // Instead of this dh computation we should keep the result
+    // when we call RenderBlock::layout.
+    int dh = 0;
+    for (RenderObject* c = firstChild(); c; c = c->nextSibling())
+        dh += c->height() + c->marginTop() + c->marginBottom();
+
+    if (dh > h)
+        h = dh;
+
+    return h;
+}
+
+int RenderView::docWidth() const
+{
+    int w = m_width;
+    int rightmostPos = rightmostPosition();
+    if (rightmostPos > w)
+        w = rightmostPos;
+
+    for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
+        int dw = c->width() + c->marginLeft() + c->marginRight();
+        if (dw > w)
+            w = dw;
+    }
+
+    return w;
+}
+
+int RenderView::viewHeight() const
+{
+    int height = 0;
+    if (!printing() && m_frameView)
+        height = m_frameView->visibleHeight();
+    return height;
+}
+
+int RenderView::viewWidth() const
+{
+    int width = 0;
+    if (!printing() && m_frameView)
+        width = m_frameView->visibleWidth();
+    return width;
+}
+
+// The idea here is to take into account what object is moving the pagination point, and
+// thus choose the best place to chop it.
+void RenderView::setBestTruncatedAt(int y, RenderObject* forRenderer, bool forcedBreak)
+{
+    // Nobody else can set a page break once we have a forced break.
+    if (m_forcedPageBreak)
+        return;
+
+    // Forced breaks always win over unforced breaks.
+    if (forcedBreak) {
+        m_forcedPageBreak = true;
+        m_bestTruncatedAt = y;
+        return;
+    }
+
+    // prefer the widest object who tries to move the pagination point
+    int width = forRenderer->width();
+    if (width > m_truncatorWidth) {
+        m_truncatorWidth = width;
+        m_bestTruncatedAt = y;
+    }
+}
+
+void RenderView::pushLayoutState(RenderObject* root)
+{
+    ASSERT(!m_frameView->needsFullRepaint());
+    ASSERT(m_layoutStateDisableCount == 0);
+    ASSERT(m_layoutState == 0);
+
+    m_layoutState = new (renderArena()) LayoutState(root);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h
new file mode 100644
index 0000000..b437cd1
--- /dev/null
+++ b/WebCore/rendering/RenderView.h
@@ -0,0 +1,161 @@
+/*
+ * This file is part of the HTML widget for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * Copyright (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderView_h
+#define RenderView_h
+
+#include "FrameView.h"
+#include "Frame.h"
+#include "LayoutState.h"
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+class RenderView : public RenderBlock {
+public:
+    RenderView(Node*, FrameView*);
+    virtual ~RenderView();
+
+    virtual const char* renderName() const { return "RenderView"; }
+
+    virtual bool isRenderView() const { return true; }
+
+    virtual void layout();
+    virtual void calcWidth();
+    virtual void calcHeight();
+    virtual void calcPrefWidths();
+    virtual bool absolutePosition(int& xPos, int& yPos, bool fixed = false) const;
+    
+    int docHeight() const;
+    int docWidth() const;
+
+    // The same as the FrameView's visibleHeight/visibleWidth but with null check guards.
+    int viewHeight() const;
+    int viewWidth() const;
+    
+    float zoomFactor() const { return m_frameView->frame() && m_frameView->frame()->shouldApplyPageZoom() ? m_frameView->frame()->zoomFactor() : 1.0f; }
+
+    FrameView* frameView() const { return m_frameView; }
+
+    virtual bool hasOverhangingFloats() { return false; }
+
+    virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed = false);
+    virtual void repaintViewRectangle(const IntRect&, bool immediate = false);
+
+    virtual void paint(PaintInfo&, int tx, int ty);
+    virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
+
+    void setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos);
+    void clearSelection();
+    virtual RenderObject* selectionStart() const { return m_selectionStart; }
+    virtual RenderObject* selectionEnd() const { return m_selectionEnd; }
+
+    bool printing() const;
+    void setPrintImages(bool enable) { m_printImages = enable; }
+    bool printImages() const { return m_printImages; }
+    void setTruncatedAt(int y) { m_truncatedAt = y; m_bestTruncatedAt = m_truncatorWidth = 0; m_forcedPageBreak = false; }
+    void setBestTruncatedAt(int y, RenderObject *forRenderer, bool forcedBreak = false);
+    int bestTruncatedAt() const { return m_bestTruncatedAt; }
+
+    int truncatedAt() const { return m_truncatedAt; }
+
+    virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
+
+    IntRect selectionRect(bool clipToVisibleContent = true) const;
+
+    void setMaximalOutlineSize(int o) { m_maximalOutlineSize = o; }
+    int maximalOutlineSize() const { return m_maximalOutlineSize; }
+
+    virtual IntRect viewRect() const;
+
+    virtual void selectionStartEnd(int& startPos, int& endPos) const;
+
+    IntRect printRect() const { return m_printRect; }
+    void setPrintRect(const IntRect& r) { m_printRect = r; }
+
+    void updateWidgetPositions();
+    void addWidget(RenderObject*);
+    void removeWidget(RenderObject*);
+
+    // layoutDelta is used transiently during layout to store how far an object has moved from its
+    // last layout location, in order to repaint correctly
+    const IntSize& layoutDelta() const { return m_layoutDelta; }
+    void addLayoutDelta(const IntSize& delta) { m_layoutDelta += delta; }
+
+    void pushLayoutState(RenderBox* renderer, const IntSize& offset)
+    {
+        if (m_layoutStateDisableCount || m_frameView->needsFullRepaint())
+            return;
+        m_layoutState = new (renderArena()) LayoutState(m_layoutState, renderer, offset);
+    }
+
+    void pushLayoutState(RenderObject*);
+
+    void popLayoutState()
+    {
+        if (m_layoutStateDisableCount || m_frameView->needsFullRepaint())
+            return;
+        LayoutState* state = m_layoutState;
+        m_layoutState = state->m_next;
+        state->destroy(renderArena());
+    }
+
+    LayoutState* layoutState() const { return m_layoutStateDisableCount ? 0 : m_layoutState; }
+
+    // Suspends the LayoutState optimization. Used under transforms that cannot be represented by
+    // LayoutState (common in SVG) and when manipulating the render tree during layout in ways
+    // that can trigger repaint of a non-child (e.g. when a list item moves its list marker around).
+    void disableLayoutState() { m_layoutStateDisableCount++; }
+    void enableLayoutState() { ASSERT(m_layoutStateDisableCount > 0); m_layoutStateDisableCount--; }
+
+protected:
+    FrameView* m_frameView;
+
+    RenderObject* m_selectionStart;
+    RenderObject* m_selectionEnd;
+    int m_selectionStartPos;
+    int m_selectionEndPos;
+
+    // used to ignore viewport width when printing to the printer
+    bool m_printImages;
+    int m_truncatedAt;
+
+    int m_maximalOutlineSize; // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
+    IntRect m_printRect; // Used when printing.
+
+    typedef HashSet<RenderObject*> RenderObjectSet;
+
+    RenderObjectSet m_widgets;
+
+private:
+    int m_bestTruncatedAt;
+    int m_truncatorWidth;
+    bool m_forcedPageBreak;
+    IntSize m_layoutDelta;
+    LayoutState* m_layoutState;
+    unsigned m_layoutStateDisableCount;
+};
+
+} // namespace WebCore
+
+#endif // RenderView_h
diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp
new file mode 100644
index 0000000..57b8722
--- /dev/null
+++ b/WebCore/rendering/RenderWidget.cpp
@@ -0,0 +1,280 @@
+/**
+ * This file is part of the HTML widget for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * Copyright (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2004, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderWidget.h"
+
+#include "AnimationController.h"
+#include "AXObjectCache.h"
+#include "Document.h"
+#include "Element.h"
+#include "Event.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HitTestResult.h"
+#include "RenderLayer.h"
+#include "RenderView.h"
+
+using namespace std;
+
+namespace WebCore {
+
+static HashMap<const Widget*, RenderWidget*>& widgetRendererMap()
+{
+    static HashMap<const Widget*, RenderWidget*>* staticWidgetRendererMap = new HashMap<const Widget*, RenderWidget*>;
+    return *staticWidgetRendererMap;
+}
+
+RenderWidget::RenderWidget(Node* node)
+      : RenderReplaced(node)
+      , m_widget(0)
+      , m_refCount(0)
+{
+    // a replaced element doesn't support being anonymous
+    ASSERT(node);
+    m_view = node->document()->view();
+
+    view()->addWidget(this);
+
+    // Reference counting is used to prevent the widget from being
+    // destroyed while inside the Widget code, which might not be
+    // able to handle that.
+    ref();
+}
+
+void RenderWidget::destroy()
+{
+    // We can't call the base class's destroy because we don't
+    // want to unconditionally delete ourselves (we're ref-counted).
+    // So the code below includes copied and pasted contents of
+    // both RenderBox::destroy() and RenderObject::destroy().
+    // Fix originally made for <rdar://problem/4228818>.
+    animation()->cancelAnimations(this);
+
+    if (RenderView* v = view())
+        v->removeWidget(this);
+
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->remove(this);
+
+    remove();
+
+    if (m_widget) {
+        if (m_view)
+            m_view->removeChild(m_widget);
+        widgetRendererMap().remove(m_widget);
+    }
+    
+    // removes from override size map
+    if (hasOverrideSize())
+        setOverrideSize(-1);
+
+    RenderLayer* layer = m_layer;
+    RenderArena* arena = renderArena();
+
+    if (layer)
+        layer->clearClipRect();
+
+    if (style() && (style()->height().isPercent() || style()->minHeight().isPercent() || style()->maxHeight().isPercent()))
+        RenderBlock::removePercentHeightDescendant(this);
+
+    setNode(0);
+    deref(arena);
+
+    if (layer)
+        layer->destroy(arena);
+}
+
+RenderWidget::~RenderWidget()
+{
+    ASSERT(m_refCount <= 0);
+    deleteWidget();
+}
+
+void RenderWidget::setWidgetGeometry(const IntRect& frame)
+{
+    if (element() && m_widget->frameRect() != frame) {
+        RenderArena* arena = ref();
+        RefPtr<Node> protectedElement(element());
+        m_widget->setFrameRect(frame);
+        deref(arena);
+    }
+}
+
+void RenderWidget::setWidget(Widget* widget)
+{
+    if (widget != m_widget) {
+        if (m_widget) {
+            m_widget->removeFromParent();
+            widgetRendererMap().remove(m_widget);
+            deleteWidget();
+        }
+        m_widget = widget;
+        if (m_widget) {
+            widgetRendererMap().add(m_widget, this);
+            // if we've already received a layout, apply the calculated space to the
+            // widget immediately, but we have to have really been full constructed (with a non-null
+            // style pointer).
+            if (style()) {
+                if (!needsLayout())
+                    setWidgetGeometry(absoluteContentBox());
+                if (style()->visibility() != VISIBLE)
+                    m_widget->hide();
+                else
+                    m_widget->show();
+            }
+            m_view->addChild(m_widget);
+        }
+    }
+}
+
+void RenderWidget::layout()
+{
+    ASSERT(needsLayout());
+
+    setNeedsLayout(false);
+}
+
+void RenderWidget::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+    RenderReplaced::styleDidChange(diff, oldStyle);
+    if (m_widget) {
+        if (style()->visibility() != VISIBLE)
+            m_widget->hide();
+        else
+            m_widget->show();
+    }
+}
+
+void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    if (!shouldPaint(paintInfo, tx, ty))
+        return;
+
+    tx += m_x;
+    ty += m_y;
+
+    if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
+        paintBoxDecorations(paintInfo, tx, ty);
+
+    if (paintInfo.phase == PaintPhaseMask) {
+        paintMask(paintInfo, tx, ty);
+        return;
+    }
+
+    if (!m_view || paintInfo.phase != PaintPhaseForeground || style()->visibility() != VISIBLE)
+        return;
+
+#if PLATFORM(MAC)
+    if (style()->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
+        paintCustomHighlight(tx - m_x, ty - m_y, style()->highlight(), true);
+#endif
+
+    if (m_widget) {
+        // Move the widget if necessary.  We normally move and resize widgets during layout, but sometimes
+        // widgets can move without layout occurring (most notably when you scroll a document that
+        // contains fixed positioned elements).
+        m_widget->move(tx + borderLeft() + paddingLeft(), ty + borderTop() + paddingTop());
+
+        // Tell the widget to paint now.  This is the only time the widget is allowed
+        // to paint itself.  That way it will composite properly with z-indexed layers.
+        m_widget->paint(paintInfo.context, paintInfo.rect);
+    }
+
+    // Paint a partially transparent wash over selected widgets.
+    if (isSelected() && !document()->printing())
+        paintInfo.context->fillRect(selectionRect(), selectionBackgroundColor());
+}
+
+void RenderWidget::deref(RenderArena *arena)
+{
+    if (--m_refCount <= 0)
+        arenaDelete(arena, this);
+}
+
+void RenderWidget::updateWidgetPosition()
+{
+    if (!m_widget)
+        return;
+
+    int x;
+    int y;
+    absolutePosition(x, y);
+    x += borderLeft() + paddingLeft();
+    y += borderTop() + paddingTop();
+
+    int width = m_width - borderLeft() - borderRight() - paddingLeft() - paddingRight();
+    int height = m_height - borderTop() - borderBottom() - paddingTop() - paddingBottom();
+
+    IntRect newBounds(x, y, width, height);
+    IntRect oldBounds(m_widget->frameRect());
+    if (newBounds != oldBounds) {
+        // The widget changed positions.  Update the frame geometry.
+        if (checkForRepaintDuringLayout()) {
+            RenderView* v = view();
+            if (!v->printing()) {
+                v->repaintViewRectangle(oldBounds);
+                v->repaintViewRectangle(newBounds);
+            }
+        }
+
+        RenderArena* arena = ref();
+        element()->ref();
+        m_widget->setFrameRect(newBounds);
+        element()->deref();
+        deref(arena);
+    }
+}
+
+void RenderWidget::setSelectionState(SelectionState state)
+{
+    if (selectionState() != state) {
+        RenderReplaced::setSelectionState(state);
+        if (m_widget)
+            m_widget->setIsSelected(isSelected());
+    }
+}
+
+void RenderWidget::deleteWidget()
+{
+    delete m_widget;
+}
+
+RenderWidget* RenderWidget::find(const Widget* widget)
+{
+    return widgetRendererMap().get(widget);
+}
+
+bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction action)
+{
+    bool hadResult = result.innerNode();
+    bool inside = RenderReplaced::nodeAtPoint(request, result, x, y, tx, ty, action);
+    
+    // Check to see if we are really over the widget itself (and not just in the border/padding area).
+    if (inside && !hadResult && result.innerNode() == element())
+        result.setIsOverWidget(contentBox().contains(result.localPoint()));
+    return inside;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderWidget.h b/WebCore/rendering/RenderWidget.h
new file mode 100644
index 0000000..a64bb54
--- /dev/null
+++ b/WebCore/rendering/RenderWidget.h
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the HTML widget for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * Copyright (C) 2004, 2005, 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderWidget_h
+#define RenderWidget_h
+
+#include "RenderReplaced.h"
+
+namespace WebCore {
+
+class Widget;
+
+class RenderWidget : public RenderReplaced {
+public:
+    RenderWidget(Node*);
+    virtual ~RenderWidget();
+
+    virtual bool isWidget() const { return true; }
+
+    virtual void paint(PaintInfo&, int tx, int ty);
+
+    virtual void destroy();
+    virtual void layout();
+
+    Widget* widget() const { return m_widget; }
+    static RenderWidget* find(const Widget*);
+
+    RenderArena* ref() { ++m_refCount; return renderArena(); }
+    void deref(RenderArena*);
+
+    virtual void setSelectionState(SelectionState);
+
+    virtual void updateWidgetPosition();
+
+    virtual void setWidget(Widget*);
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+protected:
+    virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+
+private:
+    void setWidgetGeometry(const IntRect&);
+
+    virtual void deleteWidget();
+
+protected:
+    Widget* m_widget;
+    FrameView* m_view;
+
+private:
+    int m_refCount;
+};
+
+} // namespace WebCore
+
+#endif // RenderWidget_h
diff --git a/WebCore/rendering/RenderWordBreak.cpp b/WebCore/rendering/RenderWordBreak.cpp
new file mode 100644
index 0000000..a620560
--- /dev/null
+++ b/WebCore/rendering/RenderWordBreak.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "RenderWordBreak.h"
+
+#include "HTMLElement.h"
+
+namespace WebCore {
+
+RenderWordBreak::RenderWordBreak(HTMLElement* element)
+    : RenderText(element, StringImpl::empty())
+{
+}
+
+const char* RenderWordBreak::renderName() const
+{
+    return "RenderWordBreak";
+}
+
+bool RenderWordBreak::isWordBreak() const
+{
+    return true;
+}
+
+}
diff --git a/WebCore/rendering/RenderWordBreak.h b/WebCore/rendering/RenderWordBreak.h
new file mode 100644
index 0000000..acd8179
--- /dev/null
+++ b/WebCore/rendering/RenderWordBreak.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef RenderWordBreak_h
+#define RenderWordBreak_h
+
+#include "RenderText.h"
+
+namespace WebCore {
+
+class HTMLElement;
+
+class RenderWordBreak : public RenderText {
+public:
+    RenderWordBreak(HTMLElement*);
+
+    virtual const char* renderName() const;
+    virtual bool isWordBreak() const;
+};
+
+}
+
+#endif
diff --git a/WebCore/rendering/RootInlineBox.cpp b/WebCore/rendering/RootInlineBox.cpp
new file mode 100644
index 0000000..e98d20e
--- /dev/null
+++ b/WebCore/rendering/RootInlineBox.cpp
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RootInlineBox.h"
+
+#include "BidiResolver.h"
+#include "ChromeClient.h"
+#include "Document.h"
+#include "EllipsisBox.h"
+#include "Frame.h"
+#include "GraphicsContext.h"
+#include "HitTestResult.h"
+#include "Page.h"
+#include "RenderArena.h"
+#include "RenderBlock.h"
+
+using namespace std;
+
+namespace WebCore {
+    
+typedef WTF::HashMap<const RootInlineBox*, EllipsisBox*> EllipsisBoxMap;
+static EllipsisBoxMap* gEllipsisBoxMap = 0;
+
+void* RootInlineBox::Overflow::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void RootInlineBox::Overflow::operator delete(void* ptr, size_t sz)
+{
+    // Stash size where destroy can find it.
+    *(size_t *)ptr = sz;
+}
+
+void RootInlineBox::Overflow::destroy(RenderArena* renderArena)
+{
+    delete this;
+    // Recover the size left there for us by operator delete and free the memory.
+    renderArena->free(*(size_t *)this, this);
+}
+
+void RootInlineBox::destroy(RenderArena* arena)
+{
+    if (m_overflow)
+        m_overflow->destroy(arena);
+    detachEllipsisBox(arena);
+    InlineFlowBox::destroy(arena);
+}
+
+void RootInlineBox::detachEllipsisBox(RenderArena* arena)
+{
+    if (m_hasEllipsisBox) {
+        EllipsisBox* box = gEllipsisBoxMap->take(this);
+        box->setParent(0);
+        box->destroy(arena);
+        m_hasEllipsisBox = false;
+    }
+}
+
+void RootInlineBox::clearTruncation()
+{
+    if (m_hasEllipsisBox) {
+        detachEllipsisBox(m_object->renderArena());
+        InlineFlowBox::clearTruncation();
+    }
+}
+
+bool RootInlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth)
+{
+    // First sanity-check the unoverflowed width of the whole line to see if there is sufficient room.
+    int delta = ltr ? lineBoxEdge - blockEdge : blockEdge - lineBoxEdge;
+    if (width() - delta < ellipsisWidth)
+        return false;
+
+    // Next iterate over all the line boxes on the line.  If we find a replaced element that intersects
+    // then we refuse to accommodate the ellipsis.  Otherwise we're ok.
+    return InlineFlowBox::canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth);
+}
+
+void RootInlineBox::placeEllipsis(const AtomicString& ellipsisStr,  bool ltr, int blockEdge, int ellipsisWidth,
+                                  InlineBox* markupBox)
+{
+    // Create an ellipsis box.
+    EllipsisBox* ellipsisBox = new (m_object->renderArena()) EllipsisBox(m_object, ellipsisStr, this,
+                                                              ellipsisWidth - (markupBox ? markupBox->width() : 0),
+                                                              yPos(), height(), baseline(), !prevRootBox(),
+                                                              markupBox);
+    
+    if (!gEllipsisBoxMap)
+        gEllipsisBoxMap = new EllipsisBoxMap();
+    gEllipsisBoxMap->add(this, ellipsisBox);
+    m_hasEllipsisBox = true;
+
+    if (ltr && (xPos() + width() + ellipsisWidth) <= blockEdge) {
+        ellipsisBox->m_x = xPos() + width();
+        return;
+    }
+
+    // Now attempt to find the nearest glyph horizontally and place just to the right (or left in RTL)
+    // of that glyph.  Mark all of the objects that intersect the ellipsis box as not painting (as being
+    // truncated).
+    bool foundBox = false;
+    ellipsisBox->m_x = placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
+}
+
+int RootInlineBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
+{
+    int result = InlineFlowBox::placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
+    if (result == -1)
+        result = ltr ? blockEdge - ellipsisWidth : blockEdge;
+    return result;
+}
+
+void RootInlineBox::paintEllipsisBox(RenderObject::PaintInfo& paintInfo, int tx, int ty) const
+{
+    if (m_hasEllipsisBox && object()->shouldPaintWithinRoot(paintInfo) && object()->style()->visibility() == VISIBLE &&
+            paintInfo.phase == PaintPhaseForeground)
+        ellipsisBox()->paint(paintInfo, tx, ty);
+}
+
+#if PLATFORM(MAC)
+
+void RootInlineBox::addHighlightOverflow()
+{
+    Frame* frame = object()->document()->frame();
+    if (!frame)
+        return;
+    Page* page = frame->page();
+    if (!page)
+        return;
+
+    // Highlight acts as a selection inflation.
+    FloatRect rootRect(0, selectionTop(), width(), selectionHeight());
+    IntRect inflatedRect = enclosingIntRect(page->chrome()->client()->customHighlightRect(object()->node(), object()->style()->highlight(), rootRect));
+    setHorizontalOverflowPositions(min(leftOverflow(), inflatedRect.x()), max(rightOverflow(), inflatedRect.right()));
+    setVerticalOverflowPositions(min(topOverflow(), inflatedRect.y()), max(bottomOverflow(), inflatedRect.bottom()));
+}
+
+void RootInlineBox::paintCustomHighlight(RenderObject::PaintInfo& paintInfo, int tx, int ty, const AtomicString& highlightType)
+{
+    if (!object()->shouldPaintWithinRoot(paintInfo) || object()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
+        return;
+
+    Frame* frame = object()->document()->frame();
+    if (!frame)
+        return;
+    Page* page = frame->page();
+    if (!page)
+        return;
+
+    // Get the inflated rect so that we can properly hit test.
+    FloatRect rootRect(tx + xPos(), ty + selectionTop(), width(), selectionHeight());
+    FloatRect inflatedRect = page->chrome()->client()->customHighlightRect(object()->node(), highlightType, rootRect);
+    if (inflatedRect.intersects(paintInfo.rect))
+        page->chrome()->client()->paintCustomHighlight(object()->node(), highlightType, rootRect, rootRect, false, true);
+}
+
+#endif
+
+void RootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
+{
+    InlineFlowBox::paint(paintInfo, tx, ty);
+    paintEllipsisBox(paintInfo, tx, ty);
+#if PLATFORM(MAC)
+    RenderStyle* styleToUse = object()->style(m_firstLine);
+    if (styleToUse->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
+        paintCustomHighlight(paintInfo, tx, ty, styleToUse->highlight());
+#endif
+}
+
+bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+{
+    if (m_hasEllipsisBox && object()->style()->visibility() == VISIBLE) {
+        if (ellipsisBox()->nodeAtPoint(request, result, x, y, tx, ty)) {
+            object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
+            return true;
+        }
+    }
+    return InlineFlowBox::nodeAtPoint(request, result, x, y, tx, ty);
+}
+
+void RootInlineBox::adjustPosition(int dx, int dy)
+{
+    InlineFlowBox::adjustPosition(dx, dy);
+    if (m_overflow) {
+        m_overflow->m_topOverflow += dy;
+        m_overflow->m_bottomOverflow += dy;
+        m_overflow->m_selectionTop += dy;
+        m_overflow->m_selectionBottom += dy;
+    }
+    m_blockHeight += dy;
+}
+
+void RootInlineBox::childRemoved(InlineBox* box)
+{
+    if (box->object() == m_lineBreakObj)
+        setLineBreakInfo(0, 0, BidiStatus());
+
+    for (RootInlineBox* prev = prevRootBox(); prev && prev->lineBreakObj() == box->object(); prev = prev->prevRootBox()) {
+        prev->setLineBreakInfo(0, 0, BidiStatus());
+        prev->markDirty();
+    }
+}
+
+GapRects RootInlineBox::fillLineSelectionGap(int selTop, int selHeight, RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
+                                             const RenderObject::PaintInfo* paintInfo)
+{
+    RenderObject::SelectionState lineState = selectionState();
+
+    bool leftGap, rightGap;
+    block()->getHorizontalSelectionGapInfo(lineState, leftGap, rightGap);
+
+    GapRects result;
+
+    InlineBox* firstBox = firstSelectedBox();
+    InlineBox* lastBox = lastSelectedBox();
+    if (leftGap)
+        result.uniteLeft(block()->fillLeftSelectionGap(firstBox->parent()->object(),
+                                                       firstBox->xPos(), selTop, selHeight,
+                                                       rootBlock, blockX, blockY, tx, ty, paintInfo));
+    if (rightGap)
+        result.uniteRight(block()->fillRightSelectionGap(lastBox->parent()->object(),
+                                                         lastBox->xPos() + lastBox->width(), selTop, selHeight,
+                                                         rootBlock, blockX, blockY, tx, ty, paintInfo));
+
+    if (firstBox && firstBox != lastBox) {
+        // Now fill in any gaps on the line that occurred between two selected elements.
+        int lastX = firstBox->xPos() + firstBox->width();
+        for (InlineBox* box = firstBox->nextLeafChild(); box; box = box->nextLeafChild()) {
+            if (box->selectionState() != RenderObject::SelectionNone) {
+                result.uniteCenter(block()->fillHorizontalSelectionGap(box->parent()->object(),
+                                                                       lastX + tx, selTop + ty,
+                                                                       box->xPos() - lastX, selHeight, paintInfo));
+                lastX = box->xPos() + box->width();
+            }
+            if (box == lastBox)
+                break;
+        }
+    }
+
+    return result;
+}
+
+void RootInlineBox::setHasSelectedChildren(bool b)
+{
+    if (m_hasSelectedChildren == b)
+        return;
+    m_hasSelectedChildren = b;
+}
+
+RenderObject::SelectionState RootInlineBox::selectionState()
+{
+    // Walk over all of the selected boxes.
+    RenderObject::SelectionState state = RenderObject::SelectionNone;
+    for (InlineBox* box = firstLeafChild(); box; box = box->nextLeafChild()) {
+        RenderObject::SelectionState boxState = box->selectionState();
+        if ((boxState == RenderObject::SelectionStart && state == RenderObject::SelectionEnd) ||
+            (boxState == RenderObject::SelectionEnd && state == RenderObject::SelectionStart))
+            state = RenderObject::SelectionBoth;
+        else if (state == RenderObject::SelectionNone ||
+                 ((boxState == RenderObject::SelectionStart || boxState == RenderObject::SelectionEnd) &&
+                  (state == RenderObject::SelectionNone || state == RenderObject::SelectionInside)))
+            state = boxState;
+        if (state == RenderObject::SelectionBoth)
+            break;
+    }
+
+    return state;
+}
+
+InlineBox* RootInlineBox::firstSelectedBox()
+{
+    for (InlineBox* box = firstLeafChild(); box; box = box->nextLeafChild()) {
+        if (box->selectionState() != RenderObject::SelectionNone)
+            return box;
+    }
+
+    return 0;
+}
+
+InlineBox* RootInlineBox::lastSelectedBox()
+{
+    for (InlineBox* box = lastLeafChild(); box; box = box->prevLeafChild()) {
+        if (box->selectionState() != RenderObject::SelectionNone)
+            return box;
+    }
+
+    return 0;
+}
+
+int RootInlineBox::selectionTop()
+{
+    int selectionTop = m_overflow ? m_overflow->m_selectionTop : m_y;
+    if (!prevRootBox())
+        return selectionTop;
+
+    int prevBottom = prevRootBox()->selectionBottom();
+    if (prevBottom < selectionTop && block()->containsFloats()) {
+        // This line has actually been moved further down, probably from a large line-height, but possibly because the
+        // line was forced to clear floats.  If so, let's check the offsets, and only be willing to use the previous
+        // line's bottom overflow if the offsets are greater on both sides.
+        int prevLeft = block()->leftOffset(prevBottom);
+        int prevRight = block()->rightOffset(prevBottom);
+        int newLeft = block()->leftOffset(selectionTop);
+        int newRight = block()->rightOffset(selectionTop);
+        if (prevLeft > newLeft || prevRight < newRight)
+            return selectionTop;
+    }
+
+    return prevBottom;
+}
+
+RenderBlock* RootInlineBox::block() const
+{
+    return static_cast<RenderBlock*>(m_object);
+}
+
+bool isEditableLeaf(InlineBox* leaf)
+{
+    return leaf && leaf->object() && leaf->object()->element() && leaf->object()->element()->isContentEditable();
+}
+
+InlineBox* RootInlineBox::closestLeafChildForXPos(int x, bool onlyEditableLeaves)
+{
+    InlineBox* firstLeaf = firstLeafChildAfterBox();
+    InlineBox* lastLeaf = lastLeafChildBeforeBox();
+    if (firstLeaf == lastLeaf && (!onlyEditableLeaves || isEditableLeaf(firstLeaf)))
+        return firstLeaf;
+
+    // Avoid returning a list marker when possible.
+    if (x <= firstLeaf->m_x && !firstLeaf->object()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(firstLeaf)))
+        // The x coordinate is less or equal to left edge of the firstLeaf.
+        // Return it.
+        return firstLeaf;
+
+    if (x >= lastLeaf->m_x + lastLeaf->m_width && !lastLeaf->object()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(lastLeaf)))
+        // The x coordinate is greater or equal to right edge of the lastLeaf.
+        // Return it.
+        return lastLeaf;
+
+    InlineBox* closestLeaf = 0;
+    for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChild()) {
+        if (!leaf->object()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(leaf))) {
+            closestLeaf = leaf;
+            if (x < leaf->m_x + leaf->m_width)
+                // The x coordinate is less than the right edge of the box.
+                // Return it.
+                return leaf;
+        }
+    }
+
+    return closestLeaf ? closestLeaf : lastLeaf;
+}
+
+BidiStatus RootInlineBox::lineBreakBidiStatus() const
+{ 
+    return BidiStatus(m_lineBreakBidiStatusEor, m_lineBreakBidiStatusLastStrong, m_lineBreakBidiStatusLast, m_lineBreakContext);
+}
+
+void RootInlineBox::setLineBreakInfo(RenderObject* obj, unsigned breakPos, const BidiStatus& status)
+{
+    m_lineBreakObj = obj;
+    m_lineBreakPos = breakPos;
+    m_lineBreakBidiStatusEor = status.eor;
+    m_lineBreakBidiStatusLastStrong = status.lastStrong;
+    m_lineBreakBidiStatusLast = status.last;
+    m_lineBreakContext = status.context;
+}
+
+EllipsisBox* RootInlineBox::ellipsisBox() const
+{
+    if (!m_hasEllipsisBox)
+        return false;
+    return gEllipsisBoxMap->get(this);
+}
+
+void RootInlineBox::setVerticalOverflowPositions(int top, int bottom) 
+{ 
+    if (!m_overflow) {
+        if (top == m_y && bottom == m_y + m_height)
+            return;
+        m_overflow = new (m_object->renderArena()) Overflow(this);
+    }
+    m_overflow->m_topOverflow = top; 
+    m_overflow->m_bottomOverflow = bottom; 
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RootInlineBox.h b/WebCore/rendering/RootInlineBox.h
new file mode 100644
index 0000000..4724110
--- /dev/null
+++ b/WebCore/rendering/RootInlineBox.h
@@ -0,0 +1,206 @@
+/*
+ * This file is part of the line box implementation for KDE.
+ *
+ * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RootInlineBox_h
+#define RootInlineBox_h
+
+#include "BidiContext.h"
+#include "InlineFlowBox.h"
+
+namespace WebCore {
+
+class BidiStatus;
+class EllipsisBox;
+class HitTestResult;
+struct GapRects;
+
+class RootInlineBox : public InlineFlowBox {
+public:
+    RootInlineBox(RenderObject* obj)
+        : InlineFlowBox(obj)
+        , m_overflow(0)
+        , m_lineBreakObj(0)
+        , m_lineBreakPos(0)
+    {
+    }
+
+    virtual bool isRootInlineBox() { return true; }
+
+    virtual void destroy(RenderArena*);
+    void detachEllipsisBox(RenderArena*);
+
+    RootInlineBox* nextRootBox() { return static_cast<RootInlineBox*>(m_nextLine); }
+    RootInlineBox* prevRootBox() { return static_cast<RootInlineBox*>(m_prevLine); }
+
+    virtual void adjustPosition(int dx, int dy);
+
+    virtual int topOverflow() { return m_overflow ? m_overflow->m_topOverflow : m_y; }
+    virtual int bottomOverflow() { return m_overflow ? m_overflow->m_bottomOverflow : m_y + m_height; }
+    virtual int leftOverflow() { return m_overflow ? m_overflow->m_leftOverflow : m_x; }
+    virtual int rightOverflow() { return m_overflow ? m_overflow->m_rightOverflow : m_x + m_width; }
+
+    virtual void setVerticalOverflowPositions(int top, int bottom);
+    void setHorizontalOverflowPositions(int left, int right);
+
+    virtual void setVerticalSelectionPositions(int top, int bottom);
+
+#if ENABLE(SVG)
+    virtual void computePerCharacterLayoutInformation() { }
+#endif
+
+    RenderObject* lineBreakObj() const { return m_lineBreakObj; }
+    BidiStatus lineBreakBidiStatus() const;
+    void setLineBreakInfo(RenderObject*, unsigned breakPos, const BidiStatus&);
+
+    unsigned lineBreakPos() const { return m_lineBreakPos; }
+    void setLineBreakPos(unsigned p) { m_lineBreakPos = p; }
+
+    int blockHeight() const { return m_blockHeight; }
+    void setBlockHeight(int h) { m_blockHeight = h; }
+
+    bool endsWithBreak() const { return m_endsWithBreak; }
+    void setEndsWithBreak(bool b) { m_endsWithBreak = b; }
+
+    void childRemoved(InlineBox* box);
+
+    bool canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth);
+    void placeEllipsis(const AtomicString& ellipsisStr, bool ltr, int blockEdge, int ellipsisWidth, InlineBox* markupBox = 0);
+    virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox);
+
+    EllipsisBox* ellipsisBox() const;
+
+    void paintEllipsisBox(RenderObject::PaintInfo&, int tx, int ty) const;
+    bool hitTestEllipsisBox(HitTestResult&, int x, int y, int tx, int ty, HitTestAction, bool);
+
+    virtual void clearTruncation();
+
+#if PLATFORM(MAC)
+    void addHighlightOverflow();
+    void paintCustomHighlight(RenderObject::PaintInfo&, int tx, int ty, const AtomicString& highlightType);
+#endif
+
+    virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int);
+
+    bool hasSelectedChildren() const { return m_hasSelectedChildren; }
+    void setHasSelectedChildren(bool);
+
+    virtual RenderObject::SelectionState selectionState();
+    InlineBox* firstSelectedBox();
+    InlineBox* lastSelectedBox();
+
+    GapRects fillLineSelectionGap(int selTop, int selHeight, RenderBlock* rootBlock, int blockX, int blockY,
+                                  int tx, int ty, const RenderObject::PaintInfo*);
+
+    RenderBlock* block() const;
+
+    int selectionTop();
+    int selectionBottom() { return m_overflow ? m_overflow->m_selectionBottom : m_y + m_height; }
+    int selectionHeight() { return max(0, selectionBottom() - selectionTop()); }
+
+    InlineBox* closestLeafChildForXPos(int x, bool onlyEditableLeaves = false);
+
+    Vector<RenderObject*>& floats()
+    {
+        ASSERT(!isDirty());
+        if (!m_overflow)
+            m_overflow = new (m_object->renderArena()) Overflow(this);
+        return m_overflow->floats;
+    }
+
+    Vector<RenderObject*>* floatsPtr() { ASSERT(!isDirty()); return m_overflow ? &m_overflow->floats : 0; }
+
+protected:
+    // Normally we are only as tall as the style on our block dictates, but we might have content
+    // that spills out above the height of our font (e.g, a tall image), or something that extends further
+    // below our line (e.g., a child whose font has a huge descent).
+        
+    // Allocated only when some of these fields have non-default values
+    struct Overflow {
+        Overflow(RootInlineBox* box) 
+            : m_topOverflow(box->m_y)
+            , m_bottomOverflow(box->m_y + box->m_height)
+            , m_leftOverflow(box->m_x)
+            , m_rightOverflow(box->m_x + box->m_width)
+            , m_selectionTop(box->m_y)
+            , m_selectionBottom(box->m_y + box->m_height)
+        {
+        }
+
+        void destroy(RenderArena*);
+        void* operator new(size_t, RenderArena*) throw();
+        void operator delete(void*, size_t);
+        
+        int m_topOverflow;
+        int m_bottomOverflow;
+        int m_leftOverflow;
+        int m_rightOverflow;
+        int m_selectionTop;
+        int m_selectionBottom;
+        // Floats hanging off the line are pushed into this vector during layout. It is only
+        // good for as long as the line has not been marked dirty.
+        Vector<RenderObject*> floats;
+    private:
+        void* operator new(size_t) throw();
+    };
+    
+    Overflow* m_overflow;
+
+    // Where this line ended.  The exact object and the position within that object are stored so that
+    // we can create an InlineIterator beginning just after the end of this line.
+    RenderObject* m_lineBreakObj;
+    unsigned m_lineBreakPos;
+    RefPtr<BidiContext> m_lineBreakContext;
+
+    // The height of the block at the end of this line.  This is where the next line starts.
+    int m_blockHeight;
+
+    WTF::Unicode::Direction m_lineBreakBidiStatusEor : 5;
+    WTF::Unicode::Direction m_lineBreakBidiStatusLastStrong : 5;
+    WTF::Unicode::Direction m_lineBreakBidiStatusLast : 5;
+};
+
+inline void RootInlineBox::setHorizontalOverflowPositions(int left, int right) 
+{ 
+    if (!m_overflow) {
+        if (left == m_x && right == m_x + m_width)
+            return;
+        m_overflow = new (m_object->renderArena()) Overflow(this);       
+    }
+    m_overflow->m_leftOverflow = left; 
+    m_overflow->m_rightOverflow = right; 
+}
+
+inline void RootInlineBox::setVerticalSelectionPositions(int top, int bottom) 
+{ 
+    if (!m_overflow) {
+        if (top == m_y && bottom == m_y + m_height)
+            return;
+        m_overflow = new (m_object->renderArena()) Overflow(this);
+    }
+    m_overflow->m_selectionTop = top; 
+    m_overflow->m_selectionBottom = bottom; 
+}
+
+} // namespace WebCore
+
+#endif // RootInlineBox_h
diff --git a/WebCore/rendering/SVGCharacterLayoutInfo.cpp b/WebCore/rendering/SVGCharacterLayoutInfo.cpp
new file mode 100644
index 0000000..287aeac
--- /dev/null
+++ b/WebCore/rendering/SVGCharacterLayoutInfo.cpp
@@ -0,0 +1,535 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2007 Nikolas Zimmermann <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGCharacterLayoutInfo.h"
+
+#include "InlineFlowBox.h"
+#include "InlineTextBox.h"
+#include "SVGLengthList.h"
+#include "SVGNumberList.h"
+#include "SVGTextPositioningElement.h"
+#include "RenderSVGTextPath.h"
+
+#include <float.h>
+
+namespace WebCore {
+
+// Helper function
+static float calculateBaselineShift(RenderObject* item)
+{
+    const Font& font = item->style()->font();
+    const SVGRenderStyle* svgStyle = item->style()->svgStyle();
+
+    float baselineShift = 0.0f;
+    if (svgStyle->baselineShift() == BS_LENGTH) {
+        CSSPrimitiveValue* primitive = static_cast<CSSPrimitiveValue*>(svgStyle->baselineShiftValue());
+        baselineShift = primitive->getFloatValue();
+
+        if (primitive->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+            baselineShift = baselineShift / 100.0f * font.pixelSize();
+    } else {
+        float baselineAscent = font.ascent() + font.descent();
+
+        switch (svgStyle->baselineShift()) {
+        case BS_BASELINE:
+            break;
+        case BS_SUB:
+            baselineShift = -baselineAscent / 2.0f;
+            break;
+        case BS_SUPER:
+            baselineShift = baselineAscent / 2.0f;
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    return baselineShift;
+}
+
+SVGCharacterLayoutInfo::SVGCharacterLayoutInfo(Vector<SVGChar>& chars)
+    : curx(0.0f)
+    , cury(0.0f)
+    , angle(0.0f)
+    , dx(0.0f)
+    , dy(0.0f)
+    , shiftx(0.0f)
+    , shifty(0.0f)
+    , pathExtraAdvance(0.0f)
+    , pathTextLength(0.0f)
+    , pathChunkLength(0.0f)
+    , svgChars(chars)
+    , nextDrawnSeperated(false)
+    , xStackChanged(false)
+    , yStackChanged(false)
+    , dxStackChanged(false)
+    , dyStackChanged(false)
+    , angleStackChanged(false)
+    , baselineShiftStackChanged(false)
+    , pathLayout(false)
+    , currentOffset(0.0f)
+    , startOffset(0.0f)
+    , layoutPathLength(0.0f)
+{
+}
+
+bool SVGCharacterLayoutInfo::xValueAvailable() const
+{
+    return xStack.isEmpty() ? false : xStack.last().position() < xStack.last().size();
+}
+
+bool SVGCharacterLayoutInfo::yValueAvailable() const
+{
+    return yStack.isEmpty() ? false : yStack.last().position() < yStack.last().size();
+}
+
+bool SVGCharacterLayoutInfo::dxValueAvailable() const
+{
+    return dxStack.isEmpty() ? false : dxStack.last().position() < dxStack.last().size();
+}
+
+bool SVGCharacterLayoutInfo::dyValueAvailable() const
+{
+    return dyStack.isEmpty() ? false : dyStack.last().position() < dyStack.last().size();
+}
+
+bool SVGCharacterLayoutInfo::angleValueAvailable() const
+{
+    return angleStack.isEmpty() ? false : angleStack.last().position() < angleStack.last().size();
+}
+
+bool SVGCharacterLayoutInfo::baselineShiftValueAvailable() const
+{
+    return !baselineShiftStack.isEmpty();
+}
+
+float SVGCharacterLayoutInfo::xValueNext() const
+{
+    ASSERT(!xStack.isEmpty());
+    return xStack.last().valueAtCurrentPosition();
+}
+
+float SVGCharacterLayoutInfo::yValueNext() const
+{
+    ASSERT(!yStack.isEmpty());
+    return yStack.last().valueAtCurrentPosition();
+}
+
+float SVGCharacterLayoutInfo::dxValueNext() const
+{
+    ASSERT(!dxStack.isEmpty());
+    return dxStack.last().valueAtCurrentPosition();
+}
+
+float SVGCharacterLayoutInfo::dyValueNext() const
+{
+    ASSERT(!dyStack.isEmpty());
+    return dyStack.last().valueAtCurrentPosition();
+}
+
+float SVGCharacterLayoutInfo::angleValueNext() const
+{
+    ASSERT(!angleStack.isEmpty());
+    return angleStack.last().valueAtCurrentPosition();
+}
+
+float SVGCharacterLayoutInfo::baselineShiftValueNext() const
+{
+    ASSERT(!baselineShiftStack.isEmpty());
+    return baselineShiftStack.last();
+}
+
+void SVGCharacterLayoutInfo::processedSingleCharacter()
+{
+    xStackWalk();
+    yStackWalk();
+    dxStackWalk();
+    dyStackWalk();
+    angleStackWalk();
+    baselineShiftStackWalk();
+}
+
+void SVGCharacterLayoutInfo::processedChunk(float savedShiftX, float savedShiftY)
+{
+    // baseline-shift doesn't span across ancestors, unlike dx/dy.
+    curx += savedShiftX - shiftx;
+    cury += savedShiftY - shifty;
+
+    if (inPathLayout()) {
+        shiftx = savedShiftX;
+        shifty = savedShiftY;
+    }
+
+    // rotation also doesn't span
+    angle = 0.0f;
+
+    if (xStackChanged) {
+        ASSERT(!xStack.isEmpty());
+        xStack.removeLast();
+        xStackChanged = false;
+    }
+
+    if (yStackChanged) {
+        ASSERT(!yStack.isEmpty());
+        yStack.removeLast();
+        yStackChanged = false;
+    }
+
+    if (dxStackChanged) {
+        ASSERT(!dxStack.isEmpty());
+        dxStack.removeLast();
+        dxStackChanged = false;
+    }
+
+    if (dyStackChanged) {
+        ASSERT(!dyStack.isEmpty());
+        dyStack.removeLast();
+        dyStackChanged = false;
+    }
+
+    if (angleStackChanged) {
+        ASSERT(!angleStack.isEmpty());
+        angleStack.removeLast();
+        angleStackChanged = false;
+    }
+
+    if (baselineShiftStackChanged) {
+        ASSERT(!baselineShiftStack.isEmpty());
+        baselineShiftStack.removeLast();
+        baselineShiftStackChanged = false;
+    }
+}
+
+bool SVGCharacterLayoutInfo::nextPathLayoutPointAndAngle(float glyphAdvance, float extraAdvance, float newOffset)
+{
+    if (layoutPathLength <= 0.0f)
+        return false;
+
+    if (newOffset != FLT_MIN)
+        currentOffset = startOffset + newOffset;
+
+    // Respect translation along path (extraAdvance is orthogonal to the path)
+    currentOffset += extraAdvance;
+
+    float offset = currentOffset + glyphAdvance / 2.0f;
+    currentOffset += glyphAdvance + pathExtraAdvance;
+
+    if (offset < 0.0f || offset > layoutPathLength)
+        return false;
+
+    bool ok = false; 
+    FloatPoint point = layoutPath.pointAtLength(offset, ok);
+    ASSERT(ok);
+
+    curx = point.x();
+    cury = point.y();
+
+    angle = layoutPath.normalAngleAtLength(offset, ok);
+    ASSERT(ok);
+
+    // fprintf(stderr, "t: %f, x: %f, y: %f, angle: %f, glyphAdvance: %f\n", currentOffset, x, y, angle, glyphAdvance);
+    return true;
+}
+
+bool SVGCharacterLayoutInfo::inPathLayout() const
+{
+    return pathLayout;
+}
+
+void SVGCharacterLayoutInfo::setInPathLayout(bool value)
+{
+    pathLayout = value;
+
+    pathExtraAdvance = 0.0f;
+    pathTextLength = 0.0f;
+    pathChunkLength = 0.0f;
+}
+
+void SVGCharacterLayoutInfo::addLayoutInformation(InlineFlowBox* flowBox, float textAnchorStartOffset)
+{
+    bool isInitialLayout = xStack.isEmpty() && yStack.isEmpty() &&
+                           dxStack.isEmpty() && dyStack.isEmpty() &&
+                           angleStack.isEmpty() && baselineShiftStack.isEmpty() &&
+                           curx == 0.0f && cury == 0.0f;
+
+    RenderSVGTextPath* textPath = static_cast<RenderSVGTextPath*>(flowBox->object());
+    Path path = textPath->layoutPath();
+
+    float baselineShift = calculateBaselineShift(textPath);
+
+    layoutPath = path;
+    layoutPathLength = path.length();
+
+    if (layoutPathLength <= 0.0f)
+        return;
+
+    startOffset = textPath->startOffset();
+
+    if (textPath->startOffset() >= 0.0f && textPath->startOffset() <= 1.0f)
+        startOffset *= layoutPathLength;
+
+    startOffset += textAnchorStartOffset;
+    currentOffset = startOffset;
+
+    // Only baseline-shift is handled through the normal layout system
+    addStackContent(BaselineShiftStack, baselineShift);
+
+    if (isInitialLayout) {
+        xStackChanged = false;
+        yStackChanged = false;
+        dxStackChanged = false;
+        dyStackChanged = false;
+        angleStackChanged = false;
+        baselineShiftStackChanged = false;
+    }
+}
+
+void SVGCharacterLayoutInfo::addLayoutInformation(SVGTextPositioningElement* element)
+{
+    bool isInitialLayout = xStack.isEmpty() && yStack.isEmpty() &&
+                           dxStack.isEmpty() && dyStack.isEmpty() &&
+                           angleStack.isEmpty() && baselineShiftStack.isEmpty() &&
+                           curx == 0.0f && cury == 0.0f;
+
+    float baselineShift = calculateBaselineShift(element->renderer());
+
+    addStackContent(XStack, element->x(), element);
+    addStackContent(YStack, element->y(), element);
+    addStackContent(DxStack, element->dx(), element);
+    addStackContent(DyStack, element->dy(), element);
+    addStackContent(AngleStack, element->rotate());
+    addStackContent(BaselineShiftStack, baselineShift);
+
+    if (isInitialLayout) {
+        xStackChanged = false;
+        yStackChanged = false;
+        dxStackChanged = false;
+        dyStackChanged = false;
+        angleStackChanged = false;
+        baselineShiftStackChanged = false;
+    }
+}
+
+void SVGCharacterLayoutInfo::addStackContent(StackType type, SVGNumberList* list)
+{
+    unsigned length = list->numberOfItems();
+    if (!length)
+        return;
+
+    PositionedFloatVector newLayoutInfo;
+
+    // TODO: Convert more efficiently!
+    ExceptionCode ec = 0;
+    for (unsigned i = 0; i < length; ++i) {
+        float value = list->getItem(i, ec);
+        ASSERT(ec == 0);
+
+        newLayoutInfo.append(value);
+    }
+
+    addStackContent(type, newLayoutInfo);
+}
+
+void SVGCharacterLayoutInfo::addStackContent(StackType type, SVGLengthList* list, const SVGElement* context)
+{
+    unsigned length = list->numberOfItems();
+    if (!length)
+        return;
+
+    PositionedFloatVector newLayoutInfo;
+
+    ExceptionCode ec = 0;
+    for (unsigned i = 0; i < length; ++i) {
+        float value = list->getItem(i, ec).value(context);
+        ASSERT(ec == 0);
+
+        newLayoutInfo.append(value);
+    }
+
+    addStackContent(type, newLayoutInfo);
+}
+
+void SVGCharacterLayoutInfo::addStackContent(StackType type, const PositionedFloatVector& list)
+{
+    switch (type) {
+    case XStack:
+        xStackChanged = true;
+        xStack.append(list);
+        break;
+    case YStack:
+        yStackChanged = true;
+        yStack.append(list);
+        break;
+    case DxStack:
+        dxStackChanged = true;
+        dxStack.append(list);
+        break;
+    case DyStack:
+        dyStackChanged = true;
+        dyStack.append(list);
+        break;
+   case AngleStack:
+        angleStackChanged = true;
+        angleStack.append(list);
+        break; 
+   default:
+        ASSERT_NOT_REACHED();
+    }
+}
+
+void SVGCharacterLayoutInfo::addStackContent(StackType type, float value)
+{
+    if (value == 0.0f)
+        return;
+
+    switch (type) {
+    case BaselineShiftStack:
+        baselineShiftStackChanged = true;
+        baselineShiftStack.append(value);
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+}
+
+void SVGCharacterLayoutInfo::xStackWalk()
+{
+    unsigned i = 1;
+
+    while (!xStack.isEmpty()) {
+        PositionedFloatVector& cur = xStack.last();
+        if (i + cur.position() < cur.size()) {
+            cur.advance(i);
+            break;
+        }
+
+        i += cur.position();
+        xStack.removeLast();
+        xStackChanged = false;
+    }
+}
+
+void SVGCharacterLayoutInfo::yStackWalk()
+{
+    unsigned i = 1;
+
+    while (!yStack.isEmpty()) {
+        PositionedFloatVector& cur = yStack.last();
+        if (i + cur.position() < cur.size()) {
+            cur.advance(i);
+            break;
+        }
+
+        i += cur.position();
+        yStack.removeLast();
+        yStackChanged = false;
+    }
+}
+
+void SVGCharacterLayoutInfo::dxStackWalk()
+{
+    unsigned i = 1;
+
+    while (!dxStack.isEmpty()) {
+        PositionedFloatVector& cur = dxStack.last();
+        if (i + cur.position() < cur.size()) {
+            cur.advance(i);
+            break;
+        }
+
+        i += cur.position();
+        dxStack.removeLast();
+        dxStackChanged = false;
+    }
+}
+
+void SVGCharacterLayoutInfo::dyStackWalk()
+{
+    unsigned i = 1;
+
+    while (!dyStack.isEmpty()) {
+        PositionedFloatVector& cur = dyStack.last();
+        if (i + cur.position() < cur.size()) {
+            cur.advance(i);
+            break;
+        }
+
+        i += cur.position();
+        dyStack.removeLast();
+        dyStackChanged = false;
+    }
+}
+
+void SVGCharacterLayoutInfo::angleStackWalk()
+{
+    unsigned i = 1;
+
+    while (!angleStack.isEmpty()) {
+        PositionedFloatVector& cur = angleStack.last();
+        if (i + cur.position() < cur.size()) {
+            cur.advance(i);
+            break;
+        }
+
+        i += cur.position();
+        angleStack.removeLast();
+        angleStackChanged = false;
+    }
+}
+
+void SVGCharacterLayoutInfo::baselineShiftStackWalk()
+{
+    if (!baselineShiftStack.isEmpty()) {
+        baselineShiftStack.removeLast();
+        baselineShiftStackChanged = false;
+    }
+}
+
+bool SVGChar::isHidden() const
+{
+    return pathData && pathData->hidden;
+}
+
+AffineTransform SVGChar::characterTransform() const
+{
+    AffineTransform ctm;
+
+    // Rotate character around angle, and possibly scale.
+    ctm.translate(x, y);
+    ctm.rotate(angle);
+
+    if (pathData) {
+        ctm.scale(pathData->xScale, pathData->yScale);
+        ctm.translate(pathData->xShift, pathData->yShift);
+        ctm.rotate(pathData->orientationAngle);
+    }
+
+    ctm.translate(orientationShiftX - x, orientationShiftY - y);
+    return ctm;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/SVGCharacterLayoutInfo.h b/WebCore/rendering/SVGCharacterLayoutInfo.h
new file mode 100644
index 0000000..f3c5209
--- /dev/null
+++ b/WebCore/rendering/SVGCharacterLayoutInfo.h
@@ -0,0 +1,416 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2007 Nikolas Zimmermann <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SVGCharacterLayoutInfo_h
+#define SVGCharacterLayoutInfo_h
+
+#if ENABLE(SVG)
+#include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+
+#include "AffineTransform.h"
+#include <wtf/RefCounted.h>
+#include "SVGRenderStyle.h"
+#include "SVGTextContentElement.h"
+
+namespace WebCore {
+
+class InlineBox;
+class InlineFlowBox;
+class SVGInlineTextBox;
+class SVGLengthList;
+class SVGNumberList;
+class SVGTextPositioningElement;
+
+template<class Type>
+class PositionedVector : public Vector<Type>
+{
+public:
+    PositionedVector<Type>()
+        : m_position(0)
+    {
+    }
+
+    unsigned position() const
+    {
+        return m_position;
+    }
+
+    void advance(unsigned position)
+    {
+        m_position += position;
+        ASSERT(m_position < Vector<Type>::size());
+    }
+
+    Type valueAtCurrentPosition() const
+    {
+        ASSERT(m_position < Vector<Type>::size());
+        return Vector<Type>::at(m_position);
+    }
+
+private:
+    unsigned m_position;
+};
+
+class PositionedFloatVector : public PositionedVector<float> { };
+struct SVGChar;
+
+struct SVGCharacterLayoutInfo {
+    SVGCharacterLayoutInfo(Vector<SVGChar>&);
+
+    enum StackType { XStack, YStack, DxStack, DyStack, AngleStack, BaselineShiftStack };
+
+    bool xValueAvailable() const;
+    bool yValueAvailable() const;
+    bool dxValueAvailable() const;
+    bool dyValueAvailable() const;
+    bool angleValueAvailable() const;
+    bool baselineShiftValueAvailable() const;
+
+    float xValueNext() const;
+    float yValueNext() const;
+    float dxValueNext() const;
+    float dyValueNext() const;
+    float angleValueNext() const;
+    float baselineShiftValueNext() const;
+
+    void processedChunk(float savedShiftX, float savedShiftY);
+    void processedSingleCharacter();
+
+    bool nextPathLayoutPointAndAngle(float glyphAdvance, float extraAdvance, float newOffset);
+
+    // Used for text-on-path.
+    void addLayoutInformation(InlineFlowBox*, float textAnchorOffset = 0.0f);
+
+    bool inPathLayout() const;
+    void setInPathLayout(bool value);
+
+    // Used for anything else.
+    void addLayoutInformation(SVGTextPositioningElement*);
+
+    // Global position
+    float curx;
+    float cury;
+
+    // Global rotation
+    float angle;
+
+    // Accumulated dx/dy values
+    float dx;
+    float dy;
+
+    // Accumulated baseline-shift values
+    float shiftx;
+    float shifty;
+
+    // Path specific advance values to handle lengthAdjust
+    float pathExtraAdvance;
+    float pathTextLength;
+    float pathChunkLength;
+
+    // Result vector
+    Vector<SVGChar>& svgChars;
+    bool nextDrawnSeperated : 1;
+
+private:
+    // Used for baseline-shift.
+    void addStackContent(StackType, float);
+
+    // Used for angle.
+    void addStackContent(StackType, SVGNumberList*);
+
+    // Used for x/y/dx/dy.    
+    void addStackContent(StackType, SVGLengthList*, const SVGElement*);
+
+    void addStackContent(StackType, const PositionedFloatVector&);
+
+    void xStackWalk();
+    void yStackWalk();
+    void dxStackWalk();
+    void dyStackWalk();
+    void angleStackWalk();
+    void baselineShiftStackWalk();
+
+private:
+    bool xStackChanged : 1;
+    bool yStackChanged : 1;
+    bool dxStackChanged : 1;
+    bool dyStackChanged : 1;
+    bool angleStackChanged : 1;
+    bool baselineShiftStackChanged : 1;
+
+    // text on path layout
+    bool pathLayout : 1;
+    float currentOffset;
+    float startOffset;
+    float layoutPathLength;
+    Path layoutPath;
+
+    Vector<PositionedFloatVector> xStack;
+    Vector<PositionedFloatVector> yStack;
+    Vector<PositionedFloatVector> dxStack;
+    Vector<PositionedFloatVector> dyStack;
+    Vector<PositionedFloatVector> angleStack;
+    Vector<float> baselineShiftStack;
+};
+
+// Holds extra data, when the character is laid out on a path
+struct SVGCharOnPath : RefCounted<SVGCharOnPath> {
+    static PassRefPtr<SVGCharOnPath> create() { return adoptRef(new SVGCharOnPath); }
+
+    float xScale;
+    float yScale;
+
+    float xShift;
+    float yShift;
+
+    float orientationAngle;
+
+    bool hidden : 1;
+    
+private:
+    SVGCharOnPath()
+        : xScale(1.0f)
+        , yScale(1.0f)
+        , xShift(0.0f)
+        , yShift(0.0f)
+        , orientationAngle(0.0f)
+        , hidden(false)
+    {
+    }
+};
+
+struct SVGChar {
+    SVGChar()
+        : x(0.0f)
+        , y(0.0f)
+        , angle(0.0f)
+        , orientationShiftX(0.0f)
+        , orientationShiftY(0.0f)
+        , pathData()
+        , drawnSeperated(false)
+        , newTextChunk(false)
+    {
+    }
+
+    ~SVGChar()
+    {
+    }
+
+    float x;
+    float y;
+    float angle;
+
+    float orientationShiftX;
+    float orientationShiftY;
+
+    RefPtr<SVGCharOnPath> pathData;
+
+    // Determines wheter this char needs to be drawn seperated
+    bool drawnSeperated : 1;
+
+    // Determines wheter this char starts a new chunk
+    bool newTextChunk : 1;
+
+    // Helper methods
+    bool isHidden() const;
+    AffineTransform characterTransform() const;
+};
+
+struct SVGInlineBoxCharacterRange {
+    SVGInlineBoxCharacterRange()
+        : startOffset(INT_MIN)
+        , endOffset(INT_MIN)
+        , box(0)
+    {
+    }
+
+    bool isOpen() const { return (startOffset == endOffset) && (endOffset == INT_MIN); }
+    bool isClosed() const { return startOffset != INT_MIN && endOffset != INT_MIN; }
+
+    int startOffset;
+    int endOffset;
+
+    InlineBox* box;
+};
+
+// Convenience typedef
+typedef SVGTextContentElement::SVGLengthAdjustType ELengthAdjust;
+
+struct SVGTextChunk {
+    SVGTextChunk()
+        : anchor(TA_START)
+        , textLength(0.0f)
+        , lengthAdjust(SVGTextContentElement::LENGTHADJUST_SPACING)
+        , ctm()
+        , isVerticalText(false)
+        , isTextPath(false)
+        , start(0)
+        , end(0)
+    { }
+
+    // text-anchor support
+    ETextAnchor anchor;
+
+    // textLength & lengthAdjust support
+    float textLength;
+    ELengthAdjust lengthAdjust;
+    AffineTransform ctm;
+
+    // status flags
+    bool isVerticalText : 1;
+    bool isTextPath : 1;
+
+    // main chunk data
+    Vector<SVGChar>::iterator start;
+    Vector<SVGChar>::iterator end;
+
+    Vector<SVGInlineBoxCharacterRange> boxes;
+};
+
+struct SVGTextChunkWalkerBase {
+    virtual ~SVGTextChunkWalkerBase() { }
+
+    virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm,
+                            const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) = 0;
+
+    // Followings methods are only used for painting text chunks
+    virtual void start(InlineBox*) = 0;
+    virtual void end(InlineBox*) = 0;
+    
+    virtual bool setupFill(InlineBox*) = 0;
+    virtual bool setupStroke(InlineBox*) = 0;
+};
+
+template<typename CallbackClass>
+struct SVGTextChunkWalker : public SVGTextChunkWalkerBase {
+public:
+    typedef void (CallbackClass::*SVGTextChunkWalkerCallback)(SVGInlineTextBox* textBox,
+                                                              int startOffset,
+                                                              const AffineTransform& chunkCtm,
+                                                              const Vector<SVGChar>::iterator& start,
+                                                              const Vector<SVGChar>::iterator& end);
+
+    // These callbacks are only used for painting!
+    typedef void (CallbackClass::*SVGTextChunkStartCallback)(InlineBox* box);
+    typedef void (CallbackClass::*SVGTextChunkEndCallback)(InlineBox* box);
+
+    typedef bool (CallbackClass::*SVGTextChunkSetupFillCallback)(InlineBox* box);
+    typedef bool (CallbackClass::*SVGTextChunkSetupStrokeCallback)(InlineBox* box);
+
+    SVGTextChunkWalker(CallbackClass* object,
+                       SVGTextChunkWalkerCallback walker,
+                       SVGTextChunkStartCallback start = 0,
+                       SVGTextChunkEndCallback end = 0,
+                       SVGTextChunkSetupFillCallback fill = 0,
+                       SVGTextChunkSetupStrokeCallback stroke = 0)
+        : m_object(object)
+        , m_walkerCallback(walker)
+        , m_startCallback(start)
+        , m_endCallback(end)
+        , m_setupFillCallback(fill)
+        , m_setupStrokeCallback(stroke)
+    {
+        ASSERT(object);
+        ASSERT(walker);
+    }
+
+    virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm,
+                            const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)
+    {
+        (*m_object.*m_walkerCallback)(textBox, startOffset, chunkCtm, start, end);
+    }
+
+    // Followings methods are only used for painting text chunks
+    virtual void start(InlineBox* box)
+    {
+        if (m_startCallback)
+            (*m_object.*m_startCallback)(box);
+        else
+            ASSERT_NOT_REACHED();
+    }
+
+    virtual void end(InlineBox* box)
+    {
+        if (m_endCallback)
+            (*m_object.*m_endCallback)(box);
+        else
+            ASSERT_NOT_REACHED();
+    }
+
+    virtual bool setupFill(InlineBox* box)
+    {
+        if (m_setupFillCallback)
+            return (*m_object.*m_setupFillCallback)(box);
+
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    virtual bool setupStroke(InlineBox* box)
+    {
+        if (m_setupStrokeCallback)
+            return (*m_object.*m_setupStrokeCallback)(box);
+
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+private:
+    CallbackClass* m_object;
+    SVGTextChunkWalkerCallback m_walkerCallback;
+    SVGTextChunkStartCallback m_startCallback;
+    SVGTextChunkEndCallback m_endCallback;
+    SVGTextChunkSetupFillCallback m_setupFillCallback;
+    SVGTextChunkSetupStrokeCallback m_setupStrokeCallback;
+};
+
+struct SVGTextChunkLayoutInfo {
+    SVGTextChunkLayoutInfo(Vector<SVGTextChunk>& textChunks)
+        : assignChunkProperties(true)
+        , handlingTextPath(false)
+        , svgTextChunks(textChunks)
+        , it(0)
+    {
+    }
+
+    bool assignChunkProperties : 1;
+    bool handlingTextPath : 1;
+
+    Vector<SVGTextChunk>& svgTextChunks;
+    Vector<SVGChar>::iterator it;
+
+    SVGTextChunk chunk;
+};
+
+struct SVGTextDecorationInfo {
+    // ETextDecoration is meant to be used here
+    HashMap<int, RenderObject*> fillServerMap;
+    HashMap<int, RenderObject*> strokeServerMap;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // SVGCharacterLayoutInfo_h
diff --git a/WebCore/rendering/SVGInlineFlowBox.cpp b/WebCore/rendering/SVGInlineFlowBox.cpp
new file mode 100644
index 0000000..bbd8f4a
--- /dev/null
+++ b/WebCore/rendering/SVGInlineFlowBox.cpp
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <[email protected]>
+ *           (C) 2006 Apple Computer Inc.
+ *           (C) 2007 Nikolas Zimmermann <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGInlineFlowBox.h"
+#include "SVGNames.h"
+
+namespace WebCore {
+
+using namespace SVGNames;
+
+void SVGInlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
+{
+    ASSERT_NOT_REACHED();
+}
+
+int SVGInlineFlowBox::placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing)
+{
+    // no-op
+    return 0;
+}
+
+void SVGInlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
+{
+    // no-op
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/SVGInlineFlowBox.h b/WebCore/rendering/SVGInlineFlowBox.h
new file mode 100644
index 0000000..96c5d4a
--- /dev/null
+++ b/WebCore/rendering/SVGInlineFlowBox.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <[email protected]>
+ *           (C) 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SVGInlineFlowBox_h
+#define SVGInlineFlowBox_h
+
+#if ENABLE(SVG)
+#include "InlineFlowBox.h"
+
+namespace WebCore {
+
+class SVGInlineFlowBox : public InlineFlowBox {
+public:
+    SVGInlineFlowBox(RenderObject* obj)
+        : InlineFlowBox(obj)
+    {
+    }
+
+    virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
+    virtual int placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing);
+    virtual void verticallyAlignBoxes(int& heightOfBlock);
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+
+#endif // SVGInlineFlowBox_h
diff --git a/WebCore/rendering/SVGInlineTextBox.cpp b/WebCore/rendering/SVGInlineTextBox.cpp
new file mode 100644
index 0000000..ceb7b0e
--- /dev/null
+++ b/WebCore/rendering/SVGInlineTextBox.cpp
@@ -0,0 +1,550 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2007 Rob Buis <[email protected]>
+ *           (C) 2007 Nikolas Zimmermann <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGInlineTextBox.h"
+
+#include "Document.h"
+#include "Editor.h"
+#include "Frame.h"
+#include "GraphicsContext.h"
+#include "InlineFlowBox.h"
+#include "Range.h"
+#include "SVGPaintServer.h"
+#include "SVGRootInlineBox.h"
+#include "Text.h"
+
+#include <float.h>
+
+using std::max;
+
+namespace WebCore {
+
+SVGInlineTextBox::SVGInlineTextBox(RenderObject* obj)
+    : InlineTextBox(obj)
+{
+}
+
+int SVGInlineTextBox::selectionTop()
+{
+    return m_y;
+}
+ 
+int SVGInlineTextBox::selectionHeight()
+{
+    return m_height;
+}
+
+SVGRootInlineBox* SVGInlineTextBox::svgRootInlineBox() const
+{
+    // Find associated root inline box
+    InlineFlowBox* parentBox = parent();
+
+    while (parentBox && !parentBox->isRootInlineBox())
+        parentBox = parentBox->parent();
+
+    ASSERT(parentBox);
+    ASSERT(parentBox->isRootInlineBox());
+
+    if (!parentBox->isSVGRootInlineBox())
+        return 0;
+
+    return static_cast<SVGRootInlineBox*>(parentBox);
+}
+
+float SVGInlineTextBox::calculateGlyphWidth(RenderStyle* style, int offset, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
+{
+    ASSERT(style);
+    return style->font().floatWidth(svgTextRunForInlineTextBox(textObject()->text()->characters() + offset, 1, style, this, 0), extraCharsAvailable, charsConsumed, glyphName);
+}
+
+float SVGInlineTextBox::calculateGlyphHeight(RenderStyle* style, int offset, int extraCharsAvailable) const
+{
+    ASSERT(style);
+
+    // This is just a guess, and the only purpose of this function is to centralize this hack.
+    // In real-life top-top-bottom scripts this won't be enough, I fear.
+    return style->font().ascent() + style->font().descent();
+}
+
+FloatRect SVGInlineTextBox::calculateGlyphBoundaries(RenderStyle* style, int offset, const SVGChar& svgChar) const
+{
+    const Font& font = style->font();
+
+    // Take RTL text into account and pick right glyph width/height.
+    float glyphWidth = 0.0f;
+
+    // FIXME: account for multi-character glyphs
+    int charsConsumed;
+    String glyphName;
+    if (direction() == LTR)
+        glyphWidth = calculateGlyphWidth(style, offset, 0, charsConsumed, glyphName);
+    else
+        glyphWidth = calculateGlyphWidth(style, start() + end() - offset, 0, charsConsumed, glyphName);
+
+    float x1 = svgChar.x;
+    float x2 = svgChar.x + glyphWidth;
+
+    float y1 = svgChar.y - font.ascent();
+    float y2 = svgChar.y + font.descent();
+
+    FloatRect glyphRect(x1, y1, x2 - x1, y2 - y1);
+
+    // Take per-character transformations into account
+    AffineTransform ctm = svgChar.characterTransform();
+    if (!ctm.isIdentity())
+        glyphRect = ctm.mapRect(glyphRect);
+
+    return glyphRect;
+}
+
+// Helper class for closestCharacterToPosition()
+struct SVGInlineTextBoxClosestCharacterToPositionWalker {
+    SVGInlineTextBoxClosestCharacterToPositionWalker(int x, int y)
+        : m_character(0)
+        , m_distance(FLT_MAX)
+        , m_x(x)
+        , m_y(y)
+        , m_offset(0)
+    {
+    }
+
+    void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm,
+                              const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)
+    {
+        RenderStyle* style = textBox->textObject()->style();
+
+        Vector<SVGChar>::iterator closestCharacter = 0;
+        unsigned int closestOffset = UINT_MAX;
+
+        for (Vector<SVGChar>::iterator it = start; it != end; ++it) {
+            if (it->isHidden())
+                continue;
+
+            unsigned int newOffset = textBox->start() + (it - start) + startOffset;
+            FloatRect glyphRect = chunkCtm.mapRect(textBox->calculateGlyphBoundaries(style, newOffset, *it));
+
+            // Take RTL text into account and pick right glyph width/height.
+            // NOTE: This offset has to be corrected _after_ calling calculateGlyphBoundaries
+            if (textBox->direction() == RTL)
+                newOffset = textBox->start() + textBox->end() - newOffset;
+
+            // Calculate distances relative to the glyph mid-point. I hope this is accurate enough.
+            float xDistance = glyphRect.x() + glyphRect.width() / 2.0f - m_x;
+            float yDistance = glyphRect.y() - glyphRect.height() / 2.0f - m_y;
+
+            float newDistance = sqrtf(xDistance * xDistance + yDistance * yDistance);
+            if (newDistance <= m_distance) {
+                m_distance = newDistance;
+                closestOffset = newOffset;
+                closestCharacter = it;
+            }
+        }
+
+        if (closestOffset != UINT_MAX) {
+            // Record current chunk, if it contains the current closest character next to the mouse.
+            m_character = closestCharacter;
+            m_offset = closestOffset;
+        }
+    }
+
+    SVGChar* character() const
+    {
+        return m_character;
+    }
+
+    int offset() const
+    {
+        if (!m_character)
+            return 0;
+
+        return m_offset;
+    }
+
+private:
+    Vector<SVGChar>::iterator m_character;
+    float m_distance;
+
+    int m_x;
+    int m_y;
+    int m_offset;
+};
+
+// Helper class for selectionRect()
+struct SVGInlineTextBoxSelectionRectWalker {
+    SVGInlineTextBoxSelectionRectWalker()
+    {
+    }
+
+    void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm,
+                              const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)
+    {
+        RenderStyle* style = textBox->textObject()->style();
+
+        for (Vector<SVGChar>::iterator it = start; it != end; ++it) {
+            if (it->isHidden())
+                continue;
+
+            unsigned int newOffset = textBox->start() + (it - start) + startOffset;
+            m_selectionRect.unite(textBox->calculateGlyphBoundaries(style, newOffset, *it));
+        }
+
+        m_selectionRect = chunkCtm.mapRect(m_selectionRect);
+    }
+
+    FloatRect selectionRect() const
+    {
+        return m_selectionRect;
+    }
+
+private:
+    FloatRect m_selectionRect;
+};
+
+SVGChar* SVGInlineTextBox::closestCharacterToPosition(int x, int y, int& offset) const
+{
+    SVGRootInlineBox* rootBox = svgRootInlineBox();
+    if (!rootBox)
+        return 0;
+
+    SVGInlineTextBoxClosestCharacterToPositionWalker walkerCallback(x, y);
+    SVGTextChunkWalker<SVGInlineTextBoxClosestCharacterToPositionWalker> walker(&walkerCallback, &SVGInlineTextBoxClosestCharacterToPositionWalker::chunkPortionCallback);
+
+    rootBox->walkTextChunks(&walker, this);
+
+    offset = walkerCallback.offset();
+    return walkerCallback.character();
+}
+
+bool SVGInlineTextBox::svgCharacterHitsPosition(int x, int y, int& offset) const
+{
+    SVGChar* charAtPosPtr = closestCharacterToPosition(x, y, offset);
+    if (!charAtPosPtr)
+        return false;
+
+    SVGChar& charAtPos = *charAtPosPtr;
+    RenderStyle* style = textObject()->style(m_firstLine);
+    FloatRect glyphRect = calculateGlyphBoundaries(style, offset, charAtPos);
+
+    if (direction() == RTL)
+        offset++;
+
+    // FIXME: todo list
+    // (#13910) This code does not handle bottom-to-top/top-to-bottom vertical text.
+
+    // Check whether y position hits the current character 
+    if (y < charAtPos.y - glyphRect.height() || y > charAtPos.y)
+        return false;
+
+    // Check whether x position hits the current character
+    if (x < charAtPos.x) {
+        if (offset > 0 && direction() == LTR)
+            return true;
+        else if (offset < (int) end() && direction() == RTL)
+            return true;
+
+        return false;
+    }
+
+    // If we are past the last glyph of this box, don't mark it as 'hit' anymore.
+    if (x >= charAtPos.x + glyphRect.width() && offset == (int) end())
+        return false;
+
+    // Snap to character at half of it's advance
+    if (x >= charAtPos.x + glyphRect.width() / 2.0)
+        offset += direction() == RTL ? -1 : 1;
+
+    return true;
+}
+
+int SVGInlineTextBox::offsetForPosition(int x, bool includePartialGlyphs) const
+{
+    // SVG doesn't use the offset <-> position selection system. 
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+int SVGInlineTextBox::positionForOffset(int offset) const
+{
+    // SVG doesn't use the offset <-> position selection system. 
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+{
+    ASSERT(!isLineBreak());
+
+    IntRect rect = selectionRect(0, 0, 0, len());
+    if (object()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
+        object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
+        return true;
+    }
+
+    return false;
+}
+
+IntRect SVGInlineTextBox::selectionRect(int, int, int startPos, int endPos)
+{
+    if (startPos >= endPos)
+        return IntRect();
+
+    // TODO: Actually respect startPos/endPos - we're returning the _full_ selectionRect
+    // here. This won't lead to visible bugs, but to extra work being done. Investigate.
+    SVGRootInlineBox* rootBox = svgRootInlineBox();
+    if (!rootBox)
+        return IntRect();
+
+    SVGInlineTextBoxSelectionRectWalker walkerCallback;
+    SVGTextChunkWalker<SVGInlineTextBoxSelectionRectWalker> walker(&walkerCallback, &SVGInlineTextBoxSelectionRectWalker::chunkPortionCallback);
+
+    rootBox->walkTextChunks(&walker, this);
+    return enclosingIntRect(walkerCallback.selectionRect());
+}
+
+void SVGInlineTextBox::paintCharacters(RenderObject::PaintInfo& paintInfo, int tx, int ty, const SVGChar& svgChar, const UChar* chars, int length, SVGPaintServer* activePaintServer)
+{
+    if (object()->style()->visibility() != VISIBLE || paintInfo.phase == PaintPhaseOutline)
+        return;
+
+    ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines);
+
+    RenderText* text = textObject();
+    ASSERT(text);
+
+    bool isPrinting = text->document()->printing();
+
+    // Determine whether or not we're selected.
+    bool haveSelection = !isPrinting && selectionState() != RenderObject::SelectionNone;
+    if (!haveSelection && paintInfo.phase == PaintPhaseSelection)
+        // When only painting the selection, don't bother to paint if there is none.
+        return;
+
+    // Determine whether or not we have a composition.
+    bool containsComposition = text->document()->frame()->editor()->compositionNode() == text->node();
+    bool useCustomUnderlines = containsComposition && text->document()->frame()->editor()->compositionUsesCustomUnderlines();
+
+    // Set our font
+    RenderStyle* styleToUse = text->style(isFirstLineStyle());
+    const Font* font = &styleToUse->font();
+    if (*font != paintInfo.context->font())
+        paintInfo.context->setFont(*font);
+
+    AffineTransform ctm = svgChar.characterTransform();
+    if (!ctm.isIdentity())
+        paintInfo.context->concatCTM(ctm);
+
+    // 1. Paint backgrounds behind text if needed.  Examples of such backgrounds include selection
+    // and marked text.
+    if (paintInfo.phase != PaintPhaseSelection && !isPrinting) {
+#if PLATFORM(MAC)
+        // Custom highlighters go behind everything else.
+        if (styleToUse->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
+            paintCustomHighlight(tx, ty, styleToUse->highlight());
+#endif
+
+        if (containsComposition && !useCustomUnderlines)
+            paintCompositionBackground(paintInfo.context, tx, ty, styleToUse, font, 
+                                                text->document()->frame()->editor()->compositionStart(),
+                                                text->document()->frame()->editor()->compositionEnd());
+        
+        paintDocumentMarkers(paintInfo.context, tx, ty, styleToUse, font, true);
+
+        if (haveSelection && !useCustomUnderlines) {
+            int boxStartOffset = chars - text->characters() - start();
+            paintSelection(boxStartOffset, svgChar, chars, length, paintInfo.context, styleToUse, font);
+        }
+    }
+
+    // Set a text shadow if we have one.
+    // FIXME: Support multiple shadow effects.  Need more from the CG API before
+    // we can do this.
+    bool setShadow = false;
+    if (styleToUse->textShadow()) {
+        paintInfo.context->setShadow(IntSize(styleToUse->textShadow()->x, styleToUse->textShadow()->y),
+                                     styleToUse->textShadow()->blur, styleToUse->textShadow()->color);
+        setShadow = true;
+    }
+
+    IntPoint origin((int) svgChar.x, (int) svgChar.y);
+    TextRun run = svgTextRunForInlineTextBox(chars, length, styleToUse, this, svgChar.x);
+
+#if ENABLE(SVG_FONTS)
+    // SVG Fonts need access to the paint server used to draw the current text chunk.
+    // They need to be able to call renderPath() on a SVGPaintServer object.
+    run.setActivePaintServer(activePaintServer);
+#endif
+
+    paintInfo.context->drawText(run, origin);
+
+    if (paintInfo.phase != PaintPhaseSelection) {
+        paintDocumentMarkers(paintInfo.context, tx, ty, styleToUse, font, false);
+
+        if (useCustomUnderlines) {
+            const Vector<CompositionUnderline>& underlines = text->document()->frame()->editor()->customCompositionUnderlines();
+            size_t numUnderlines = underlines.size();
+            
+            for (size_t index = 0; index < numUnderlines; ++index) {
+                const CompositionUnderline& underline = underlines[index];
+                
+                if (underline.endOffset <= start())
+                    // underline is completely before this run.  This might be an underline that sits
+                    // before the first run we draw, or underlines that were within runs we skipped 
+                    // due to truncation.
+                    continue;
+                
+                if (underline.startOffset <= end()) {
+                    // underline intersects this run.  Paint it.
+                    paintCompositionUnderline(paintInfo.context, tx, ty, underline);
+                    if (underline.endOffset > end() + 1)
+                        // underline also runs into the next run. Bail now, no more marker advancement.
+                        break;
+                } else
+                    // underline is completely after this run, bail.  A later run will paint it.
+                    break;
+            }
+        }
+        
+    }
+
+    if (setShadow)
+        paintInfo.context->clearShadow();
+
+    if (!ctm.isIdentity())
+        paintInfo.context->concatCTM(ctm.inverse());
+}
+
+void SVGInlineTextBox::paintSelection(int boxStartOffset, const SVGChar& svgChar, const UChar* chars, int length, GraphicsContext* p, RenderStyle* style, const Font* f)
+{
+    if (selectionState() == RenderObject::SelectionNone)
+        return;
+
+    int startPos, endPos;
+    selectionStartEnd(startPos, endPos);
+
+    if (startPos >= endPos)
+        return;
+
+    Color textColor = style->color();
+    Color color = object()->selectionBackgroundColor();
+    if (!color.isValid() || color.alpha() == 0)
+        return;
+
+    // If the text color ends up being the same as the selection background, invert the selection
+    // background.  This should basically never happen, since the selection has transparency.
+    if (textColor == color)
+        color = Color(0xff - color.red(), 0xff - color.green(), 0xff - color.blue());
+
+    // Map from text box positions and a given start offset to chunk positions
+    // 'boxStartOffset' represents the beginning of the text chunk.
+    if ((startPos > boxStartOffset && endPos > boxStartOffset + length) || boxStartOffset >= endPos)
+        return;
+
+    if (endPos > boxStartOffset + length)
+        endPos = boxStartOffset + length;
+
+    if (startPos < boxStartOffset)
+        startPos = boxStartOffset;
+
+    ASSERT(startPos >= boxStartOffset);
+    ASSERT(endPos <= boxStartOffset + length);
+    ASSERT(startPos < endPos);
+
+    p->save();
+
+    int adjust = startPos >= boxStartOffset ? boxStartOffset : 0;
+    p->drawHighlightForText(svgTextRunForInlineTextBox(textObject()->text()->characters() + start() + boxStartOffset, length, style, this, svgChar.x),
+                            IntPoint((int) svgChar.x, (int) svgChar.y - f->ascent()),
+                            f->ascent() + f->descent(), color, startPos - adjust, endPos - adjust);
+
+    p->restore();
+}
+
+static inline Path pathForDecoration(ETextDecoration decoration, RenderObject* object, float x, float y, float width)
+{
+    float thickness = SVGRenderStyle::cssPrimitiveToLength(object, object->style()->svgStyle()->strokeWidth(), 1.0f);
+
+    const Font& font = object->style()->font();
+    thickness = max(thickness * powf(font.size(), 2.0f) / font.unitsPerEm(), 1.0f);
+
+    if (decoration == UNDERLINE)
+        y += thickness * 1.5f; // For compatibility with Batik/Opera
+    else if (decoration == OVERLINE)
+        y += thickness;
+
+    float halfThickness = thickness / 2.0f;
+    return Path::createRectangle(FloatRect(x + halfThickness, y, width - 2.0f * halfThickness, thickness));
+}
+
+void SVGInlineTextBox::paintDecoration(ETextDecoration decoration, GraphicsContext* context, int tx, int ty, int width, const SVGChar& svgChar, const SVGTextDecorationInfo& info)
+{
+    if (object()->style()->visibility() != VISIBLE)
+        return;
+
+    // This function does NOT accept combinated text decorations. It's meant to be invoked for just one.
+    ASSERT(decoration == TDNONE || decoration == UNDERLINE || decoration == OVERLINE || decoration == LINE_THROUGH || decoration == BLINK);
+
+    bool isFilled = info.fillServerMap.contains(decoration);
+    bool isStroked = info.strokeServerMap.contains(decoration);
+
+    if (!isFilled && !isStroked)
+        return;
+
+    if (decoration == UNDERLINE)
+        ty += m_baseline;
+    else if (decoration == LINE_THROUGH)
+        ty += 2 * m_baseline / 3;
+
+    context->save();
+    context->beginPath();
+
+    AffineTransform ctm = svgChar.characterTransform();
+    if (!ctm.isIdentity())
+        context->concatCTM(ctm);
+
+    if (isFilled) {
+        if (RenderObject* fillObject = info.fillServerMap.get(decoration)) {
+            if (SVGPaintServer* fillPaintServer = SVGPaintServer::fillPaintServer(fillObject->style(), fillObject)) {
+                context->addPath(pathForDecoration(decoration, fillObject, tx, ty, width));
+                fillPaintServer->draw(context, fillObject, ApplyToFillTargetType);
+            }
+        }
+    }
+
+    if (isStroked) {
+        if (RenderObject* strokeObject = info.strokeServerMap.get(decoration)) {
+            if (SVGPaintServer* strokePaintServer = SVGPaintServer::strokePaintServer(strokeObject->style(), strokeObject)) {
+                context->addPath(pathForDecoration(decoration, strokeObject, tx, ty, width));
+                strokePaintServer->draw(context, strokeObject, ApplyToStrokeTargetType);
+            }
+        }
+    }
+
+    context->restore();
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/rendering/SVGInlineTextBox.h b/WebCore/rendering/SVGInlineTextBox.h
new file mode 100644
index 0000000..1ddc23a
--- /dev/null
+++ b/WebCore/rendering/SVGInlineTextBox.h
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2007 Rob Buis <[email protected]>
+ *           (C) 2007 Nikolas Zimmermann <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SVGInlineTextBox_h
+#define SVGInlineTextBox_h
+
+#if ENABLE(SVG)
+#include "InlineTextBox.h"
+
+namespace WebCore {
+
+    class SVGChar;
+    class SVGRootInlineBox;
+    class SVGTextDecorationInfo;
+
+    class SVGInlineTextBox : public InlineTextBox {
+    public:
+        SVGInlineTextBox(RenderObject* obj);
+
+        virtual int selectionTop();
+        virtual int selectionHeight();
+
+        virtual int offsetForPosition(int x, bool includePartialGlyphs = true) const;
+        virtual int positionForOffset(int offset) const;
+
+        virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
+        virtual IntRect selectionRect(int absx, int absy, int startPos, int endPos);
+
+        // SVGs custom paint text method
+        void paintCharacters(RenderObject::PaintInfo&, int tx, int ty, const SVGChar&, const UChar* chars, int length, SVGPaintServer*);
+
+        // SVGs custom paint selection method
+        void paintSelection(int boxStartOffset, const SVGChar&, const UChar*, int length, GraphicsContext*, RenderStyle*, const Font*);
+
+        // SVGs custom paint decoration method
+        void paintDecoration(ETextDecoration, GraphicsContext*, int tx, int ty, int width, const SVGChar&, const SVGTextDecorationInfo&);
+ 
+        SVGRootInlineBox* svgRootInlineBox() const;
+
+        // Helper functions shared with SVGRootInlineBox     
+        float calculateGlyphWidth(RenderStyle* style, int offset, int extraCharsAvailable, int& charsConsumed, String& glyphName) const;
+        float calculateGlyphHeight(RenderStyle*, int offset, int extraCharsAvailable) const;
+
+        FloatRect calculateGlyphBoundaries(RenderStyle*, int offset, const SVGChar&) const;
+        SVGChar* closestCharacterToPosition(int x, int y, int& offset) const;
+
+    private:
+        friend class RenderSVGInlineText;
+        bool svgCharacterHitsPosition(int x, int y, int& offset) const;
+    };
+
+} // namespace WebCore
+
+#endif
+#endif // SVGInlineTextBox_h
diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp
new file mode 100644
index 0000000..f3223f1
--- /dev/null
+++ b/WebCore/rendering/SVGRenderSupport.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2007, 2008 Rob Buis <[email protected]>
+ *           (C) 2007 Nikolas Zimmermann <[email protected]>
+ *           (C) 2007 Eric Seidel <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGRenderSupport.h"
+
+#include "AffineTransform.h"
+#include "ImageBuffer.h"
+#include "RenderObject.h"
+#include "RenderSVGContainer.h"
+#include "RenderView.h"
+#include "SVGResourceClipper.h"
+#include "SVGResourceFilter.h"
+#include "SVGResourceMasker.h"
+#include "SVGStyledElement.h"
+#include "SVGURIReference.h"
+
+namespace WebCore {
+
+void prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, SVGResourceFilter* rootFilter)
+{    
+    SVGElement* svgElement = static_cast<SVGElement*>(object->element());
+    ASSERT(svgElement && svgElement->document() && svgElement->isStyled());
+    ASSERT(object);
+
+    SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
+    const RenderStyle* style = object->style();
+    ASSERT(style);
+
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+    ASSERT(svgStyle);
+
+    // Setup transparency layers before setting up filters!
+    float opacity = style->opacity(); 
+    if (opacity < 1.0f) {
+        paintInfo.context->clip(enclosingIntRect(boundingBox));
+        paintInfo.context->beginTransparencyLayer(opacity);
+    }
+
+#if ENABLE(SVG_FILTERS)
+    AtomicString filterId(svgStyle->filter());
+#endif
+
+    AtomicString clipperId(svgStyle->clipPath());
+    AtomicString maskerId(svgStyle->maskElement());
+
+    Document* document = object->document();
+
+#if ENABLE(SVG_FILTERS)
+    SVGResourceFilter* newFilter = getFilterById(document, filterId);
+    if (newFilter == rootFilter) {
+        // Catch <text filter="url(#foo)">Test<tspan filter="url(#foo)">123</tspan></text>.
+        // The filter is NOT meant to be applied twice in that case!
+        filter = 0;
+        filterId = String();
+    } else
+        filter = newFilter;
+#endif
+
+    SVGResourceClipper* clipper = getClipperById(document, clipperId);
+    SVGResourceMasker* masker = getMaskerById(document, maskerId);
+
+#if ENABLE(SVG_FILTERS)
+    if (filter) {
+        filter->addClient(styledElement);
+        filter->prepareFilter(paintInfo.context, boundingBox);
+    } else if (!filterId.isEmpty())
+        svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement);
+#endif
+
+    if (clipper) {
+        clipper->addClient(styledElement);
+        clipper->applyClip(paintInfo.context, boundingBox);
+    } else if (!clipperId.isEmpty())
+        svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement);
+
+    if (masker) {
+        masker->addClient(styledElement);
+        masker->applyMask(paintInfo.context, boundingBox);
+    } else if (!maskerId.isEmpty())
+        svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement);
+}
+
+void finishRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, GraphicsContext* savedContext)
+{
+    ASSERT(object);
+
+    const RenderStyle* style = object->style();
+    ASSERT(style);
+
+#if ENABLE(SVG_FILTERS)
+    if (filter) {
+        filter->applyFilter(paintInfo.context, boundingBox);
+        paintInfo.context = savedContext;
+    }
+#endif
+
+    float opacity = style->opacity();    
+    if (opacity < 1.0f)
+        paintInfo.context->endTransparencyLayer();
+}
+
+void renderSubtreeToImage(ImageBuffer* image, RenderObject* item)
+{
+    ASSERT(item);
+    ASSERT(image);
+    ASSERT(image->context());
+    RenderObject::PaintInfo info(image->context(), IntRect(), PaintPhaseForeground, 0, 0, 0);
+
+    RenderSVGContainer* svgContainer = 0;
+    if (item && item->isSVGContainer())
+        svgContainer = static_cast<RenderSVGContainer*>(item);
+
+    bool drawsContents = svgContainer ? svgContainer->drawsContents() : false;
+    if (svgContainer && !drawsContents)
+        svgContainer->setDrawsContents(true);
+
+    item->layoutIfNeeded();
+    item->paint(info, 0, 0);
+
+    if (svgContainer && !drawsContents)
+        svgContainer->setDrawsContents(false);
+}
+
+void clampImageBufferSizeToViewport(RenderObject* object, IntSize& size)
+{
+    if (!object || !object->isRenderView())
+        return;
+
+    RenderView* view = static_cast<RenderView*>(object);
+    if (!view->frameView())
+        return;
+
+    int viewWidth = view->frameView()->visibleWidth();
+    int viewHeight = view->frameView()->visibleHeight();
+
+    if (size.width() > viewWidth)
+        size.setWidth(viewWidth);
+
+    if (size.height() > viewHeight)
+        size.setHeight(viewHeight);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/SVGRenderSupport.h b/WebCore/rendering/SVGRenderSupport.h
new file mode 100644
index 0000000..7fdfcf8
--- /dev/null
+++ b/WebCore/rendering/SVGRenderSupport.h
@@ -0,0 +1,42 @@
+/**
+ * This file is part of the DOM implementation for WebKit.
+ *
+ * Copyright (C) 2007 Rob Buis <[email protected]>
+ *           (C) 2007 Nikolas Zimmermann <[email protected]>
+ *           (C) 2007 Eric Seidel <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if ENABLE(SVG)
+#include "RenderObject.h"
+
+namespace WebCore {
+
+class SVGResourceFilter;
+void prepareToRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, SVGResourceFilter*&, SVGResourceFilter* rootFilter = 0);
+void finishRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, SVGResourceFilter*&, GraphicsContext* savedContext);
+
+// This offers a way to render parts of a WebKit rendering tree into a ImageBuffer.
+class ImageBuffer;
+void renderSubtreeToImage(ImageBuffer*, RenderObject*);
+
+void clampImageBufferSizeToViewport(RenderObject*, IntSize&);
+
+}
+
+#endif
diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp
new file mode 100644
index 0000000..d3e029c
--- /dev/null
+++ b/WebCore/rendering/SVGRenderTreeAsText.cpp
@@ -0,0 +1,562 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Apple Inc. All rights reserved.
+ *           (C) 2005 Rob Buis <[email protected]>
+ *           (C) 2006 Alexander Kellett <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGRenderTreeAsText.h"
+
+#include "GraphicsTypes.h"
+#include "InlineTextBox.h"
+#include "HTMLNames.h"
+#include "RenderSVGContainer.h"
+#include "RenderSVGInlineText.h"
+#include "RenderSVGText.h"
+#include "RenderSVGRoot.h"
+#include "RenderTreeAsText.h"
+#include "SVGCharacterLayoutInfo.h"
+#include "SVGInlineTextBox.h"
+#include "SVGPaintServerGradient.h"
+#include "SVGPaintServerPattern.h"
+#include "SVGPaintServerSolid.h"
+#include "SVGResourceClipper.h"
+#include "SVGRootInlineBox.h"
+#include "SVGStyledElement.h"
+#include <math.h>
+
+namespace WebCore {
+
+/** class + iomanip to help streaming list separators, i.e. ", " in string "a, b, c, d"
+ * Can be used in cases where you don't know which item in the list is the first
+ * one to be printed, but still want to avoid strings like ", b, c".
+ */
+class TextStreamSeparator {
+public:
+    TextStreamSeparator(const String& s)
+        : m_separator(s)
+        , m_needToSeparate(false)
+    {
+    }
+
+private:
+    friend TextStream& operator<<(TextStream&, TextStreamSeparator&);
+
+    String m_separator;
+    bool m_needToSeparate;
+};
+
+TextStream& operator<<(TextStream& ts, TextStreamSeparator& sep)
+{
+    if (sep.m_needToSeparate)
+        ts << sep.m_separator;
+    else
+        sep.m_needToSeparate = true;
+    return ts;
+}
+
+TextStream& operator<<(TextStream& ts, const IntPoint& p)
+{
+    return ts << "(" << p.x() << "," << p.y() << ")";
+}
+
+TextStream& operator<<(TextStream& ts, const IntRect& r)
+{
+    return ts << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
+}
+
+bool hasFractions(double val)
+{
+    double epsilon = 0.0001;
+    int ival = static_cast<int>(val);
+    double dval = static_cast<double>(ival);
+    return fabs(val - dval) > epsilon;
+}
+
+TextStream& operator<<(TextStream& ts, const FloatRect &r)
+{
+    ts << "at ("; 
+    if (hasFractions(r.x())) 
+        ts << r.x();
+    else 
+        ts << int(r.x());
+    ts << ",";
+    if (hasFractions(r.y())) 
+        ts << r.y();
+    else 
+        ts << int(r.y());
+    ts << ") size ";
+    if (hasFractions(r.width())) 
+        ts << r.width(); 
+    else 
+        ts << int(r.width()); 
+    ts << "x";
+    if (hasFractions(r.height())) 
+        ts << r.height();
+    else 
+        ts << int(r.height());
+    return ts;
+}
+
+TextStream& operator<<(TextStream& ts, const FloatPoint& p)
+{
+    ts << "(";    
+    if (hasFractions(p.x()))
+        ts << p.x();
+    else 
+        ts << int(p.x());    
+    ts << ",";
+    if (hasFractions(p.y())) 
+        ts << p.y();
+    else 
+        ts << int(p.y());    
+    return ts << ")";
+}
+
+TextStream& operator<<(TextStream& ts, const FloatSize& s)
+{
+    ts << "width=";
+    if (hasFractions(s.width()))
+        ts << s.width();
+    else
+        ts << int(s.width());
+    ts << " height=";
+    if (hasFractions(s.height())) 
+        ts << s.height();
+    else
+        ts << int(s.height());
+    return ts;
+}
+
+TextStream& operator<<(TextStream& ts, const AffineTransform& transform)
+{
+    if (transform.isIdentity())
+        ts << "identity";
+    else
+        ts << "{m=(("
+           << transform.a() << "," << transform.b()
+           << ")("
+           << transform.c() << "," << transform.d()
+           << ")) t=("
+           << transform.e() << "," << transform.f()
+           << ")}";
+
+    return ts;
+}
+
+TextStream& operator<<(TextStream& ts, const Color& c)
+{
+    return ts << c.name();
+}
+
+static void writeIndent(TextStream& ts, int indent)
+{
+    for (int i = 0; i != indent; ++i)
+        ts << "  ";
+}
+
+// FIXME: Maybe this should be in KCanvasRenderingStyle.cpp
+static TextStream& operator<<(TextStream& ts, const DashArray& a)
+{
+    ts << "{";
+    DashArray::const_iterator end = a.end();
+    for (DashArray::const_iterator it = a.begin(); it != end; ++it) {
+        if (it != a.begin())
+            ts << ", ";
+        ts << *it;
+    }
+    ts << "}";
+    return ts;
+}
+
+// FIXME: Maybe this should be in GraphicsTypes.cpp
+static TextStream& operator<<(TextStream& ts, LineCap style)
+{
+    switch (style) {
+        case ButtCap:
+            ts << "BUTT";
+            break;
+        case RoundCap:
+            ts << "ROUND";
+            break;
+        case SquareCap:
+            ts << "SQUARE";
+            break;
+    }
+    return ts;
+}
+
+// FIXME: Maybe this should be in GraphicsTypes.cpp
+static TextStream& operator<<(TextStream& ts, LineJoin style)
+{
+    switch (style) {
+        case MiterJoin:
+            ts << "MITER";
+            break;
+        case RoundJoin:
+            ts << "ROUND";
+            break;
+        case BevelJoin:
+            ts << "BEVEL";
+            break;
+    }
+    return ts;
+}
+
+static void writeStyle(TextStream& ts, const RenderObject& object)
+{
+    const RenderStyle* style = object.style();
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+
+    if (!object.localTransform().isIdentity())
+        ts << " [transform=" << object.localTransform() << "]";
+    if (svgStyle->imageRendering() != SVGRenderStyle::initialImageRendering())
+        ts << " [image rendering=" << svgStyle->imageRendering() << "]";
+    if (style->opacity() != RenderStyle::initialOpacity())
+        ts << " [opacity=" << style->opacity() << "]";
+    if (object.isRenderPath()) {
+        const RenderPath& path = static_cast<const RenderPath&>(object);
+        SVGPaintServer* strokePaintServer = SVGPaintServer::strokePaintServer(style, &path);
+        if (strokePaintServer) {
+            TextStreamSeparator s(" ");
+            ts << " [stroke={";
+            if (strokePaintServer)
+                ts << s << *strokePaintServer;
+
+            double dashOffset = SVGRenderStyle::cssPrimitiveToLength(&path, svgStyle->strokeDashOffset(), 0.0f);
+            const DashArray& dashArray = dashArrayFromRenderingStyle(style);
+            double strokeWidth = SVGRenderStyle::cssPrimitiveToLength(&path, svgStyle->strokeWidth(), 1.0f);
+
+            if (svgStyle->strokeOpacity() != 1.0f)
+                ts << s << "[opacity=" << svgStyle->strokeOpacity() << "]";
+            if (strokeWidth != 1.0f)
+                ts << s << "[stroke width=" << strokeWidth << "]";
+            if (svgStyle->strokeMiterLimit() != 4)
+                ts << s << "[miter limit=" << svgStyle->strokeMiterLimit() << "]";
+            if (svgStyle->capStyle() != 0)
+                ts << s << "[line cap=" << svgStyle->capStyle() << "]";
+            if (svgStyle->joinStyle() != 0)
+                ts << s << "[line join=" << svgStyle->joinStyle() << "]";
+            if (dashOffset != 0.0f)
+                ts << s << "[dash offset=" << dashOffset << "]";
+            if (!dashArray.isEmpty())
+                ts << s << "[dash array=" << dashArray << "]";
+            ts << "}]";
+        }
+        SVGPaintServer* fillPaintServer = SVGPaintServer::fillPaintServer(style, &path);
+        if (fillPaintServer) {
+            TextStreamSeparator s(" ");
+            ts << " [fill={";
+            if (fillPaintServer)
+                ts << s << *fillPaintServer;
+
+            if (style->svgStyle()->fillOpacity() != 1.0f)
+                ts << s << "[opacity=" << style->svgStyle()->fillOpacity() << "]";
+            if (style->svgStyle()->fillRule() != RULE_NONZERO)
+                ts << s << "[fill rule=" << style->svgStyle()->fillRule() << "]";
+            ts << "}]";
+        }
+    }
+    if (!svgStyle->clipPath().isEmpty())
+        ts << " [clip path=\"" << svgStyle->clipPath() << "\"]";
+    if (!svgStyle->startMarker().isEmpty())
+        ts << " [start marker=" << svgStyle->startMarker() << "]";
+    if (!svgStyle->midMarker().isEmpty())
+        ts << " [middle marker=" << svgStyle->midMarker() << "]";
+    if (!svgStyle->endMarker().isEmpty())
+        ts << " [end marker=" << svgStyle->endMarker() << "]";
+    if (!svgStyle->filter().isEmpty())
+        ts << " [filter=" << svgStyle->filter() << "]";
+}
+
+static TextStream& operator<<(TextStream& ts, const RenderPath& path)
+{
+    ts << " " << path.absoluteTransform().mapRect(path.relativeBBox());
+
+    writeStyle(ts, path);
+
+    ts << " [data=\"" << path.path().debugString() << "\"]";
+
+    return ts;
+}
+
+static TextStream& operator<<(TextStream& ts, const RenderSVGContainer& container)
+{
+    ts << " " << container.absoluteTransform().mapRect(container.relativeBBox());
+
+    writeStyle(ts, container);
+
+    return ts;
+}
+
+static TextStream& operator<<(TextStream& ts, const RenderSVGRoot& root)
+{
+    ts << " " << root.absoluteTransform().mapRect(root.relativeBBox());
+
+    writeStyle(ts, root);
+
+    return ts;
+}
+
+static TextStream& operator<<(TextStream& ts, const RenderSVGText& text)
+{
+    SVGRootInlineBox* box = static_cast<SVGRootInlineBox*>(text.firstRootBox());
+
+    if (!box)
+        return ts;
+
+    Vector<SVGTextChunk>& chunks = const_cast<Vector<SVGTextChunk>& >(box->svgTextChunks());
+    ts << " at (" << text.xPos() << "," << text.yPos() << ") size " << box->width() << "x" << box->height() << " contains " << chunks.size() << " chunk(s)";
+
+    if (text.parent() && (text.parent()->style()->color() != text.style()->color()))
+        ts << " [color=" << text.style()->color().name() << "]";
+
+    return ts;
+}
+
+static inline bool containsInlineTextBox(SVGTextChunk& chunk, SVGInlineTextBox* box)
+{
+    Vector<SVGInlineBoxCharacterRange>::iterator boxIt = chunk.boxes.begin();
+    Vector<SVGInlineBoxCharacterRange>::iterator boxEnd = chunk.boxes.end();
+
+    bool found = false;
+    for (; boxIt != boxEnd; ++boxIt) {
+        SVGInlineBoxCharacterRange& range = *boxIt;
+
+        if (box == static_cast<SVGInlineTextBox*>(range.box)) {
+            found = true;
+            break;
+        }
+    }
+
+    return found;
+}
+
+static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textBox, int indent)
+{
+    SVGRootInlineBox* rootBox = textBox->svgRootInlineBox();
+    if (!rootBox)
+        return;
+
+    Vector<SVGTextChunk>& chunks = const_cast<Vector<SVGTextChunk>& >(rootBox->svgTextChunks());
+
+    Vector<SVGTextChunk>::iterator it = chunks.begin();
+    Vector<SVGTextChunk>::iterator end = chunks.end();
+
+    // Write text chunks
+    unsigned int i = 1;
+    for (; it != end; ++it) {
+        SVGTextChunk& cur = *it;
+
+        // Write inline box character ranges
+        Vector<SVGInlineBoxCharacterRange>::iterator boxIt = cur.boxes.begin();
+        Vector<SVGInlineBoxCharacterRange>::iterator boxEnd = cur.boxes.end();
+
+        if (!containsInlineTextBox(cur, textBox)) {
+            i++;
+            continue;
+        }
+
+        writeIndent(ts, indent + 1);
+
+        unsigned int j = 1;
+        ts << "chunk " << i << " ";
+
+        if (cur.anchor == TA_MIDDLE) {
+            ts << "(middle anchor";
+            if (cur.isVerticalText)
+                ts << ", vertical";
+            ts << ") ";
+        } else if (cur.anchor == TA_END) {
+            ts << "(end anchor";
+            if (cur.isVerticalText)
+                ts << ", vertical";
+            ts << ") ";
+        } else if (cur.isVerticalText)
+            ts << "(vertical) ";
+
+        unsigned int totalOffset = 0;
+
+        for (; boxIt != boxEnd; ++boxIt) {
+            SVGInlineBoxCharacterRange& range = *boxIt;
+
+            unsigned int offset = range.endOffset - range.startOffset;
+            ASSERT(cur.start + totalOffset <= cur.end);
+    
+            totalOffset += offset;
+      
+            if (textBox != static_cast<SVGInlineTextBox*>(range.box)) {
+                j++;
+                continue;
+            }
+  
+            FloatPoint topLeft = topLeftPositionOfCharacterRange(cur.start + totalOffset - offset, cur.start + totalOffset);
+
+            ts << "text run " << j << " at (" << topLeft.x() << "," << topLeft.y() << ") ";
+            ts << "startOffset " << range.startOffset << " endOffset " << range.endOffset;
+
+            if (cur.isVerticalText)
+                ts << " height " << cummulatedHeightOfInlineBoxCharacterRange(range);
+            else
+                ts << " width " << cummulatedWidthOfInlineBoxCharacterRange(range);
+
+            if (textBox->direction() == RTL || textBox->m_dirOverride) {
+                ts << (textBox->direction() == RTL ? " RTL" : " LTR");
+
+                if (textBox->m_dirOverride)
+                    ts << " override";
+            }
+
+            ts << ": " << quoteAndEscapeNonPrintables(String(textBox->textObject()->text()).substring(textBox->start() + range.startOffset, offset)) << "\n";
+
+            j++;
+        }
+
+        i++;
+    }
+}
+
+static inline void writeSVGInlineText(TextStream& ts, const RenderSVGInlineText& text, int indent)
+{
+    for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox())
+        writeSVGInlineTextBox(ts, static_cast<SVGInlineTextBox*>(box), indent);
+}
+
+static String getTagName(SVGStyledElement* elem)
+{
+    if (elem)
+        return elem->nodeName();
+    return "";
+}
+
+void write(TextStream& ts, const RenderSVGContainer& container, int indent)
+{
+    writeIndent(ts, indent);
+    ts << container.renderName();
+
+    if (container.element()) {
+        String tagName = getTagName(static_cast<SVGStyledElement*>(container.element()));
+        if (!tagName.isEmpty())
+            ts << " {" << tagName << "}";
+    }
+
+    ts << container << "\n";
+
+    for (RenderObject* child = container.firstChild(); child; child = child->nextSibling())
+        write(ts, *child, indent + 1);
+}
+
+void write(TextStream& ts, const RenderSVGRoot& root, int indent)
+{
+    writeIndent(ts, indent);
+    ts << root.renderName();
+
+    if (root.element()) {
+        String tagName = getTagName(static_cast<SVGStyledElement*>(root.element()));
+        if (!tagName.isEmpty())
+            ts << " {" << tagName << "}";
+    }
+
+    ts << root << "\n";
+
+    for (RenderObject* child = root.firstChild(); child; child = child->nextSibling())
+        write(ts, *child, indent + 1);
+}
+
+void write(TextStream& ts, const RenderSVGText& text, int indent)
+{
+    writeIndent(ts, indent);
+    ts << text.renderName();
+
+    if (text.element()) {
+        String tagName = getTagName(static_cast<SVGStyledElement*>(text.element()));
+        if (!tagName.isEmpty())
+            ts << " {" << tagName << "}";
+    }
+
+    ts << text << "\n";
+
+    for (RenderObject* child = text.firstChild(); child; child = child->nextSibling())
+        write(ts, *child, indent + 1);
+}
+
+void write(TextStream& ts, const RenderSVGInlineText& text, int indent)
+{
+    writeIndent(ts, indent);
+    ts << text.renderName();
+
+    if (text.element()) {
+        String tagName = getTagName(static_cast<SVGStyledElement*>(text.element()));
+        if (!tagName.isEmpty())
+            ts << " {" << tagName << "}";
+    }
+
+    ts << " at (" << text.xPos() << "," << text.yPos() << ") size " << text.width() << "x" << text.height() << "\n";
+    writeSVGInlineText(ts, text, indent);
+}
+
+void write(TextStream& ts, const RenderPath& path, int indent)
+{
+    writeIndent(ts, indent);
+    ts << path.renderName();
+
+    if (path.element()) {
+        String tagName = getTagName(static_cast<SVGStyledElement*>(path.element()));
+        if (!tagName.isEmpty())
+            ts << " {" << tagName << "}";
+    }
+
+    ts << path << "\n";
+}
+
+void writeRenderResources(TextStream& ts, Node* parent)
+{
+    ASSERT(parent);
+    Node* node = parent;
+    do {
+        if (!node->isSVGElement())
+            continue;
+        SVGElement* svgElement = static_cast<SVGElement*>(node);
+        if (!svgElement->isStyled())
+            continue;
+
+        SVGStyledElement* styled = static_cast<SVGStyledElement*>(svgElement);
+        RefPtr<SVGResource> resource(styled->canvasResource());
+        if (!resource)
+            continue;
+
+        String elementId = svgElement->getAttribute(HTMLNames::idAttr);
+        if (resource->isPaintServer()) {
+            RefPtr<SVGPaintServer> paintServer = WTF::static_pointer_cast<SVGPaintServer>(resource);
+            ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *paintServer << "}" << "\n";
+        } else
+            ts << "KCanvasResource {id=\"" << elementId << "\" " << *resource << "}" << "\n";
+    } while ((node = node->traverseNextNode(parent)));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/SVGRenderTreeAsText.h b/WebCore/rendering/SVGRenderTreeAsText.h
new file mode 100644
index 0000000..e23b82c
--- /dev/null
+++ b/WebCore/rendering/SVGRenderTreeAsText.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2004, 2005 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SVGRenderTreeAsText_h
+#define SVGRenderTreeAsText_h
+
+#if ENABLE(SVG)
+
+#include "TextStream.h"
+
+namespace WebCore {
+
+    class AffineTransform;
+    class Color;
+    class FloatPoint;
+    class FloatRect;
+    class FloatSize;
+    class IntPoint;
+    class IntRect;
+    class Node;
+    class RenderPath;
+    class RenderSVGContainer;
+    class RenderSVGInlineText;
+    class RenderSVGRoot;
+    class RenderSVGText; 
+
+// functions used by the main RenderTreeAsText code
+void write(TextStream&, const RenderPath&, int indent = 0);
+void write(TextStream&, const RenderSVGContainer&, int indent = 0);
+void write(TextStream&, const RenderSVGInlineText&, int ident = 0);
+void write(TextStream&, const RenderSVGRoot&, int indent = 0);
+void write(TextStream&, const RenderSVGText&, int ident = 0);
+
+void writeRenderResources(TextStream&, Node* parent);
+
+// helper operators defined used in various classes to dump the render tree.
+TextStream& operator<<(TextStream&, const AffineTransform&);
+TextStream& operator<<(TextStream&, const IntRect&);
+TextStream& operator<<(TextStream&, const Color&);
+TextStream& operator<<(TextStream&, const IntPoint&);
+TextStream& operator<<(TextStream&, const FloatSize&);
+TextStream& operator<<(TextStream&, const FloatRect&);
+TextStream& operator<<(TextStream&, const FloatPoint&);
+
+// helper operators specific to dumping the render tree. these are used in various classes to dump the render tree
+// these could be defined in separate namespace to avoid matching these generic signatures unintentionally.
+
+template<typename Item>
+TextStream& operator<<(TextStream& ts, const Vector<Item*>& v)
+{
+    ts << "[";
+
+    for (unsigned i = 0; i < v.size(); i++) {
+        ts << *v[i];
+        if (i < v.size() - 1)
+            ts << ", ";
+    }
+
+    ts << "]";
+    return ts;
+}
+
+template<typename Item>
+TextStream& operator<<(TextStream& ts, const Vector<Item>& v)
+{
+    ts << "[";
+
+    for (unsigned i = 0; i < v.size(); i++) {
+        ts << v[i];
+        if (i < v.size() - 1)
+            ts << ", ";
+    }
+
+    ts << "]";
+    return ts;
+}
+
+template<typename Pointer>
+TextStream& operator<<(TextStream& ts, Pointer* t)
+{
+    ts << reinterpret_cast<intptr_t>(t);
+    return ts;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+
+#endif // SVGRenderTreeAsText_h
diff --git a/WebCore/rendering/SVGRootInlineBox.cpp b/WebCore/rendering/SVGRootInlineBox.cpp
new file mode 100644
index 0000000..e5f9fdf
--- /dev/null
+++ b/WebCore/rendering/SVGRootInlineBox.cpp
@@ -0,0 +1,1708 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <[email protected]>
+ *           (C) 2006 Apple Computer Inc.
+ *           (C) 2007 Nikolas Zimmermann <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGRootInlineBox.h"
+
+#include "Editor.h"
+#include "Frame.h"
+#include "GraphicsContext.h"
+#include "RenderSVGRoot.h"
+#include "SVGInlineFlowBox.h"
+#include "SVGInlineTextBox.h"
+#include "SVGFontElement.h"
+#include "SVGPaintServer.h"
+#include "SVGRenderStyleDefs.h"
+#include "SVGRenderSupport.h"
+#include "SVGResourceFilter.h"
+#include "SVGTextPositioningElement.h"
+#include "SVGURIReference.h"
+#include "Text.h"
+#include "UnicodeRange.h"
+
+#include <float.h>
+
+// Text chunk creation is complex and the whole process
+// can easily be traced by setting this variable > 0.
+#define DEBUG_CHUNK_BUILDING 0
+
+namespace WebCore {
+
+static inline bool isVerticalWritingMode(const SVGRenderStyle* style)
+{
+    return style->writingMode() == WM_TBRL || style->writingMode() == WM_TB; 
+}
+
+static inline EAlignmentBaseline dominantBaselineToShift(bool isVerticalText, const RenderObject* text, const Font& font)
+{
+    ASSERT(text);
+
+    const SVGRenderStyle* style = text->style() ? text->style()->svgStyle() : 0;
+    ASSERT(style);
+
+    const SVGRenderStyle* parentStyle = text->parent() && text->parent()->style() ? text->parent()->style()->svgStyle() : 0;
+
+    EDominantBaseline baseline = style->dominantBaseline();
+    if (baseline == DB_AUTO) {
+        if (isVerticalText)
+            baseline = DB_CENTRAL;
+        else
+            baseline = DB_ALPHABETIC;
+    }
+
+    switch (baseline) {
+    case DB_USE_SCRIPT:
+        // TODO: The dominant-baseline and the baseline-table components are set by
+        //       determining the predominant script of the character data content.
+        return AB_ALPHABETIC;
+    case DB_NO_CHANGE:
+    {
+        if (parentStyle)
+            return dominantBaselineToShift(isVerticalText, text->parent(), font);
+
+        ASSERT_NOT_REACHED();
+        return AB_AUTO;
+    }
+    case DB_RESET_SIZE:
+    {
+        if (parentStyle)
+            return dominantBaselineToShift(isVerticalText, text->parent(), font);
+
+        ASSERT_NOT_REACHED();
+        return AB_AUTO;    
+    }
+    case DB_IDEOGRAPHIC:
+        return AB_IDEOGRAPHIC;
+    case DB_ALPHABETIC:
+        return AB_ALPHABETIC;
+    case DB_HANGING:
+        return AB_HANGING;
+    case DB_MATHEMATICAL:
+        return AB_MATHEMATICAL;
+    case DB_CENTRAL:
+        return AB_CENTRAL;
+    case DB_MIDDLE:
+        return AB_MIDDLE;
+    case DB_TEXT_AFTER_EDGE:
+        return AB_TEXT_AFTER_EDGE;
+    case DB_TEXT_BEFORE_EDGE:
+        return AB_TEXT_BEFORE_EDGE;
+    default:
+        ASSERT_NOT_REACHED();
+        return AB_AUTO;
+    }
+}
+
+static inline float alignmentBaselineToShift(bool isVerticalText, const RenderObject* text, const Font& font)
+{
+    ASSERT(text);
+
+    const SVGRenderStyle* style = text->style() ? text->style()->svgStyle() : 0;
+    ASSERT(style);
+
+    const SVGRenderStyle* parentStyle = text->parent() && text->parent()->style() ? text->parent()->style()->svgStyle() : 0;
+
+    EAlignmentBaseline baseline = style->alignmentBaseline();
+    if (baseline == AB_AUTO) {
+        if (parentStyle && style->dominantBaseline() == DB_AUTO)
+            baseline = dominantBaselineToShift(isVerticalText, text->parent(), font);
+        else
+            baseline = dominantBaselineToShift(isVerticalText, text, font);
+
+        ASSERT(baseline != AB_AUTO);    
+    }
+
+    // Note: http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling
+    switch (baseline) {
+    case AB_BASELINE:
+    {
+        if (parentStyle)
+            return dominantBaselineToShift(isVerticalText, text->parent(), font);
+
+        return 0.0f;
+    }
+    case AB_BEFORE_EDGE:
+    case AB_TEXT_BEFORE_EDGE:
+        return font.ascent();
+    case AB_MIDDLE:
+        return font.xHeight() / 2.0f;
+    case AB_CENTRAL:
+        // Not needed, we're taking this into account already for vertical text!
+        // return (font.ascent() - font.descent()) / 2.0f;
+        return 0.0f;
+    case AB_AFTER_EDGE:
+    case AB_TEXT_AFTER_EDGE:
+    case AB_IDEOGRAPHIC:
+        return font.descent();
+    case AB_ALPHABETIC:
+        return 0.0f;
+    case AB_HANGING:
+        return font.ascent() * 8.0f / 10.0f;
+    case AB_MATHEMATICAL:
+        return font.ascent() / 2.0f;
+    default:
+        ASSERT_NOT_REACHED();
+        return 0.0f;
+    }
+}
+
+static inline float glyphOrientationToAngle(const SVGRenderStyle* svgStyle, bool isVerticalText, const UChar& character)
+{
+    switch (isVerticalText ? svgStyle->glyphOrientationVertical() : svgStyle->glyphOrientationHorizontal()) {
+    case GO_AUTO:
+    {
+        // Spec: Fullwidth ideographic and fullwidth Latin text will be set with a glyph-orientation of 0-degrees.
+        //       Text which is not fullwidth will be set with a glyph-orientation of 90-degrees.
+        unsigned int unicodeRange = findCharUnicodeRange(character);
+        if (unicodeRange == cRangeSetLatin || unicodeRange == cRangeArabic)
+            return 90.0f;
+
+        return 0.0f;
+    }
+    case GO_90DEG:
+        return 90.0f;
+    case GO_180DEG:
+        return 180.0f;
+    case GO_270DEG:
+        return 270.0f;
+    case GO_0DEG:
+    default:
+        return 0.0f;
+    }
+}
+
+static inline bool glyphOrientationIsMultiplyOf180Degrees(float orientationAngle)
+{
+    return fabsf(fmodf(orientationAngle, 180.0f)) == 0.0f;
+}
+
+static inline float calculateGlyphAdvanceAndShiftRespectingOrientation(bool isVerticalText, float orientationAngle, float glyphWidth, float glyphHeight, const Font& font, SVGChar& svgChar, float& xOrientationShift, float& yOrientationShift)
+{
+    bool orientationIsMultiplyOf180Degrees = glyphOrientationIsMultiplyOf180Degrees(orientationAngle);
+
+    // The function is based on spec requirements:
+    //
+    // Spec: If the 'glyph-orientation-horizontal' results in an orientation angle that is not a multiple of
+    // of 180 degrees, then the current text position is incremented according to the vertical metrics of the glyph.
+    //
+    // Spec: If if the 'glyph-orientation-vertical' results in an orientation angle that is not a multiple of
+    // 180 degrees,then the current text position is incremented according to the horizontal metrics of the glyph.
+
+    // vertical orientation handling
+    if (isVerticalText) {
+        if (orientationAngle == 0.0f) {
+            xOrientationShift = -glyphWidth / 2.0f;
+            yOrientationShift = font.ascent();
+        } else if (orientationAngle == 90.0f) {
+            xOrientationShift = -glyphHeight;
+            yOrientationShift = font.descent();
+            svgChar.orientationShiftY = -font.ascent();
+        } else if (orientationAngle == 270.0f) {
+            xOrientationShift = glyphHeight;
+            yOrientationShift = font.descent();
+            svgChar.orientationShiftX = -glyphWidth;
+            svgChar.orientationShiftY = -font.ascent();
+        } else if (orientationAngle == 180.0f) {
+            yOrientationShift = font.ascent();
+            svgChar.orientationShiftX = -glyphWidth / 2.0f;
+            svgChar.orientationShiftY = font.ascent() - font.descent();
+        }
+
+        // vertical advance calculation
+        if (orientationAngle != 0.0f && !orientationIsMultiplyOf180Degrees)
+            return glyphWidth;
+
+        return glyphHeight; 
+    }
+
+    // horizontal orientation handling
+    if (orientationAngle == 90.0f) {
+        xOrientationShift = glyphWidth / 2.0f;
+        yOrientationShift = -font.descent();
+        svgChar.orientationShiftX = -glyphWidth / 2.0f - font.descent(); 
+        svgChar.orientationShiftY = font.descent();
+    } else if (orientationAngle == 270.0f) {
+        xOrientationShift = -glyphWidth / 2.0f;
+        yOrientationShift = -font.descent();
+        svgChar.orientationShiftX = -glyphWidth / 2.0f + font.descent();
+        svgChar.orientationShiftY = glyphHeight;
+    } else if (orientationAngle == 180.0f) {
+        xOrientationShift = glyphWidth / 2.0f;
+        svgChar.orientationShiftX = -glyphWidth / 2.0f;
+        svgChar.orientationShiftY = font.ascent() - font.descent();
+    }
+
+    // horizontal advance calculation
+    if (orientationAngle != 0.0f && !orientationIsMultiplyOf180Degrees)
+        return glyphHeight;
+
+    return glyphWidth;
+}
+
+static inline void startTextChunk(SVGTextChunkLayoutInfo& info)
+{
+    info.chunk.boxes.clear();
+    info.chunk.boxes.append(SVGInlineBoxCharacterRange());
+
+    info.chunk.start = info.it;
+    info.assignChunkProperties = true;
+}
+
+static inline void closeTextChunk(SVGTextChunkLayoutInfo& info)
+{
+    ASSERT(!info.chunk.boxes.last().isOpen());
+    ASSERT(info.chunk.boxes.last().isClosed());
+
+    info.chunk.end = info.it;
+    ASSERT(info.chunk.end >= info.chunk.start);
+
+    info.svgTextChunks.append(info.chunk);
+}
+
+RenderSVGRoot* findSVGRootObject(RenderObject* start)
+{
+    // Find associated root inline box
+    while (start && !start->isSVGRoot())
+        start = start->parent();
+
+    ASSERT(start);
+    ASSERT(start->isSVGRoot());
+
+    return static_cast<RenderSVGRoot*>(start);
+}
+
+static inline FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>& chars)
+{
+    return topLeftPositionOfCharacterRange(chars.begin(), chars.end());
+}
+
+FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>::iterator it, Vector<SVGChar>::iterator end)
+{
+    float lowX = FLT_MAX, lowY = FLT_MAX;
+    for (; it != end; ++it) {
+        if (it->isHidden())
+            continue;
+
+        float x = (*it).x;
+        float y = (*it).y;
+
+        if (x < lowX)
+            lowX = x;
+
+        if (y < lowY)
+            lowY = y;
+    }
+
+    return FloatPoint(lowX, lowY);
+}
+
+// Helper function
+static float calculateKerning(RenderObject* item)
+{
+    const Font& font = item->style()->font();
+    const SVGRenderStyle* svgStyle = item->style()->svgStyle();
+
+    float kerning = 0.0f;
+    if (CSSPrimitiveValue* primitive = static_cast<CSSPrimitiveValue*>(svgStyle->kerning())) {
+        kerning = primitive->getFloatValue();
+
+        if (primitive->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE && font.pixelSize() > 0)
+            kerning = kerning / 100.0f * font.pixelSize();
+    }
+
+    return kerning;
+}
+
+// Helper class for paint()
+struct SVGRootInlineBoxPaintWalker {
+    SVGRootInlineBoxPaintWalker(SVGRootInlineBox* rootBox, SVGResourceFilter* rootFilter, RenderObject::PaintInfo paintInfo, int tx, int ty)
+        : m_rootBox(rootBox)
+        , m_chunkStarted(false)
+        , m_paintInfo(paintInfo)
+        , m_savedInfo(paintInfo)
+        , m_boundingBox(tx + rootBox->xPos(), ty + rootBox->yPos(), rootBox->width(), rootBox->height())
+        , m_filter(0)
+        , m_rootFilter(rootFilter)
+        , m_fillPaintServer(0)
+        , m_strokePaintServer(0)
+        , m_fillPaintServerObject(0)
+        , m_strokePaintServerObject(0)
+        , m_tx(tx)
+        , m_ty(ty)
+    {
+    }
+
+    ~SVGRootInlineBoxPaintWalker()
+    {
+        ASSERT(!m_filter);
+        ASSERT(!m_fillPaintServer);
+        ASSERT(!m_fillPaintServerObject);
+        ASSERT(!m_strokePaintServer);
+        ASSERT(!m_strokePaintServerObject);
+        ASSERT(!m_chunkStarted);
+    }
+
+    void teardownFillPaintServer()
+    {
+        if (!m_fillPaintServer)
+            return;
+
+        m_fillPaintServer->teardown(m_paintInfo.context, m_fillPaintServerObject, ApplyToFillTargetType, true);
+
+        m_fillPaintServer = 0;
+        m_fillPaintServerObject = 0;
+    }
+
+    void teardownStrokePaintServer()
+    {
+        if (!m_strokePaintServer)
+            return;
+
+        m_strokePaintServer->teardown(m_paintInfo.context, m_strokePaintServerObject, ApplyToStrokeTargetType, true);
+
+        m_strokePaintServer = 0;
+        m_strokePaintServerObject = 0;
+    }
+
+    void chunkStartCallback(InlineBox* box)
+    {
+        ASSERT(!m_chunkStarted);
+        m_chunkStarted = true;
+
+        InlineFlowBox* flowBox = box->parent();
+
+        // Initialize text rendering
+        RenderObject* object = flowBox->object();
+        ASSERT(object);
+
+        m_savedInfo = m_paintInfo;
+        m_paintInfo.context->save();
+
+        if (!flowBox->isRootInlineBox())
+            m_paintInfo.context->concatCTM(m_rootBox->object()->localTransform());
+
+        m_paintInfo.context->concatCTM(object->localTransform());
+
+        if (!flowBox->isRootInlineBox()) {
+            prepareToRenderSVGContent(object, m_paintInfo, m_boundingBox, m_filter, m_rootFilter);
+            m_paintInfo.rect = object->localTransform().inverse().mapRect(m_paintInfo.rect);
+        }
+    }
+
+    void chunkEndCallback(InlineBox* box)
+    {
+        ASSERT(m_chunkStarted);
+        m_chunkStarted = false;
+
+        InlineFlowBox* flowBox = box->parent();
+
+        RenderObject* object = flowBox->object();
+        ASSERT(object);
+
+        // Clean up last used paint server
+        teardownFillPaintServer();
+        teardownStrokePaintServer();
+
+        // Finalize text rendering 
+        if (!flowBox->isRootInlineBox()) {
+            finishRenderSVGContent(object, m_paintInfo, m_boundingBox, m_filter, m_savedInfo.context);
+            m_filter = 0;
+        }
+
+        // Restore context & repaint rect
+        m_paintInfo.context->restore();
+        m_paintInfo.rect = m_savedInfo.rect;
+    }
+
+    bool chunkSetupFillCallback(InlineBox* box)
+    {
+        InlineFlowBox* flowBox = box->parent();
+
+        // Setup fill paint server
+        RenderObject* object = flowBox->object();
+        ASSERT(object);
+
+        ASSERT(!m_strokePaintServer);
+        teardownFillPaintServer();
+
+        m_fillPaintServer = SVGPaintServer::fillPaintServer(object->style(), object);
+        if (m_fillPaintServer) {
+            m_fillPaintServer->setup(m_paintInfo.context, object, ApplyToFillTargetType, true);
+            m_fillPaintServerObject = object;
+            return true;
+        }
+
+        return false;
+    }
+
+    bool chunkSetupStrokeCallback(InlineBox* box)
+    {
+        InlineFlowBox* flowBox = box->parent();
+
+        // Setup stroke paint server
+        RenderObject* object = flowBox->object();
+        ASSERT(object);
+
+        // If we're both stroked & filled, teardown fill paint server before stroking.
+        teardownFillPaintServer();
+        teardownStrokePaintServer();
+
+        m_strokePaintServer = SVGPaintServer::strokePaintServer(object->style(), object);
+
+        if (m_strokePaintServer) {
+            m_strokePaintServer->setup(m_paintInfo.context, object, ApplyToStrokeTargetType, true);
+            m_strokePaintServerObject = object;
+            return true;
+        }
+
+        return false;
+    }
+
+    void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm,
+                              const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)
+    {
+        RenderText* text = textBox->textObject();
+        ASSERT(text);
+
+        RenderStyle* styleToUse = text->style(textBox->isFirstLineStyle());
+        ASSERT(styleToUse);
+
+        startOffset += textBox->start();
+
+        int textDecorations = styleToUse->textDecorationsInEffect(); 
+
+        int textWidth = 0;
+        IntPoint decorationOrigin;
+        SVGTextDecorationInfo info;
+
+        if (!chunkCtm.isIdentity())
+            m_paintInfo.context->concatCTM(chunkCtm);
+
+        for (Vector<SVGChar>::iterator it = start; it != end; ++it) {
+            if (it->isHidden())
+                continue;
+
+            // Determine how many characters - starting from the current - can be drawn at once.
+            Vector<SVGChar>::iterator itSearch = it + 1;
+            while (itSearch != end) {
+                if (itSearch->drawnSeperated || itSearch->isHidden())
+                    break;
+
+                itSearch++;
+            }
+
+            const UChar* stringStart = text->characters() + startOffset + (it - start);
+            unsigned int stringLength = itSearch - it;
+
+            // Paint decorations, that have to be drawn before the text gets drawn
+            if (textDecorations != TDNONE && m_paintInfo.phase != PaintPhaseSelection) {
+                textWidth = styleToUse->font().width(svgTextRunForInlineTextBox(stringStart, stringLength, styleToUse, textBox, (*it).x));
+                decorationOrigin = IntPoint((int) (*it).x, (int) (*it).y - styleToUse->font().ascent());
+                info = m_rootBox->retrievePaintServersForTextDecoration(text);
+            }
+
+            if (textDecorations & UNDERLINE && textWidth != 0.0f)
+                textBox->paintDecoration(UNDERLINE, m_paintInfo.context, decorationOrigin.x(), decorationOrigin.y(), textWidth, *it, info);
+
+            if (textDecorations & OVERLINE && textWidth != 0.0f)
+                textBox->paintDecoration(OVERLINE, m_paintInfo.context, decorationOrigin.x(), decorationOrigin.y(), textWidth, *it, info);
+
+            // Paint text
+            SVGPaintServer* activePaintServer = m_fillPaintServer;
+            if (!activePaintServer)
+                activePaintServer = m_strokePaintServer;
+
+            ASSERT(activePaintServer);
+            textBox->paintCharacters(m_paintInfo, m_tx, m_ty, *it, stringStart, stringLength, activePaintServer);
+
+            // Paint decorations, that have to be drawn afterwards
+            if (textDecorations & LINE_THROUGH && textWidth != 0.0f)
+                textBox->paintDecoration(LINE_THROUGH, m_paintInfo.context, decorationOrigin.x(), decorationOrigin.y(), textWidth, *it, info);
+
+            // Skip processed characters
+            it = itSearch - 1;
+        }
+
+        if (!chunkCtm.isIdentity())
+            m_paintInfo.context->concatCTM(chunkCtm.inverse());
+    }
+
+private:
+    SVGRootInlineBox* m_rootBox;
+    bool m_chunkStarted : 1;
+
+    RenderObject::PaintInfo m_paintInfo;
+    RenderObject::PaintInfo m_savedInfo;
+
+    FloatRect m_boundingBox;
+    SVGResourceFilter* m_filter;
+    SVGResourceFilter* m_rootFilter;
+
+    SVGPaintServer* m_fillPaintServer;
+    SVGPaintServer* m_strokePaintServer;
+
+    RenderObject* m_fillPaintServerObject;
+    RenderObject* m_strokePaintServerObject;
+
+    int m_tx;
+    int m_ty;
+};
+
+void SVGRootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
+{
+    if (paintInfo.context->paintingDisabled() || paintInfo.phase != PaintPhaseForeground)
+        return;
+
+    RenderObject::PaintInfo savedInfo(paintInfo);
+    paintInfo.context->save();
+
+    SVGResourceFilter* filter = 0;
+    FloatRect boundingBox(tx + xPos(), ty + yPos(), width(), height());
+
+    // Initialize text rendering
+    paintInfo.context->concatCTM(object()->localTransform());
+    prepareToRenderSVGContent(object(), paintInfo, boundingBox, filter);
+    paintInfo.context->concatCTM(object()->localTransform().inverse());
+ 
+    // Render text, chunk-by-chunk
+    SVGRootInlineBoxPaintWalker walkerCallback(this, filter, paintInfo, tx, ty);
+    SVGTextChunkWalker<SVGRootInlineBoxPaintWalker> walker(&walkerCallback,
+                                                           &SVGRootInlineBoxPaintWalker::chunkPortionCallback,
+                                                           &SVGRootInlineBoxPaintWalker::chunkStartCallback,
+                                                           &SVGRootInlineBoxPaintWalker::chunkEndCallback,
+                                                           &SVGRootInlineBoxPaintWalker::chunkSetupFillCallback,
+                                                           &SVGRootInlineBoxPaintWalker::chunkSetupStrokeCallback);
+
+    walkTextChunks(&walker);
+
+    // Finalize text rendering 
+    finishRenderSVGContent(object(), paintInfo, boundingBox, filter, savedInfo.context);
+    paintInfo.context->restore();
+}
+
+int SVGRootInlineBox::placeBoxesHorizontally(int, int& leftPosition, int& rightPosition, bool&)
+{
+    // Remove any offsets caused by RTL text layout
+    leftPosition = 0;
+    rightPosition = 0;
+    return 0;
+}
+
+void SVGRootInlineBox::verticallyAlignBoxes(int& heightOfBlock)
+{
+    // height is set by layoutInlineBoxes.
+    heightOfBlock = height();
+}
+
+float cummulatedWidthOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range)
+{
+    ASSERT(!range.isOpen());
+    ASSERT(range.isClosed());
+    ASSERT(range.box->isInlineTextBox());
+
+    InlineTextBox* textBox = static_cast<InlineTextBox*>(range.box);
+    RenderText* text = textBox->textObject();
+    RenderStyle* style = text->style();
+
+    return style->font().floatWidth(svgTextRunForInlineTextBox(text->characters() + textBox->start() + range.startOffset, range.endOffset - range.startOffset, style, textBox, 0));
+}
+
+float cummulatedHeightOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range)
+{
+    ASSERT(!range.isOpen());
+    ASSERT(range.isClosed());
+    ASSERT(range.box->isInlineTextBox());
+
+    InlineTextBox* textBox = static_cast<InlineTextBox*>(range.box);
+    RenderText* text = textBox->textObject();
+    const Font& font = text->style()->font();
+
+    return (range.endOffset - range.startOffset) * (font.ascent() + font.descent());
+}
+
+TextRun svgTextRunForInlineTextBox(const UChar* c, int len, RenderStyle* style, const InlineTextBox* textBox, float xPos)
+{
+    ASSERT(textBox);
+    ASSERT(style);
+
+    TextRun run(c, len, false, static_cast<int>(xPos), textBox->toAdd(), textBox->direction() == RTL, textBox->m_dirOverride || style->visuallyOrdered());
+
+#if ENABLE(SVG_FONTS)
+    run.setReferencingRenderObject(textBox->textObject()->parent());
+#endif
+
+    // We handle letter & word spacing ourselves
+    run.disableSpacing();
+    return run;
+}
+
+static float cummulatedWidthOrHeightOfTextChunk(SVGTextChunk& chunk, bool calcWidthOnly)
+{
+    float length = 0.0f;
+    Vector<SVGChar>::iterator charIt = chunk.start;
+
+    Vector<SVGInlineBoxCharacterRange>::iterator it = chunk.boxes.begin();
+    Vector<SVGInlineBoxCharacterRange>::iterator end = chunk.boxes.end();
+
+    for (; it != end; ++it) {
+        SVGInlineBoxCharacterRange& range = *it;
+
+        SVGInlineTextBox* box = static_cast<SVGInlineTextBox*>(range.box);
+        RenderStyle* style = box->object()->style();
+
+        for (int i = range.startOffset; i < range.endOffset; ++i) {
+            ASSERT(charIt <= chunk.end);
+
+            // Determine how many characters - starting from the current - can be measured at once.
+            // Important for non-absolute positioned non-latin1 text (ie. Arabic) where ie. the width
+            // of a string is not the sum of the boundaries of all contained glyphs.
+            Vector<SVGChar>::iterator itSearch = charIt + 1;
+            Vector<SVGChar>::iterator endSearch = charIt + range.endOffset - i;
+            while (itSearch != endSearch) {
+                // No need to check for 'isHidden()' here as this function is not called for text paths.
+                if (itSearch->drawnSeperated)
+                    break;
+
+                itSearch++;
+            }
+
+            unsigned int positionOffset = itSearch - charIt;
+
+            // Calculate width/height of subrange
+            SVGInlineBoxCharacterRange subRange;
+            subRange.box = range.box;
+            subRange.startOffset = i;
+            subRange.endOffset = i + positionOffset;
+
+            if (calcWidthOnly)
+                length += cummulatedWidthOfInlineBoxCharacterRange(subRange);
+            else
+                length += cummulatedHeightOfInlineBoxCharacterRange(subRange);
+
+            // Calculate gap between the previous & current range
+            // <text x="10 50 70">ABCD</text> - we need to take the gaps between A & B into account
+            // so add "40" as width, and analogous for B & C, add "20" as width.
+            if (itSearch > chunk.start && itSearch < chunk.end) {
+                SVGChar& lastCharacter = *(itSearch - 1);
+                SVGChar& currentCharacter = *itSearch;
+
+                int offset = box->direction() == RTL ? box->end() - i - positionOffset + 1 : box->start() + i + positionOffset - 1;
+
+                // FIXME: does this need to change to handle multichar glyphs?
+                int charsConsumed = 1;
+                String glyphName;
+                if (calcWidthOnly) {
+                    float lastGlyphWidth = box->calculateGlyphWidth(style, offset, 0, charsConsumed, glyphName);
+                    length += currentCharacter.x - lastCharacter.x - lastGlyphWidth;
+                } else {
+                    float lastGlyphHeight = box->calculateGlyphHeight(style, offset, 0);
+                    length += currentCharacter.y - lastCharacter.y - lastGlyphHeight;
+                }
+            }
+
+            // Advance processed characters
+            i += positionOffset - 1;
+            charIt = itSearch;
+        }
+    }
+
+    ASSERT(charIt == chunk.end);
+    return length;
+}
+
+static float cummulatedWidthOfTextChunk(SVGTextChunk& chunk)
+{
+    return cummulatedWidthOrHeightOfTextChunk(chunk, true);
+}
+
+static float cummulatedHeightOfTextChunk(SVGTextChunk& chunk)
+{
+    return cummulatedWidthOrHeightOfTextChunk(chunk, false);
+}
+
+static float calculateTextAnchorShiftForTextChunk(SVGTextChunk& chunk, ETextAnchor anchor)
+{
+    float shift = 0.0f;
+
+    if (chunk.isVerticalText)
+        shift = cummulatedHeightOfTextChunk(chunk);
+    else
+        shift = cummulatedWidthOfTextChunk(chunk);
+
+    if (anchor == TA_MIDDLE)
+        shift *= -0.5f;
+    else
+        shift *= -1.0f;
+
+    return shift;
+}
+
+static void applyTextAnchorToTextChunk(SVGTextChunk& chunk)
+{
+    // This method is not called for chunks containing chars aligned on a path.
+    // -> all characters are visible, no need to check for "isHidden()" anywhere.
+
+    if (chunk.anchor == TA_START)
+        return;
+
+    float shift = calculateTextAnchorShiftForTextChunk(chunk, chunk.anchor);
+
+    // Apply correction to chunk
+    Vector<SVGChar>::iterator chunkIt = chunk.start;
+    for (; chunkIt != chunk.end; ++chunkIt) {
+        SVGChar& curChar = *chunkIt;
+
+        if (chunk.isVerticalText)
+            curChar.y += shift;
+        else
+            curChar.x += shift;
+    }
+
+    // Move inline boxes
+    Vector<SVGInlineBoxCharacterRange>::iterator boxIt = chunk.boxes.begin();
+    Vector<SVGInlineBoxCharacterRange>::iterator boxEnd = chunk.boxes.end();
+
+    for (; boxIt != boxEnd; ++boxIt) {
+        SVGInlineBoxCharacterRange& range = *boxIt;
+
+        InlineBox* curBox = range.box;
+        ASSERT(curBox->isInlineTextBox());
+        ASSERT(curBox->parent() && (curBox->parent()->isRootInlineBox() || curBox->parent()->isInlineFlowBox()));
+
+        // Move target box
+        if (chunk.isVerticalText)
+            curBox->setYPos(curBox->yPos() + static_cast<int>(shift));
+        else
+            curBox->setXPos(curBox->xPos() + static_cast<int>(shift));
+    }
+}
+
+static float calculateTextLengthCorrectionForTextChunk(SVGTextChunk& chunk, ELengthAdjust lengthAdjust, float& computedLength)
+{
+    if (chunk.textLength <= 0.0f)
+        return 0.0f;
+
+    float computedWidth = cummulatedWidthOfTextChunk(chunk);
+    float computedHeight = cummulatedHeightOfTextChunk(chunk);
+
+    if ((computedWidth <= 0.0f && !chunk.isVerticalText) ||
+        (computedHeight <= 0.0f && chunk.isVerticalText))
+        return 0.0f;
+
+    if (chunk.isVerticalText)
+        computedLength = computedHeight;
+    else
+        computedLength = computedWidth;
+
+    if (lengthAdjust == SVGTextContentElement::LENGTHADJUST_SPACINGANDGLYPHS) {
+        if (chunk.isVerticalText)
+            chunk.ctm.scale(1.0f, chunk.textLength / computedLength);
+        else
+            chunk.ctm.scale(chunk.textLength / computedLength, 1.0f);
+
+        return 0.0f;
+    }
+
+    return (chunk.textLength - computedLength) / float(chunk.end - chunk.start);
+}
+
+static void applyTextLengthCorrectionToTextChunk(SVGTextChunk& chunk)
+{
+    // This method is not called for chunks containing chars aligned on a path.
+    // -> all characters are visible, no need to check for "isHidden()" anywhere.
+
+    // lengthAdjust="spacingAndGlyphs" is handled by modifying chunk.ctm
+    float computedLength = 0.0f;
+    float spacingToApply = calculateTextLengthCorrectionForTextChunk(chunk, chunk.lengthAdjust, computedLength);
+
+    if (!chunk.ctm.isIdentity() && chunk.lengthAdjust == SVGTextContentElement::LENGTHADJUST_SPACINGANDGLYPHS) {
+        SVGChar& firstChar = *(chunk.start);
+
+        // Assure we apply the chunk scaling in the right origin
+        AffineTransform newChunkCtm;
+        newChunkCtm.translate(firstChar.x, firstChar.y);
+        newChunkCtm = chunk.ctm * newChunkCtm;
+        newChunkCtm.translate(-firstChar.x, -firstChar.y);
+
+        chunk.ctm = newChunkCtm;
+    }
+
+    // Apply correction to chunk 
+    if (spacingToApply != 0.0f) {
+        Vector<SVGChar>::iterator chunkIt = chunk.start;
+        for (; chunkIt != chunk.end; ++chunkIt) {
+            SVGChar& curChar = *chunkIt;
+            curChar.drawnSeperated = true;
+
+            if (chunk.isVerticalText)
+                curChar.y += (chunkIt - chunk.start) * spacingToApply;
+            else
+                curChar.x += (chunkIt - chunk.start) * spacingToApply;
+        }
+    }
+}
+
+void SVGRootInlineBox::computePerCharacterLayoutInformation()
+{
+    // Clean up any previous layout information
+    m_svgChars.clear();
+    m_svgTextChunks.clear();
+
+    // Build layout information for all contained render objects
+    SVGCharacterLayoutInfo info(m_svgChars);
+    buildLayoutInformation(this, info);
+
+    // Now all layout information are available for every character
+    // contained in any of our child inline/flow boxes. Build list
+    // of text chunks now, to be able to apply text-anchor shifts.
+    buildTextChunks(m_svgChars, m_svgTextChunks, this);
+
+    // Layout all text chunks
+    // text-anchor needs to be applied to individual chunks.
+    layoutTextChunks();
+
+    // Finally the top left position of our box is known.
+    // Propogate this knownledge to our RenderSVGText parent.
+    FloatPoint topLeft = topLeftPositionOfCharacterRange(m_svgChars);
+    object()->setPos((int) floorf(topLeft.x()), (int) floorf(topLeft.y()));
+
+    // Layout all InlineText/Flow boxes
+    // BEWARE: This requires the root top/left position to be set correctly before!
+    layoutInlineBoxes();
+}
+
+void SVGRootInlineBox::buildLayoutInformation(InlineFlowBox* start, SVGCharacterLayoutInfo& info)
+{
+    if (start->isRootInlineBox()) {
+        ASSERT(start->object()->element()->hasTagName(SVGNames::textTag));
+
+        SVGTextPositioningElement* positioningElement = static_cast<SVGTextPositioningElement*>(start->object()->element());
+        ASSERT(positioningElement);
+        ASSERT(positioningElement->parentNode());
+
+        info.addLayoutInformation(positioningElement);
+    }
+
+    LastGlyphInfo lastGlyph;
+    
+    for (InlineBox* curr = start->firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->object()->isText())
+            buildLayoutInformationForTextBox(info, static_cast<InlineTextBox*>(curr), lastGlyph);
+        else {
+            ASSERT(curr->isInlineFlowBox());
+            InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);
+
+            bool isAnchor = flowBox->object()->element()->hasTagName(SVGNames::aTag);
+            bool isTextPath = flowBox->object()->element()->hasTagName(SVGNames::textPathTag);
+
+            if (!isTextPath && !isAnchor) {
+                SVGTextPositioningElement* positioningElement = static_cast<SVGTextPositioningElement*>(flowBox->object()->element());
+                ASSERT(positioningElement);
+                ASSERT(positioningElement->parentNode());
+
+                info.addLayoutInformation(positioningElement);
+            } else if (!isAnchor) {
+                info.setInPathLayout(true);
+
+                // Handle text-anchor/textLength on path, which is special.
+                SVGTextContentElement* textContent = 0;
+                Node* node = flowBox->object()->element();
+                if (node && node->isSVGElement())
+                    textContent = static_cast<SVGTextContentElement*>(node);
+                ASSERT(textContent);
+
+                ELengthAdjust lengthAdjust = (ELengthAdjust) textContent->lengthAdjust();
+                ETextAnchor anchor = flowBox->object()->style()->svgStyle()->textAnchor();
+                float textAnchorStartOffset = 0.0f;
+
+                // Initialize sub-layout. We need to create text chunks from the textPath
+                // children using our standard layout code, to be able to measure the
+                // text length using our normal methods and not textPath specific hacks.
+                Vector<SVGChar> tempChars;
+                Vector<SVGTextChunk> tempChunks;
+
+                SVGCharacterLayoutInfo tempInfo(tempChars);
+                buildLayoutInformation(flowBox, tempInfo);
+
+                buildTextChunks(tempChars, tempChunks, flowBox);
+
+                Vector<SVGTextChunk>::iterator it = tempChunks.begin();
+                Vector<SVGTextChunk>::iterator end = tempChunks.end();
+
+                AffineTransform ctm;
+                float computedLength = 0.0f;
+ 
+                for (; it != end; ++it) {
+                    SVGTextChunk& chunk = *it;
+
+                    // Apply text-length calculation
+                    info.pathExtraAdvance += calculateTextLengthCorrectionForTextChunk(chunk, lengthAdjust, computedLength);
+
+                    if (lengthAdjust == SVGTextContentElement::LENGTHADJUST_SPACINGANDGLYPHS) {
+                        info.pathTextLength += computedLength;
+                        info.pathChunkLength += chunk.textLength;
+                    }
+
+                    // Calculate text-anchor start offset
+                    if (anchor == TA_START)
+                        continue;
+
+                    textAnchorStartOffset += calculateTextAnchorShiftForTextChunk(chunk, anchor);
+                }
+
+                info.addLayoutInformation(flowBox, textAnchorStartOffset);
+            }
+
+            float shiftxSaved = info.shiftx;
+            float shiftySaved = info.shifty;
+
+            buildLayoutInformation(flowBox, info);
+            info.processedChunk(shiftxSaved, shiftySaved);
+
+            if (isTextPath)
+                info.setInPathLayout(false);
+        }
+    }
+}
+
+void SVGRootInlineBox::layoutInlineBoxes()
+{
+    int lowX = INT_MAX;
+    int lowY = INT_MAX;
+    int highX = INT_MIN;
+    int highY = INT_MIN;
+
+    // Layout all child boxes
+    Vector<SVGChar>::iterator it = m_svgChars.begin(); 
+    layoutInlineBoxes(this, it, lowX, highX, lowY, highY);
+    ASSERT(it == m_svgChars.end());
+}
+
+void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::iterator& it, int& lowX, int& highX, int& lowY, int& highY)
+{
+    for (InlineBox* curr = start->firstChild(); curr; curr = curr->nextOnLine()) {
+        RenderStyle* style = curr->object()->style();    
+        const Font& font = style->font();
+
+        if (curr->object()->isText()) {
+            SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(curr);
+            unsigned length = textBox->len();
+
+            SVGChar curChar = *it; 
+            ASSERT(it != m_svgChars.end());  
+
+            FloatRect stringRect;
+            for (unsigned i = 0; i < length; ++i) {
+                ASSERT(it != m_svgChars.end());
+
+                if (it->isHidden()) {
+                    ++it;
+                    continue;
+                }
+
+                stringRect.unite(textBox->calculateGlyphBoundaries(style, textBox->start() + i, *it));
+                ++it;
+            }
+
+            IntRect enclosedStringRect = enclosingIntRect(stringRect);
+
+            int minX = enclosedStringRect.x();
+            int maxX = minX + enclosedStringRect.width();
+
+            int minY = enclosedStringRect.y();
+            int maxY = minY + enclosedStringRect.height();
+
+            curr->setXPos(minX - object()->xPos());
+            curr->setWidth(enclosedStringRect.width());
+
+            curr->setYPos(minY - object()->yPos());
+            curr->setBaseline(font.ascent());
+            curr->setHeight(enclosedStringRect.height());
+
+            if (minX < lowX)
+                lowX = minX;
+
+            if (maxX > highX)
+                highX = maxX;
+
+            if (minY < lowY)
+                lowY = minY;
+
+            if (maxY > highY)
+                highY = maxY;
+        } else {
+            ASSERT(curr->isInlineFlowBox());
+
+            int minX = INT_MAX;
+            int minY = INT_MAX;
+            int maxX = INT_MIN;
+            int maxY = INT_MIN;
+
+            InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);
+            layoutInlineBoxes(flowBox, it, minX, maxX, minY, maxY);
+
+            curr->setXPos(minX - object()->xPos());
+            curr->setWidth(maxX - minX);
+
+            curr->setYPos(minY - object()->yPos());
+            curr->setBaseline(font.ascent());
+            curr->setHeight(maxY - minY);
+
+            if (minX < lowX)
+                lowX = minX;
+
+            if (maxX > highX)
+                highX = maxX;
+
+            if (minY < lowY)
+                lowY = minY;
+
+            if (maxY > highY)
+                highY = maxY;
+        }
+    }
+
+    if (start->isRootInlineBox()) {
+        int top = lowY - object()->yPos();
+        int bottom = highY - object()->yPos();
+
+        start->setXPos(lowX - object()->xPos());
+        start->setYPos(top);
+
+        start->setWidth(highX - lowX);
+        start->setHeight(highY - lowY);
+
+        start->setVerticalOverflowPositions(top, bottom);
+        start->setVerticalSelectionPositions(top, bottom);
+    }
+}
+
+void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo& info, InlineTextBox* textBox, LastGlyphInfo& lastGlyph)
+{
+    RenderText* text = textBox->textObject();
+    ASSERT(text);
+
+    RenderStyle* style = text->style(textBox->isFirstLineStyle());
+    ASSERT(style);
+
+    const Font& font = style->font();
+    SVGInlineTextBox* svgTextBox = static_cast<SVGInlineTextBox*>(textBox);
+
+    unsigned length = textBox->len();
+
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+    bool isVerticalText = isVerticalWritingMode(svgStyle);
+
+    int charsConsumed = 0;
+    for (unsigned i = 0; i < length; i += charsConsumed) {
+        SVGChar svgChar;
+
+        if (info.inPathLayout())
+            svgChar.pathData = SVGCharOnPath::create();
+
+        float glyphWidth = 0.0f;
+        float glyphHeight = 0.0f;
+
+        int extraCharsAvailable = length - i - 1;
+
+        String unicodeStr;
+        String glyphName;
+        if (textBox->direction() == RTL) {
+            glyphWidth = svgTextBox->calculateGlyphWidth(style, textBox->end() - i, extraCharsAvailable, charsConsumed, glyphName);
+            glyphHeight = svgTextBox->calculateGlyphHeight(style, textBox->end() - i, extraCharsAvailable);
+            unicodeStr = String(textBox->textObject()->text()->characters() + textBox->end() - i, charsConsumed);
+        } else {
+            glyphWidth = svgTextBox->calculateGlyphWidth(style, textBox->start() + i, extraCharsAvailable, charsConsumed, glyphName);
+            glyphHeight = svgTextBox->calculateGlyphHeight(style, textBox->start() + i, extraCharsAvailable);
+            unicodeStr = String(textBox->textObject()->text()->characters() + textBox->start() + i, charsConsumed);
+        }
+
+        bool assignedX = false;
+        bool assignedY = false;
+
+        if (info.xValueAvailable() && (!info.inPathLayout() || (info.inPathLayout() && !isVerticalText))) {
+            if (!isVerticalText)
+                svgChar.newTextChunk = true;
+
+            assignedX = true;
+            svgChar.drawnSeperated = true;
+            info.curx = info.xValueNext();
+        }
+
+        if (info.yValueAvailable() && (!info.inPathLayout() || (info.inPathLayout() && isVerticalText))) {
+            if (isVerticalText)
+                svgChar.newTextChunk = true;
+
+            assignedY = true;
+            svgChar.drawnSeperated = true;
+            info.cury = info.yValueNext();
+        }
+
+        float dx = 0.0f;
+        float dy = 0.0f;
+
+        // Apply x-axis shift
+        if (info.dxValueAvailable()) {
+            svgChar.drawnSeperated = true;
+
+            dx = info.dxValueNext();
+            info.dx += dx;
+
+            if (!info.inPathLayout())
+                info.curx += dx;
+        }
+
+        // Apply y-axis shift
+        if (info.dyValueAvailable()) {
+            svgChar.drawnSeperated = true;
+
+            dy = info.dyValueNext();
+            info.dy += dy;
+
+            if (!info.inPathLayout())
+                info.cury += dy;
+        }
+
+        // Take letter & word spacing and kerning into account
+        float spacing = font.letterSpacing() + calculateKerning(textBox->object()->element()->renderer());
+
+        const UChar* currentCharacter = text->characters() + (textBox->direction() == RTL ? textBox->end() - i : textBox->start() + i);
+        const UChar* lastCharacter = 0;
+
+        if (textBox->direction() == RTL) {
+            if (i < textBox->end())
+                lastCharacter = text->characters() + textBox->end() - i +  1;
+        } else {
+            if (i > 0)
+                lastCharacter = text->characters() + textBox->start() + i - 1;
+        }
+
+        if (info.nextDrawnSeperated || spacing != 0.0f) {
+            info.nextDrawnSeperated = false;
+            svgChar.drawnSeperated = true;
+        }
+
+        if (currentCharacter && Font::treatAsSpace(*currentCharacter) && lastCharacter && !Font::treatAsSpace(*lastCharacter)) {
+            spacing += font.wordSpacing();
+
+            if (spacing != 0.0f && !info.inPathLayout())
+                info.nextDrawnSeperated = true;
+        }
+
+        float orientationAngle = glyphOrientationToAngle(svgStyle, isVerticalText, *currentCharacter);
+
+        float xOrientationShift = 0.0f;
+        float yOrientationShift = 0.0f;
+        float glyphAdvance = calculateGlyphAdvanceAndShiftRespectingOrientation(isVerticalText, orientationAngle, glyphWidth, glyphHeight,
+                                                                                font, svgChar, xOrientationShift, yOrientationShift);
+
+        // Handle textPath layout mode
+        if (info.inPathLayout()) {
+            float extraAdvance = isVerticalText ? dy : dx;
+            float newOffset = FLT_MIN;
+
+            if (assignedX && !isVerticalText)
+                newOffset = info.curx;
+            else if (assignedY && isVerticalText)
+                newOffset = info.cury;
+
+            float correctedGlyphAdvance = glyphAdvance;
+
+            // Handle lengthAdjust="spacingAndGlyphs" by specifying per-character scale operations
+            if (info.pathTextLength > 0.0f && info.pathChunkLength > 0.0f) { 
+                if (isVerticalText) {
+                    svgChar.pathData->yScale = info.pathChunkLength / info.pathTextLength;
+                    spacing *= svgChar.pathData->yScale;
+                    correctedGlyphAdvance *= svgChar.pathData->yScale;
+                } else {
+                    svgChar.pathData->xScale = info.pathChunkLength / info.pathTextLength;
+                    spacing *= svgChar.pathData->xScale;
+                    correctedGlyphAdvance *= svgChar.pathData->xScale;
+                }
+            }
+
+            // Handle letter & word spacing on text path
+            float pathExtraAdvance = info.pathExtraAdvance;
+            info.pathExtraAdvance += spacing;
+
+            svgChar.pathData->hidden = !info.nextPathLayoutPointAndAngle(correctedGlyphAdvance, extraAdvance, newOffset);
+            svgChar.drawnSeperated = true;
+
+            info.pathExtraAdvance = pathExtraAdvance;
+        }
+
+        // Apply rotation
+        if (info.angleValueAvailable())
+            info.angle = info.angleValueNext();
+
+        // Apply baseline-shift
+        if (info.baselineShiftValueAvailable()) {
+            svgChar.drawnSeperated = true;
+            float shift = info.baselineShiftValueNext();
+
+            if (isVerticalText)
+                info.shiftx += shift;
+            else
+                info.shifty -= shift;
+        }
+
+        // Take dominant-baseline / alignment-baseline into account
+        yOrientationShift += alignmentBaselineToShift(isVerticalText, text, font);
+
+        svgChar.x = info.curx;
+        svgChar.y = info.cury;
+        svgChar.angle = info.angle;
+
+        // For text paths any shift (dx/dy/baseline-shift) has to be applied after the rotation
+        if (!info.inPathLayout()) {
+            svgChar.x += info.shiftx + xOrientationShift;
+            svgChar.y += info.shifty + yOrientationShift;
+
+            if (orientationAngle != 0.0f)
+                svgChar.angle += orientationAngle;
+
+            if (svgChar.angle != 0.0f)
+                svgChar.drawnSeperated = true;
+        } else {
+            svgChar.pathData->orientationAngle = orientationAngle;
+
+            if (isVerticalText)
+                svgChar.angle -= 90.0f;
+
+            svgChar.pathData->xShift = info.shiftx + xOrientationShift;
+            svgChar.pathData->yShift = info.shifty + yOrientationShift;
+
+            // Translate to glyph midpoint
+            if (isVerticalText) {
+                svgChar.pathData->xShift += info.dx;
+                svgChar.pathData->yShift -= glyphAdvance / 2.0f;
+            } else {
+                svgChar.pathData->xShift -= glyphAdvance / 2.0f;
+                svgChar.pathData->yShift += info.dy;
+            }
+        }
+
+        double kerning = 0.0;
+#if ENABLE(SVG_FONTS)
+        SVGFontElement* svgFont = 0;
+        if (style->font().isSVGFont())
+            svgFont = style->font().svgFont();
+
+        if (lastGlyph.isValid && style->font().isSVGFont()) {
+            SVGHorizontalKerningPair kerningPair;
+            if (svgFont->getHorizontalKerningPairForStringsAndGlyphs(lastGlyph.unicode, lastGlyph.glyphName, unicodeStr, glyphName, kerningPair))
+                kerning = kerningPair.kerning;
+        }
+
+        if (style->font().isSVGFont()) {
+            lastGlyph.unicode = unicodeStr;
+            lastGlyph.glyphName = glyphName;
+            lastGlyph.isValid = true;
+        } else
+            lastGlyph.isValid = false;
+#endif
+
+        svgChar.x -= (float)kerning;
+
+        // Advance to new position
+        if (isVerticalText) {
+            svgChar.drawnSeperated = true;
+            info.cury += glyphAdvance + spacing;
+        } else
+            info.curx += glyphAdvance + spacing - (float)kerning;
+
+        // Advance to next character group
+        for (int k = 0; k < charsConsumed; ++k) {
+            info.svgChars.append(svgChar);
+            info.processedSingleCharacter();
+            svgChar.drawnSeperated = false;
+            svgChar.newTextChunk = false;
+        }
+    }
+}
+
+void SVGRootInlineBox::buildTextChunks(Vector<SVGChar>& svgChars, Vector<SVGTextChunk>& svgTextChunks, InlineFlowBox* start)
+{
+    SVGTextChunkLayoutInfo info(svgTextChunks);
+    info.it = svgChars.begin();
+    info.chunk.start = svgChars.begin();
+    info.chunk.end = svgChars.begin();
+
+    buildTextChunks(svgChars, start, info);
+    ASSERT(info.it == svgChars.end());
+}
+
+void SVGRootInlineBox::buildTextChunks(Vector<SVGChar>& svgChars, InlineFlowBox* start, SVGTextChunkLayoutInfo& info)
+{
+#if DEBUG_CHUNK_BUILDING > 1
+    fprintf(stderr, " -> buildTextChunks(start=%p)\n", start);
+#endif
+
+    for (InlineBox* curr = start->firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->object()->isText()) {
+            InlineTextBox* textBox = static_cast<InlineTextBox*>(curr);
+
+            unsigned length = textBox->len();
+            if (!length)
+                continue;
+
+#if DEBUG_CHUNK_BUILDING > 1
+            fprintf(stderr, " -> Handle inline text box (%p) with %i characters (start: %i, end: %i), handlingTextPath=%i\n",
+                            textBox, length, textBox->start(), textBox->end(), (int) info.handlingTextPath);
+#endif
+
+            RenderText* text = textBox->textObject();
+            ASSERT(text);
+            ASSERT(text->element());
+
+            SVGTextContentElement* textContent = 0;
+            Node* node = text->element()->parent();
+            while (node && node->isSVGElement() && !textContent) {
+                if (static_cast<SVGElement*>(node)->isTextContent())
+                    textContent = static_cast<SVGTextContentElement*>(node);
+                else
+                    node = node->parentNode();
+            }
+            ASSERT(textContent);
+
+            // Start new character range for the first chunk
+            bool isFirstCharacter = info.svgTextChunks.isEmpty() && info.chunk.start == info.it && info.chunk.start == info.chunk.end;
+            if (isFirstCharacter) {
+                ASSERT(info.chunk.boxes.isEmpty());
+                info.chunk.boxes.append(SVGInlineBoxCharacterRange());
+            } else
+                ASSERT(!info.chunk.boxes.isEmpty());
+
+            // Walk string to find out new chunk positions, if existant
+            for (unsigned i = 0; i < length; ++i) {
+                ASSERT(info.it != svgChars.end());
+
+                SVGInlineBoxCharacterRange& range = info.chunk.boxes.last();
+                if (range.isOpen()) {
+                    range.box = curr;
+                    range.startOffset = (i == 0 ? 0 : i - 1);
+
+#if DEBUG_CHUNK_BUILDING > 1
+                    fprintf(stderr, " | -> Range is open! box=%p, startOffset=%i\n", range.box, range.startOffset);
+#endif
+                }
+
+                // If a new (or the first) chunk has been started, record it's text-anchor and writing mode.
+                if (info.assignChunkProperties) {
+                    info.assignChunkProperties = false;
+
+                    info.chunk.isVerticalText = isVerticalWritingMode(text->style()->svgStyle());
+                    info.chunk.isTextPath = info.handlingTextPath;
+                    info.chunk.anchor = text->style()->svgStyle()->textAnchor();
+                    info.chunk.textLength = textContent->textLength().value(textContent);
+                    info.chunk.lengthAdjust = (ELengthAdjust) textContent->lengthAdjust();
+
+#if DEBUG_CHUNK_BUILDING > 1
+                    fprintf(stderr, " | -> Assign chunk properties, isVerticalText=%i, anchor=%i\n", info.chunk.isVerticalText, info.chunk.anchor);
+#endif
+                }
+
+                if (i > 0 && !isFirstCharacter && (*info.it).newTextChunk) {
+                    // Close mid chunk & character range
+                    ASSERT(!range.isOpen());
+                    ASSERT(!range.isClosed());
+
+                    range.endOffset = i;
+                    closeTextChunk(info);
+
+#if DEBUG_CHUNK_BUILDING > 1
+                    fprintf(stderr, " | -> Close mid-text chunk, at endOffset: %i and starting new mid chunk!\n", range.endOffset);
+#endif
+    
+                    // Prepare for next chunk, if we're not at the end
+                    startTextChunk(info);
+                    if (i + 1 == length) {
+#if DEBUG_CHUNK_BUILDING > 1
+                        fprintf(stderr, " | -> Record last chunk of inline text box!\n");
+#endif
+
+                        startTextChunk(info);
+                        SVGInlineBoxCharacterRange& range = info.chunk.boxes.last();
+
+                        info.assignChunkProperties = false;
+                        info.chunk.isVerticalText = isVerticalWritingMode(text->style()->svgStyle());
+                        info.chunk.isTextPath = info.handlingTextPath;
+                        info.chunk.anchor = text->style()->svgStyle()->textAnchor();
+                        info.chunk.textLength = textContent->textLength().value(textContent);
+                        info.chunk.lengthAdjust = (ELengthAdjust) textContent->lengthAdjust();
+
+                        range.box = curr;
+                        range.startOffset = i;
+
+                        ASSERT(!range.isOpen());
+                        ASSERT(!range.isClosed());
+                    }
+                }
+
+                // This should only hold true for the first character of the first chunk
+                if (isFirstCharacter)
+                    isFirstCharacter = false;
+    
+                ++info.it;
+            }
+
+#if DEBUG_CHUNK_BUILDING > 1    
+            fprintf(stderr, " -> Finished inline text box!\n");
+#endif
+
+            SVGInlineBoxCharacterRange& range = info.chunk.boxes.last();
+            if (!range.isOpen() && !range.isClosed()) {
+#if DEBUG_CHUNK_BUILDING > 1
+                fprintf(stderr, " -> Last range not closed - closing with endOffset: %i\n", length);
+#endif
+
+                // Current text chunk is not yet closed. Finish the current range, but don't start a new chunk.
+                range.endOffset = length;
+
+                if (info.it != svgChars.end()) {
+#if DEBUG_CHUNK_BUILDING > 1
+                    fprintf(stderr, " -> Not at last character yet!\n");
+#endif
+
+                    // If we're not at the end of the last box to be processed, and if the next
+                    // character starts a new chunk, then close the current chunk and start a new one.
+                    if ((*info.it).newTextChunk) {
+#if DEBUG_CHUNK_BUILDING > 1
+                        fprintf(stderr, " -> Next character starts new chunk! Closing current chunk, and starting a new one...\n");
+#endif
+
+                        closeTextChunk(info);
+                        startTextChunk(info);
+                    } else {
+                        // Just start a new character range
+                        info.chunk.boxes.append(SVGInlineBoxCharacterRange());
+
+#if DEBUG_CHUNK_BUILDING > 1
+                        fprintf(stderr, " -> Next character does NOT start a new chunk! Starting new character range...\n");
+#endif
+                    }
+                } else {
+#if DEBUG_CHUNK_BUILDING > 1
+                    fprintf(stderr, " -> Closing final chunk! Finished processing!\n");
+#endif
+
+                    // Close final chunk, once we're at the end of the last box
+                    closeTextChunk(info);
+                }
+            }
+        } else {
+            ASSERT(curr->isInlineFlowBox());
+            InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);
+
+            bool isTextPath = flowBox->object()->element()->hasTagName(SVGNames::textPathTag);
+
+#if DEBUG_CHUNK_BUILDING > 1
+            fprintf(stderr, " -> Handle inline flow box (%p), isTextPath=%i\n", flowBox, (int) isTextPath);
+#endif
+
+            if (isTextPath)
+                info.handlingTextPath = true;
+
+            buildTextChunks(svgChars, flowBox, info);
+
+            if (isTextPath)
+                info.handlingTextPath = false;
+        }
+    }
+
+#if DEBUG_CHUNK_BUILDING > 1
+    fprintf(stderr, " <- buildTextChunks(start=%p)\n", start);
+#endif
+}
+
+const Vector<SVGTextChunk>& SVGRootInlineBox::svgTextChunks() const 
+{
+    return m_svgTextChunks;
+}
+
+void SVGRootInlineBox::layoutTextChunks()
+{
+    Vector<SVGTextChunk>::iterator it = m_svgTextChunks.begin();
+    Vector<SVGTextChunk>::iterator end = m_svgTextChunks.end();
+
+    for (; it != end; ++it) {
+        SVGTextChunk& chunk = *it;
+
+#if DEBUG_CHUNK_BUILDING > 0
+        {
+            fprintf(stderr, "Handle TEXT CHUNK! anchor=%i, textLength=%f, lengthAdjust=%i, isVerticalText=%i, isTextPath=%i start=%p, end=%p -> dist: %i\n",
+                    (int) chunk.anchor, chunk.textLength, (int) chunk.lengthAdjust, (int) chunk.isVerticalText,
+                    (int) chunk.isTextPath, chunk.start, chunk.end, (unsigned int) (chunk.end - chunk.start));
+
+            Vector<SVGInlineBoxCharacterRange>::iterator boxIt = chunk.boxes.begin();
+            Vector<SVGInlineBoxCharacterRange>::iterator boxEnd = chunk.boxes.end();
+
+            unsigned int i = 0;
+            for (; boxIt != boxEnd; ++boxIt) {
+                SVGInlineBoxCharacterRange& range = *boxIt; i++;
+                fprintf(stderr, " -> RANGE %i STARTOFFSET: %i, ENDOFFSET: %i, BOX: %p\n", i, range.startOffset, range.endOffset, range.box);
+            }
+        }
+#endif
+
+        if (chunk.isTextPath)
+            continue;
+
+        // text-path & textLength, with lengthAdjust="spacing" is already handled for textPath layouts.
+        applyTextLengthCorrectionToTextChunk(chunk);
+ 
+        // text-anchor is already handled for textPath layouts.
+        applyTextAnchorToTextChunk(chunk);
+    }
+}
+
+static inline void addPaintServerToTextDecorationInfo(ETextDecoration decoration, SVGTextDecorationInfo& info, RenderObject* object)
+{
+    if (object->style()->svgStyle()->hasFill())
+        info.fillServerMap.set(decoration, object);
+
+    if (object->style()->svgStyle()->hasStroke())
+        info.strokeServerMap.set(decoration, object);
+}
+
+SVGTextDecorationInfo SVGRootInlineBox::retrievePaintServersForTextDecoration(RenderObject* start)
+{
+    ASSERT(start);
+
+    Vector<RenderObject*> parentChain;
+    while ((start = start->parent())) {
+        parentChain.prepend(start);
+
+        // Stop at our direct <text> parent.
+        if (start->isSVGText())
+            break;
+    }
+
+    Vector<RenderObject*>::iterator it = parentChain.begin();
+    Vector<RenderObject*>::iterator end = parentChain.end();
+
+    SVGTextDecorationInfo info;
+
+    for (; it != end; ++it) {
+        RenderObject* object = *it;
+        ASSERT(object);
+
+        RenderStyle* style = object->style();
+        ASSERT(style);
+
+        int decorations = style->textDecoration();
+        if (decorations != NONE) {
+            if (decorations & OVERLINE)
+                addPaintServerToTextDecorationInfo(OVERLINE, info, object);
+
+            if (decorations & UNDERLINE)
+                addPaintServerToTextDecorationInfo(UNDERLINE, info, object);
+
+            if (decorations & LINE_THROUGH)
+                addPaintServerToTextDecorationInfo(LINE_THROUGH, info, object);
+        }
+    }
+
+    return info;
+}
+
+void SVGRootInlineBox::walkTextChunks(SVGTextChunkWalkerBase* walker, const SVGInlineTextBox* textBox)
+{
+    ASSERT(walker);
+
+    Vector<SVGTextChunk>::iterator it = m_svgTextChunks.begin();
+    Vector<SVGTextChunk>::iterator itEnd = m_svgTextChunks.end();
+
+    for (; it != itEnd; ++it) {
+        SVGTextChunk& curChunk = *it;
+
+        Vector<SVGInlineBoxCharacterRange>::iterator boxIt = curChunk.boxes.begin();
+        Vector<SVGInlineBoxCharacterRange>::iterator boxEnd = curChunk.boxes.end();
+
+        InlineBox* lastNotifiedBox = 0;
+        InlineBox* prevBox = 0;
+
+        unsigned int chunkOffset = 0;
+        bool startedFirstChunk = false;
+
+        for (; boxIt != boxEnd; ++boxIt) {
+            SVGInlineBoxCharacterRange& range = *boxIt;
+
+            ASSERT(range.box->isInlineTextBox());
+            SVGInlineTextBox* rangeTextBox = static_cast<SVGInlineTextBox*>(range.box);
+
+            if (textBox && rangeTextBox != textBox) {
+                chunkOffset += range.endOffset - range.startOffset;
+                continue;
+            }
+
+            // Eventually notify that we started a new chunk
+            if (!textBox && !startedFirstChunk) {
+                startedFirstChunk = true;
+
+                lastNotifiedBox = range.box;
+                walker->start(range.box);
+            } else {
+                // Eventually apply new style, as this chunk spans multiple boxes (with possible different styling)
+                if (prevBox && prevBox != range.box) {
+                    lastNotifiedBox = range.box;
+
+                    walker->end(prevBox);
+                    walker->start(lastNotifiedBox);
+                }
+            }
+
+            unsigned int length = range.endOffset - range.startOffset;
+
+            Vector<SVGChar>::iterator itCharBegin = curChunk.start + chunkOffset;
+            Vector<SVGChar>::iterator itCharEnd = curChunk.start + chunkOffset + length;
+            ASSERT(itCharEnd <= curChunk.end);
+
+            // Process this chunk portion
+            if (textBox)
+                (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd);
+            else {
+                if (walker->setupFill(range.box))
+                    (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd);
+
+                if (walker->setupStroke(range.box))
+                    (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd);
+            }
+
+            chunkOffset += length;
+
+            if (!textBox)
+                prevBox = range.box;
+        }
+
+        if (!textBox && startedFirstChunk)
+            walker->end(lastNotifiedBox);
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/SVGRootInlineBox.h b/WebCore/rendering/SVGRootInlineBox.h
new file mode 100644
index 0000000..800664b
--- /dev/null
+++ b/WebCore/rendering/SVGRootInlineBox.h
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <[email protected]>
+ *           (C) 2006 Apple Computer Inc.
+ *           (C) 2007 Nikolas Zimmermann <[email protected]>
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SVGRootInlineBox_h
+#define SVGRootInlineBox_h
+
+#if ENABLE(SVG)
+#include "RootInlineBox.h"
+#include "SVGCharacterLayoutInfo.h"
+
+namespace WebCore {
+
+class InlineTextBox;
+class RenderSVGRoot;
+class SVGInlineTextBox;
+
+struct LastGlyphInfo {
+    LastGlyphInfo() : isValid(false) { }
+
+    String unicode;
+    String glyphName;
+    bool isValid;
+};
+
+class SVGRootInlineBox : public RootInlineBox {
+public:
+    SVGRootInlineBox(RenderObject* obj)
+        : RootInlineBox(obj)
+    {
+    }
+
+    virtual bool isSVGRootInlineBox() { return true; }
+
+    virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
+
+    virtual int placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing);
+    virtual void verticallyAlignBoxes(int& heightOfBlock);
+
+    virtual void computePerCharacterLayoutInformation();
+
+    // Used by SVGInlineTextBox
+    const Vector<SVGTextChunk>& svgTextChunks() const;
+
+    void walkTextChunks(SVGTextChunkWalkerBase*, const SVGInlineTextBox* textBox = 0);
+
+private:
+    friend struct SVGRootInlineBoxPaintWalker;
+
+    void layoutInlineBoxes();
+    void layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::iterator& it, int& minX, int& maxX, int& minY, int& maxY);
+
+    void buildLayoutInformation(InlineFlowBox* start, SVGCharacterLayoutInfo&);
+    void buildLayoutInformationForTextBox(SVGCharacterLayoutInfo&, InlineTextBox*, LastGlyphInfo&);
+
+    void buildTextChunks(Vector<SVGChar>&, Vector<SVGTextChunk>&, InlineFlowBox* start);
+    void buildTextChunks(Vector<SVGChar>&, InlineFlowBox* start, SVGTextChunkLayoutInfo&);
+    void layoutTextChunks();
+
+    SVGTextDecorationInfo retrievePaintServersForTextDecoration(RenderObject* start);
+
+private:
+    Vector<SVGChar> m_svgChars;
+    Vector<SVGTextChunk> m_svgTextChunks;
+};
+
+// Shared with SVGRenderTreeAsText / SVGInlineTextBox
+TextRun svgTextRunForInlineTextBox(const UChar*, int len, RenderStyle* style, const InlineTextBox* textBox, float xPos);
+FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>::iterator start, Vector<SVGChar>::iterator end);
+float cummulatedWidthOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range);
+float cummulatedHeightOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range);
+
+RenderSVGRoot* findSVGRootObject(RenderObject* start);
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+
+#endif // SVGRootInlineBox_h
diff --git a/WebCore/rendering/TableLayout.h b/WebCore/rendering/TableLayout.h
new file mode 100644
index 0000000..8ae0ce7
--- /dev/null
+++ b/WebCore/rendering/TableLayout.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2002 Lars Knoll ([email protected])
+ *           (C) 2002 Dirk Mueller ([email protected])
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TableLayout_h
+#define TableLayout_h
+
+namespace WebCore {
+
+class RenderTable;
+
+class TableLayout {
+public:
+    TableLayout(RenderTable* table)
+        : m_table(table)
+    {
+    }
+
+    virtual ~TableLayout() { }
+
+    virtual void calcPrefWidths(int& minWidth, int& maxWidth) = 0;
+    virtual void layout() = 0;
+
+protected:
+    RenderTable* m_table;
+};
+
+} // namespace WebCore
+
+#endif // TableLayout_h
diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp
new file mode 100644
index 0000000..f14480f
--- /dev/null
+++ b/WebCore/rendering/TextControlInnerElements.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2006, 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+ 
+#include "config.h"
+#include "TextControlInnerElements.h"
+
+#include "BeforeTextInsertedEvent.h"
+#include "Document.h"
+#include "EventHandler.h"
+#include "EventNames.h"
+#include "Frame.h"
+#include "HTMLInputElement.h"
+#include "HTMLTextAreaElement.h"
+#include "MouseEvent.h"
+#include "RenderTextControl.h"
+
+namespace WebCore {
+
+class RenderTextControlInnerBlock : public RenderBlock {
+public:
+    RenderTextControlInnerBlock(Node* node) : RenderBlock(node) { }
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+};
+
+bool RenderTextControlInnerBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
+{
+    RenderTextControl* renderer = static_cast<RenderTextControl*>(node()->shadowAncestorNode()->renderer());
+    
+    return RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, renderer->placeholderIsVisible() ? HitTestBlockBackground : hitTestAction);
+}
+
+TextControlInnerElement::TextControlInnerElement(Document* doc, Node* shadowParent)
+    : HTMLDivElement(doc), m_shadowParent(shadowParent)
+{
+}
+
+void TextControlInnerElement::attachInnerElement(Node* parent, PassRefPtr<RenderStyle> style, RenderArena* arena)
+{
+    // When adding these elements, create the renderer & style first before adding to the DOM.
+    // Otherwise, the render tree will create some anonymous blocks that will mess up our layout.
+
+    // Create the renderer with the specified style
+    RenderObject* renderer = createRenderer(arena, style.get());
+    if (renderer) {
+        setRenderer(renderer);
+        renderer->setStyle(style);
+    }
+    
+    // Set these explicitly since this normally happens during an attach()
+    setAttached();
+    setInDocument(true);
+    
+    // For elements without a shadow parent, add the node to the DOM normally.
+    if (!m_shadowParent)
+        parent->addChild(this);
+    
+    // Add the renderer to the render tree
+    if (renderer)
+        parent->renderer()->addChild(renderer);
+}
+
+TextControlInnerTextElement::TextControlInnerTextElement(Document* doc, Node* shadowParent)
+    : TextControlInnerElement(doc, shadowParent)
+{
+}
+
+void TextControlInnerTextElement::defaultEventHandler(Event* evt)
+{
+    // FIXME: In the future, we should add a way to have default event listeners.  Then we would add one to the text field's inner div, and we wouldn't need this subclass.
+    Node* shadowAncestor = shadowAncestorNode();
+    if (shadowAncestor && shadowAncestor->renderer()) {
+        ASSERT(shadowAncestor->renderer()->isTextField() || shadowAncestor->renderer()->isTextArea());
+        if (evt->isBeforeTextInsertedEvent())
+            if (shadowAncestor->renderer()->isTextField())
+                static_cast<HTMLInputElement*>(shadowAncestor)->defaultEventHandler(evt);
+            else
+                static_cast<HTMLTextAreaElement*>(shadowAncestor)->defaultEventHandler(evt);
+        if (evt->type() == eventNames().webkitEditableContentChangedEvent)
+            static_cast<RenderTextControl*>(shadowAncestor->renderer())->subtreeHasChanged();
+    }
+    if (!evt->defaultHandled())
+        HTMLDivElement::defaultEventHandler(evt);
+}
+
+RenderObject* TextControlInnerTextElement::createRenderer(RenderArena* arena, RenderStyle*)
+{
+    return new (arena) RenderTextControlInnerBlock(this);
+}
+
+SearchFieldResultsButtonElement::SearchFieldResultsButtonElement(Document* doc)
+    : TextControlInnerElement(doc)
+{
+}
+
+void SearchFieldResultsButtonElement::defaultEventHandler(Event* evt)
+{
+    // On mousedown, bring up a menu, if needed
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode());
+    if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
+        input->focus();
+        input->select();
+        if (input && input->renderer() && static_cast<RenderTextControl*>(input->renderer())->popupIsVisible())
+            static_cast<RenderTextControl*>(input->renderer())->hidePopup();
+        else if (input->maxResults() > 0)
+            static_cast<RenderTextControl*>(input->renderer())->showPopup();
+        evt->setDefaultHandled();
+    }
+    if (!evt->defaultHandled())
+        HTMLDivElement::defaultEventHandler(evt);
+}
+
+SearchFieldCancelButtonElement::SearchFieldCancelButtonElement(Document* doc)
+    : TextControlInnerElement(doc)
+    , m_capturing(false)
+{
+}
+
+void SearchFieldCancelButtonElement::defaultEventHandler(Event* evt)
+{
+    // If the element is visible, on mouseup, clear the value, and set selection
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode());
+    if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
+        input->focus();
+        input->select();
+        evt->setDefaultHandled();
+        if (renderer() && renderer()->style()->visibility() == VISIBLE)
+            if (Frame* frame = document()->frame()) {
+                frame->eventHandler()->setCapturingMouseEventsNode(this);
+                m_capturing = true;
+            }
+    } else if (evt->type() == eventNames().mouseupEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
+        if (m_capturing && renderer() && renderer()->style()->visibility() == VISIBLE) {
+            if (hovered()) {
+                input->setValue("");
+                input->onSearch();
+                evt->setDefaultHandled();
+            }
+            if (Frame* frame = document()->frame()) {
+                frame->eventHandler()->setCapturingMouseEventsNode(0);
+                m_capturing = false;
+            }
+        }
+    }
+    if (!evt->defaultHandled())
+        HTMLDivElement::defaultEventHandler(evt);
+}
+
+}
diff --git a/WebCore/rendering/TextControlInnerElements.h b/WebCore/rendering/TextControlInnerElements.h
new file mode 100644
index 0000000..9e81ada
--- /dev/null
+++ b/WebCore/rendering/TextControlInnerElements.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2006, 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+ 
+#ifndef TextControlInnerElements_h
+#define TextControlInnerElements_h
+
+#include "HTMLDivElement.h"
+
+namespace WebCore {
+
+class String;
+
+class TextControlInnerElement : public HTMLDivElement
+{
+public:
+    TextControlInnerElement(Document*, Node* shadowParent = 0);
+    
+    virtual bool isMouseFocusable() const { return false; } 
+    virtual bool isShadowNode() const { return m_shadowParent; }
+    virtual Node* shadowParentNode() { return m_shadowParent; }
+    void setShadowParentNode(Node* node) { m_shadowParent = node; }
+    void attachInnerElement(Node*, PassRefPtr<RenderStyle>, RenderArena*);
+    
+private:
+    Node* m_shadowParent;
+};
+
+class TextControlInnerTextElement : public TextControlInnerElement {
+public:
+    TextControlInnerTextElement(Document*, Node* shadowParent);
+    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);  
+    virtual void defaultEventHandler(Event*);
+};
+
+class SearchFieldResultsButtonElement : public TextControlInnerElement {
+public:
+    SearchFieldResultsButtonElement(Document*);
+    virtual void defaultEventHandler(Event*);
+};
+
+class SearchFieldCancelButtonElement : public TextControlInnerElement {
+public:
+    SearchFieldCancelButtonElement(Document*);
+    virtual void defaultEventHandler(Event*);
+private:
+    bool m_capturing;
+};
+
+} //namespace
+
+#endif
diff --git a/WebCore/rendering/bidi.cpp b/WebCore/rendering/bidi.cpp
new file mode 100644
index 0000000..93f3b0f
--- /dev/null
+++ b/WebCore/rendering/bidi.cpp
@@ -0,0 +1,2299 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ * Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All right reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "bidi.h"
+
+#include "CharacterNames.h"
+#include "Document.h"
+#include "Element.h"
+#include "FrameView.h"
+#include "InlineTextBox.h"
+#include "Logging.h"
+#include "RenderArena.h"
+#include "RenderLayer.h"
+#include "RenderListMarker.h"
+#include "RenderView.h"
+#include "break_lines.h"
+#include <wtf/AlwaysInline.h>
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/Vector.h>
+#ifdef ANDROID_LAYOUT
+#include "Frame.h"
+#include "FrameTree.h"
+#include "Settings.h"
+#include "Text.h"
+#include "HTMLNames.h"
+#endif // ANDROID_LAYOUT
+
+using namespace std;
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+// We don't let our line box tree for a single line get any deeper than this.
+const unsigned cMaxLineDepth = 200;
+
+class InlineIterator {
+public:
+    InlineIterator()
+        : block(0)
+        , obj(0)
+        , pos(0)
+        , nextBreakablePosition(-1)
+    {
+    }
+
+    InlineIterator(RenderBlock* b, RenderObject* o, unsigned p)
+        : block(b)
+        , obj(o)
+        , pos(p)
+        , nextBreakablePosition(-1)
+    {
+    }
+
+    void increment(InlineBidiResolver* resolver = 0);
+    bool atEnd() const;
+
+    UChar current() const;
+    WTF::Unicode::Direction direction() const;
+
+    RenderBlock* block;
+    RenderObject* obj;
+    unsigned pos;
+    int nextBreakablePosition;
+};
+
+// Midpoint globals.  The goal is not to do any allocation when dealing with
+// these midpoints, so we just keep an array around and never clear it.  We track
+// the number of items and position using the two other variables.
+static Vector<InlineIterator>* smidpoints;
+static unsigned sNumMidpoints;
+static unsigned sCurrMidpoint;
+static bool betweenMidpoints;
+
+static bool isLineEmpty = true;
+static bool previousLineBrokeCleanly = true;
+
+static int getBorderPaddingMargin(RenderObject* child, bool endOfInline)
+{
+    bool leftSide = (child->style()->direction() == LTR) ? !endOfInline : endOfInline;
+    if (leftSide)
+        return child->marginLeft() + child->paddingLeft() + child->borderLeft();
+    return child->marginRight() + child->paddingRight() + child->borderRight();
+}
+
+static int inlineWidth(RenderObject* child, bool start = true, bool end = true)
+{
+    unsigned lineDepth = 1;
+    int extraWidth = 0;
+    RenderObject* parent = child->parent();
+    while (parent->isInline() && !parent->isInlineBlockOrInlineTable() && lineDepth++ < cMaxLineDepth) {
+        if (start && parent->firstChild() == child)
+            extraWidth += getBorderPaddingMargin(parent, false);
+        if (end && parent->lastChild() == child)
+            extraWidth += getBorderPaddingMargin(parent, true);
+        child = parent;
+        parent = child->parent();
+    }
+    return extraWidth;
+}
+
+#ifndef NDEBUG
+static WTF::RefCountedLeakCounter bidiRunCounter("BidiRun");
+
+static bool inBidiRunDestroy;
+#endif
+
+void BidiRun::destroy()
+{
+#ifndef NDEBUG
+    inBidiRunDestroy = true;
+#endif
+    RenderArena* renderArena = m_object->renderArena();
+    delete this;
+#ifndef NDEBUG
+    inBidiRunDestroy = false;
+#endif
+
+    // Recover the size left there for us by operator delete and free the memory.
+    renderArena->free(*reinterpret_cast<size_t*>(this), this);
+}
+
+void* BidiRun::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+#ifndef NDEBUG
+    bidiRunCounter.increment();
+#endif
+    return renderArena->allocate(sz);
+}
+
+void BidiRun::operator delete(void* ptr, size_t sz)
+{
+#ifndef NDEBUG
+    bidiRunCounter.decrement();
+#endif
+    ASSERT(inBidiRunDestroy);
+
+    // Stash size where destroy() can find it.
+    *(size_t*)ptr = sz;
+}
+
+// ---------------------------------------------------------------------
+
+inline bool operator==(const InlineIterator& it1, const InlineIterator& it2)
+{
+    return it1.pos == it2.pos && it1.obj == it2.obj;
+}
+
+inline bool operator!=(const InlineIterator& it1, const InlineIterator& it2)
+{
+    return it1.pos != it2.pos || it1.obj != it2.obj;
+}
+
+static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current, InlineBidiResolver* resolver = 0, bool skipInlines = true, bool* endOfInlinePtr = 0)
+{
+    RenderObject* next = 0;
+    bool oldEndOfInline = endOfInlinePtr ? *endOfInlinePtr : false;
+    bool endOfInline = false;
+
+    while (current) {
+        next = 0;
+        if (!oldEndOfInline && !current->isFloating() && !current->isReplaced() && !current->isPositioned()) {
+            next = current->firstChild();
+            if (next && resolver && next->isInlineFlow()) {
+                EUnicodeBidi ub = next->style()->unicodeBidi();
+                if (ub != UBNormal) {
+                    TextDirection dir = next->style()->direction();
+                    Direction d = (ub == Embed
+                        ? (dir == RTL ? RightToLeftEmbedding : LeftToRightEmbedding)
+                        : (dir == RTL ? RightToLeftOverride : LeftToRightOverride));
+                    resolver->embed(d);
+                }
+            }
+        }
+
+        if (!next) {
+            if (!skipInlines && !oldEndOfInline && current->isInlineFlow()) {
+                next = current;
+                endOfInline = true;
+                break;
+            }
+
+            while (current && current != block) {
+                if (resolver && current->isInlineFlow() && current->style()->unicodeBidi() != UBNormal)
+                    resolver->embed(PopDirectionalFormat);
+
+                next = current->nextSibling();
+                if (next) {
+                    if (resolver && next->isInlineFlow()) {
+                        EUnicodeBidi ub = next->style()->unicodeBidi();
+                        if (ub != UBNormal) {
+                            TextDirection dir = next->style()->direction();
+                            Direction d = (ub == Embed
+                                ? (dir == RTL ? RightToLeftEmbedding: LeftToRightEmbedding)
+                                : (dir == RTL ? RightToLeftOverride : LeftToRightOverride));
+                            resolver->embed(d);
+                        }
+                    }
+                    break;
+                }
+                
+                current = current->parent();
+                if (!skipInlines && current && current != block && current->isInlineFlow()) {
+                    next = current;
+                    endOfInline = true;
+                    break;
+                }
+            }
+        }
+
+        if (!next)
+            break;
+
+        if (next->isText() || next->isFloating() || next->isReplaced() || next->isPositioned()
+            || ((!skipInlines || !next->firstChild()) // Always return EMPTY inlines.
+                && next->isInlineFlow()))
+            break;
+        current = next;
+    }
+
+    if (endOfInlinePtr)
+        *endOfInlinePtr = endOfInline;
+
+    return next;
+}
+
+static RenderObject* bidiFirst(RenderBlock* block, InlineBidiResolver* resolver, bool skipInlines = true)
+{
+    if (!block->firstChild())
+        return 0;
+    
+    RenderObject* o = block->firstChild();
+    if (o->isInlineFlow()) {
+        if (resolver) {
+            EUnicodeBidi ub = o->style()->unicodeBidi();
+            if (ub != UBNormal) {
+                TextDirection dir = o->style()->direction();
+                Direction d = (ub == Embed
+                    ? (dir == RTL ? RightToLeftEmbedding : LeftToRightEmbedding)
+                    : (dir == RTL ? RightToLeftOverride : LeftToRightOverride));
+                resolver->embed(d);
+            }
+        }
+        if (skipInlines && o->firstChild())
+            o = bidiNext(block, o, resolver, skipInlines);
+        else {
+            // Never skip empty inlines.
+            if (resolver)
+                resolver->commitExplicitEmbedding();
+            return o; 
+        }
+    }
+
+    if (o && !o->isText() && !o->isReplaced() && !o->isFloating() && !o->isPositioned())
+        o = bidiNext(block, o, resolver, skipInlines);
+
+    if (resolver)
+        resolver->commitExplicitEmbedding();
+    return o;
+}
+
+inline void InlineIterator::increment(InlineBidiResolver* resolver)
+{
+    if (!obj)
+        return;
+    if (obj->isText()) {
+        pos++;
+        if (pos >= static_cast<RenderText*>(obj)->textLength()) {
+            obj = bidiNext(block, obj, resolver);
+            pos = 0;
+            nextBreakablePosition = -1;
+        }
+    } else {
+        obj = bidiNext(block, obj, resolver);
+        pos = 0;
+        nextBreakablePosition = -1;
+    }
+}
+
+template<>
+inline void InlineBidiResolver::increment()
+{
+    current.increment(this);
+}
+
+inline bool InlineIterator::atEnd() const
+{
+    return !obj;
+}
+
+inline UChar InlineIterator::current() const
+{
+    if (!obj || !obj->isText())
+        return 0;
+
+    RenderText* text = static_cast<RenderText*>(obj);
+    if (pos >= text->textLength())
+        return 0;
+
+    return text->characters()[pos];
+}
+
+ALWAYS_INLINE Direction InlineIterator::direction() const
+{
+    if (UChar c = current())
+        return Unicode::direction(c);
+
+    if (obj && obj->isListMarker())
+        return obj->style()->direction() == LTR ? LeftToRight : RightToLeft;
+
+    return OtherNeutral;
+}
+
+// -------------------------------------------------------------------------------------------------
+
+static void chopMidpointsAt(RenderObject* obj, unsigned pos)
+{
+    if (!sNumMidpoints)
+        return;
+    InlineIterator* midpoints = smidpoints->data();
+    for (int i = sNumMidpoints - 1; i >= 0; i--) {
+        const InlineIterator& point = midpoints[i];
+        if (point.obj == obj && point.pos == pos) {
+            sNumMidpoints = i;
+            break;
+        }
+    }
+}
+
+static void checkMidpoints(InlineIterator& lBreak)
+{
+    // Check to see if our last midpoint is a start point beyond the line break.  If so,
+    // shave it off the list, and shave off a trailing space if the previous end point doesn't
+    // preserve whitespace.
+    if (lBreak.obj && sNumMidpoints && sNumMidpoints % 2 == 0) {
+        InlineIterator* midpoints = smidpoints->data();
+        InlineIterator& endpoint = midpoints[sNumMidpoints-2];
+        const InlineIterator& startpoint = midpoints[sNumMidpoints-1];
+        InlineIterator currpoint = endpoint;
+        while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)
+            currpoint.increment();
+        if (currpoint == lBreak) {
+            // We hit the line break before the start point.  Shave off the start point.
+            sNumMidpoints--;
+            if (endpoint.obj->style()->collapseWhiteSpace()) {
+                if (endpoint.obj->isText()) {
+                    // Don't shave a character off the endpoint if it was from a soft hyphen.
+                    RenderText* textObj = static_cast<RenderText*>(endpoint.obj);
+                    if (endpoint.pos + 1 < textObj->textLength()) {
+                        if (textObj->characters()[endpoint.pos+1] == softHyphen)
+                            return;
+                    } else if (startpoint.obj->isText()) {
+                        RenderText *startText = static_cast<RenderText*>(startpoint.obj);
+                        if (startText->textLength() && startText->characters()[0] == softHyphen)
+                            return;
+                    }
+                }
+                endpoint.pos--;
+            }
+        }
+    }    
+}
+
+static void addMidpoint(const InlineIterator& midpoint)
+{
+    if (smidpoints->size() <= sNumMidpoints)
+        smidpoints->grow(sNumMidpoints + 10);
+
+    InlineIterator* midpoints = smidpoints->data();
+    midpoints[sNumMidpoints++] = midpoint;
+}
+
+static void appendRunsForObject(int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
+{
+    if (start > end || obj->isFloating() ||
+        (obj->isPositioned() && !obj->hasStaticX() && !obj->hasStaticY() && !obj->container()->isInlineFlow()))
+        return;
+
+    bool haveNextMidpoint = (sCurrMidpoint < sNumMidpoints);
+    InlineIterator nextMidpoint;
+    if (haveNextMidpoint)
+        nextMidpoint = smidpoints->at(sCurrMidpoint);
+    if (betweenMidpoints) {
+        if (!(haveNextMidpoint && nextMidpoint.obj == obj))
+            return;
+        // This is a new start point. Stop ignoring objects and 
+        // adjust our start.
+        betweenMidpoints = false;
+        start = nextMidpoint.pos;
+        sCurrMidpoint++;
+        if (start < end)
+            return appendRunsForObject(start, end, obj, resolver);
+    } else {
+        if (!haveNextMidpoint || (obj != nextMidpoint.obj)) {
+            resolver.addRun(new (obj->renderArena()) BidiRun(start, end, obj, resolver.context(), resolver.dir()));
+            return;
+        }
+
+        // An end midpoint has been encountered within our object.  We
+        // need to go ahead and append a run with our endpoint.
+        if (static_cast<int>(nextMidpoint.pos + 1) <= end) {
+            betweenMidpoints = true;
+            sCurrMidpoint++;
+            if (nextMidpoint.pos != UINT_MAX) { // UINT_MAX means stop at the object and don't include any of it.
+                if (static_cast<int>(nextMidpoint.pos + 1) > start)
+                    resolver.addRun(new (obj->renderArena())
+                        BidiRun(start, nextMidpoint.pos + 1, obj, resolver.context(), resolver.dir()));
+                return appendRunsForObject(nextMidpoint.pos + 1, end, obj, resolver);
+            }
+        } else
+           resolver.addRun(new (obj->renderArena()) BidiRun(start, end, obj, resolver.context(), resolver.dir()));
+    }
+}
+
+template <>
+void InlineBidiResolver::appendRun()
+{
+    if (!emptyRun && !eor.atEnd()) {
+        int start = sor.pos;
+        RenderObject *obj = sor.obj;
+        while (obj && obj != eor.obj && obj != endOfLine.obj) {
+            appendRunsForObject(start, obj->length(), obj, *this);        
+            start = 0;
+            obj = bidiNext(sor.block, obj);
+        }
+        if (obj) {
+            unsigned pos = obj == eor.obj ? eor.pos : UINT_MAX;
+            if (obj == endOfLine.obj && endOfLine.pos <= pos) {
+                reachedEndOfLine = true;
+                pos = endOfLine.pos;
+            }
+            // It's OK to add runs for zero-length RenderObjects, just don't make the run larger than it should be
+            int end = obj->length() ? pos+1 : 0;
+            appendRunsForObject(start, end, obj, *this);
+        }
+        
+        eor.increment();
+        sor = eor;
+    }
+
+    m_direction = OtherNeutral;
+    m_status.eor = OtherNeutral;
+}
+
+InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj)
+{
+    // See if we have an unconstructed line box for this object that is also
+    // the last item on the line.
+    unsigned lineDepth = 1;
+    InlineFlowBox* childBox = 0;
+    InlineFlowBox* parentBox = 0;
+    InlineFlowBox* result = 0;
+    do {
+        ASSERT(obj->isInlineFlow() || obj == this);
+        RenderFlow* flow = static_cast<RenderFlow*>(obj);
+
+        // Get the last box we made for this render object.
+        parentBox = flow->lastLineBox();
+
+        // If this box is constructed then it is from a previous line, and we need
+        // to make a new box for our line.  If this box is unconstructed but it has
+        // something following it on the line, then we know we have to make a new box
+        // as well.  In this situation our inline has actually been split in two on
+        // the same line (this can happen with very fancy language mixtures).
+        bool constructedNewBox = false;
+        if (!parentBox || parentBox->isConstructed() || parentBox->nextOnLine()) {
+            // We need to make a new box for this render object.  Once
+            // made, we need to place it at the end of the current line.
+            InlineBox* newBox = obj->createInlineBox(false, obj == this);
+            ASSERT(newBox->isInlineFlowBox());
+            parentBox = static_cast<InlineFlowBox*>(newBox);
+            parentBox->setFirstLineStyleBit(m_firstLine);
+            constructedNewBox = true;
+        }
+
+        if (!result)
+            result = parentBox;
+
+        // If we have hit the block itself, then |box| represents the root
+        // inline box for the line, and it doesn't have to be appended to any parent
+        // inline.
+        if (childBox)
+            parentBox->addToLine(childBox);
+
+        if (!constructedNewBox || obj == this)
+            break;
+
+        childBox = parentBox;        
+
+        // If we've exceeded our line depth, then jump straight to the root and skip all the remaining
+        // intermediate inline flows.
+        obj = (++lineDepth >= cMaxLineDepth) ? this : obj->parent();
+
+    } while (true);
+
+    return result;
+}
+
+RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool lastLine, RenderObject* endObject)
+{
+    ASSERT(firstRun);
+
+    InlineFlowBox* parentBox = 0;
+    for (BidiRun* r = firstRun; r; r = r->next()) {
+        // Create a box for our object.
+        bool isOnlyRun = (runCount == 1);
+        if (runCount == 2 && !r->m_object->isListMarker())
+            isOnlyRun = ((style()->direction() == RTL) ? lastRun : firstRun)->m_object->isListMarker();
+
+        InlineBox* box = r->m_object->createInlineBox(r->m_object->isPositioned(), false, isOnlyRun);
+        r->m_box = box;
+
+        if (box) {
+            // If we have no parent box yet, or if the run is not simply a sibling,
+            // then we need to construct inline boxes as necessary to properly enclose the
+            // run's inline box.
+            if (!parentBox || parentBox->object() != r->m_object->parent())
+                // Create new inline boxes all the way back to the appropriate insertion point.
+                parentBox = createLineBoxes(r->m_object->parent());
+
+            // Append the inline box to this line.
+            parentBox->addToLine(box);
+
+            bool visuallyOrdered = r->m_object->style()->visuallyOrdered();
+            box->setBidiLevel(visuallyOrdered ? 0 : r->level());
+
+            if (box->isInlineTextBox()) {
+                InlineTextBox* text = static_cast<InlineTextBox*>(box);
+                text->setStart(r->m_start);
+                text->setLen(r->m_stop - r->m_start);
+                text->m_dirOverride = r->dirOverride(visuallyOrdered);
+            }
+        }
+    }
+
+    // We should have a root inline box.  It should be unconstructed and
+    // be the last continuation of our line list.
+    ASSERT(lastLineBox() && !lastLineBox()->isConstructed());
+
+    // Set bits on our inline flow boxes that indicate which sides should
+    // paint borders/margins/padding.  This knowledge will ultimately be used when
+    // we determine the horizontal positions and widths of all the inline boxes on
+    // the line.
+    lastLineBox()->determineSpacingForFlowBoxes(lastLine, endObject);
+
+    // Now mark the line boxes as being constructed.
+    lastLineBox()->setConstructed();
+
+    // Return the last line.
+    return lastRootBox();
+}
+
+void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd)
+{
+    // First determine our total width.
+    int availableWidth = lineWidth(m_height);
+    int totWidth = lineBox->getFlowSpacingWidth();
+    bool needsWordSpacing = false;
+    unsigned numSpaces = 0;
+    ETextAlign textAlign = style()->textAlign();
+
+    for (BidiRun* r = firstRun; r; r = r->next()) {
+        if (!r->m_box || r->m_object->isPositioned() || r->m_box->isLineBreak())
+            continue; // Positioned objects are only participating to figure out their
+                      // correct static x position.  They have no effect on the width.
+                      // Similarly, line break boxes have no effect on the width.
+        if (r->m_object->isText()) {
+            RenderText* rt = static_cast<RenderText*>(r->m_object);
+
+            if (textAlign == JUSTIFY && r != trailingSpaceRun) {
+                const UChar* characters = rt->characters();
+                for (int i = r->m_start; i < r->m_stop; i++) {
+                    UChar c = characters[i];
+                    if (c == ' ' || c == '\n' || c == '\t')
+                        numSpaces++;
+                }
+            }
+
+            if (int length = rt->textLength()) {
+                if (!r->m_compact && !r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characters()[r->m_start]))
+                    totWidth += rt->style(m_firstLine)->font().wordSpacing();
+                needsWordSpacing = !isSpaceOrNewline(rt->characters()[r->m_stop - 1]) && r->m_stop == length;          
+            }
+            r->m_box->setWidth(rt->width(r->m_start, r->m_stop - r->m_start, totWidth, m_firstLine));
+        } else if (!r->m_object->isInlineFlow()) {
+            r->m_object->calcWidth();
+            r->m_box->setWidth(r->m_object->width());
+            if (!r->m_compact)
+                 totWidth += r->m_object->marginLeft() + r->m_object->marginRight();
+        }
+
+        // Compacts don't contribute to the width of the line, since they are placed in the margin.
+        if (!r->m_compact)
+            totWidth += r->m_box->width();
+    }
+
+    // Armed with the total width of the line (without justification),
+    // we now examine our text-align property in order to determine where to position the
+    // objects horizontally.  The total width of the line can be increased if we end up
+    // justifying text.
+    int x = leftOffset(m_height);
+    switch(textAlign) {
+        case LEFT:
+        case WEBKIT_LEFT:
+            // The direction of the block should determine what happens with wide lines.  In
+            // particular with RTL blocks, wide lines should still spill out to the left.
+            if (style()->direction() == LTR) {
+                if (totWidth > availableWidth && trailingSpaceRun)
+                    trailingSpaceRun->m_box->setWidth(trailingSpaceRun->m_box->width() - totWidth + availableWidth);
+            } else {
+                if (trailingSpaceRun)
+                    trailingSpaceRun->m_box->setWidth(0);
+                else if (totWidth > availableWidth)
+                    x -= (totWidth - availableWidth);
+            }
+            break;
+        case JUSTIFY:
+            if (numSpaces && !reachedEnd && !lineBox->endsWithBreak()) {
+                if (trailingSpaceRun) {
+                    totWidth -= trailingSpaceRun->m_box->width();
+                    trailingSpaceRun->m_box->setWidth(0);
+                }
+                break;
+            }
+            // fall through
+        case TAAUTO:
+            numSpaces = 0;
+            // for right to left fall through to right aligned
+            if (style()->direction() == LTR) {
+                if (totWidth > availableWidth && trailingSpaceRun)
+                    trailingSpaceRun->m_box->setWidth(trailingSpaceRun->m_box->width() - totWidth + availableWidth);
+                break;
+            }
+        case RIGHT:
+        case WEBKIT_RIGHT:
+            // Wide lines spill out of the block based off direction.
+            // So even if text-align is right, if direction is LTR, wide lines should overflow out of the right
+            // side of the block.
+            if (style()->direction() == LTR) {
+                if (trailingSpaceRun) {
+                    totWidth -= trailingSpaceRun->m_box->width();
+                    trailingSpaceRun->m_box->setWidth(0);
+                }
+                if (totWidth < availableWidth)
+                    x += availableWidth - totWidth;
+            } else {
+                if (totWidth > availableWidth && trailingSpaceRun) {
+                    trailingSpaceRun->m_box->setWidth(trailingSpaceRun->m_box->width() - totWidth + availableWidth);
+                    totWidth -= trailingSpaceRun->m_box->width();
+                } else
+                    x += availableWidth - totWidth;
+            }
+            break;
+        case CENTER:
+        case WEBKIT_CENTER:
+            int trailingSpaceWidth = 0;
+            if (trailingSpaceRun) {
+                totWidth -= trailingSpaceRun->m_box->width();
+                trailingSpaceWidth = min(trailingSpaceRun->m_box->width(), (availableWidth - totWidth + 1) / 2);
+                trailingSpaceRun->m_box->setWidth(trailingSpaceWidth);
+            }
+            if (style()->direction() == LTR)
+                x += max((availableWidth - totWidth) / 2, 0);
+            else
+                x += totWidth > availableWidth ? (availableWidth - totWidth) : (availableWidth - totWidth) / 2 - trailingSpaceWidth;
+            break;
+    }
+
+    if (numSpaces) {
+        for (BidiRun* r = firstRun; r; r = r->next()) {
+            if (!r->m_box || r == trailingSpaceRun)
+                continue;
+
+            int spaceAdd = 0;
+            if (r->m_object->isText() && !r->m_compact) {
+                unsigned spaces = 0;
+                const UChar* characters = static_cast<RenderText*>(r->m_object)->characters();
+                for (int i = r->m_start; i < r->m_stop; i++) {
+                    UChar c = characters[i];
+                    if (c == ' ' || c == '\n' || c == '\t')
+                        spaces++;
+                }
+
+                ASSERT(spaces <= numSpaces);
+
+                // Only justify text if whitespace is collapsed.
+                if (r->m_object->style()->collapseWhiteSpace()) {
+                    spaceAdd = (availableWidth - totWidth) * spaces / numSpaces;
+                    static_cast<InlineTextBox*>(r->m_box)->setSpaceAdd(spaceAdd);
+                    totWidth += spaceAdd;
+                }
+                numSpaces -= spaces;
+                if (!numSpaces)
+                    break;
+            }
+        }
+    }
+
+    // The widths of all runs are now known.  We can now place every inline box (and
+    // compute accurate widths for the inline flow boxes).
+    int leftPosition = x;
+    int rightPosition = x;
+    needsWordSpacing = false;
+    lineBox->placeBoxesHorizontally(x, leftPosition, rightPosition, needsWordSpacing);
+    lineBox->setHorizontalOverflowPositions(leftPosition, rightPosition);
+}
+
+void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun)
+{
+    lineBox->verticallyAlignBoxes(m_height);
+    lineBox->setBlockHeight(m_height);
+
+    // See if the line spilled out.  If so set overflow height accordingly.
+    int bottomOfLine = lineBox->bottomOverflow();
+    if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight)
+        m_overflowHeight = bottomOfLine;
+
+    // Now make sure we place replaced render objects correctly.
+    for (BidiRun* r = firstRun; r; r = r->next()) {
+        if (!r->m_box)
+            continue; // Skip runs with no line boxes.
+
+        // Align positioned boxes with the top of the line box.  This is
+        // a reasonable approximation of an appropriate y position.
+        if (r->m_object->isPositioned())
+            r->m_box->setYPos(m_height);
+
+        // Position is used to properly position both replaced elements and
+        // to update the static normal flow x/y of positioned elements.
+        r->m_object->position(r->m_box);
+    }
+    // Positioned objects and zero-length text nodes destroy their boxes in
+    // position(), which unnecessarily dirties the line.
+    lineBox->markDirty(false);
+}
+
+// collects one line of the paragraph and transforms it to visual order
+void RenderBlock::bidiReorderLine(InlineBidiResolver& resolver, const InlineIterator& end)
+{
+    resolver.createBidiRunsForLine(end, style()->visuallyOrdered(), previousLineBrokeCleanly);
+}
+
+static void buildCompactRuns(RenderObject* compactObj, InlineBidiResolver& resolver)
+{
+    ASSERT(compactObj->isRenderBlock());
+    ASSERT(!resolver.firstRun());
+
+    // Format the compact like it is its own single line.  We build up all the runs for
+    // the little compact and then reorder them for bidi.
+    RenderBlock* compactBlock = static_cast<RenderBlock*>(compactObj);
+
+    InlineIterator start(compactBlock, bidiFirst(compactBlock, &resolver), 0);
+    resolver.setPosition(start);
+
+    betweenMidpoints = false;
+    isLineEmpty = true;
+    previousLineBrokeCleanly = true;
+
+    InlineIterator end = compactBlock->findNextLineBreak(resolver);
+    if (!isLineEmpty)
+        compactBlock->bidiReorderLine(resolver, end);
+
+    for (BidiRun* run = resolver.firstRun(); run; run = run->next())
+        run->m_compact = true;
+
+    sNumMidpoints = 0;
+    sCurrMidpoint = 0;
+    betweenMidpoints = false;
+}
+
+static inline bool isCollapsibleSpace(UChar character, RenderText* renderer)
+{
+    if (character == ' ' || character == '\t' || character == softHyphen)
+        return true;
+    if (character == '\n')
+        return !renderer->style()->preserveNewline();
+    if (character == noBreakSpace)
+        return renderer->style()->nbspMode() == SPACE;
+    return false;
+}
+
+void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, int& repaintBottom)
+{
+    bool useRepaintBounds = false;
+
+    invalidateVerticalPosition();
+    
+    m_overflowHeight = 0;
+        
+    m_height = borderTop() + paddingTop();
+    int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
+
+    // Figure out if we should clear out our line boxes.
+    // FIXME: Handle resize eventually!
+    // FIXME: Do something better when floats are present.
+    bool fullLayout = !firstLineBox() || !firstChild() || selfNeedsLayout() || relayoutChildren;
+    if (fullLayout)
+        deleteLineBoxes();
+
+    // Text truncation only kicks in if your overflow isn't visible and your text-overflow-mode isn't
+    // clip.
+    // FIXME: CSS3 says that descendants that are clipped must also know how to truncate.  This is insanely
+    // difficult to figure out (especially in the middle of doing layout), and is really an esoteric pile of nonsense
+    // anyway, so we won't worry about following the draft here.
+    bool hasTextOverflow = style()->textOverflow() && hasOverflowClip();
+
+    // Walk all the lines and delete our ellipsis line boxes if they exist.
+    if (hasTextOverflow)
+         deleteEllipsisLineBoxes();
+
+    if (firstChild()) {
+#ifdef ANDROID_LAYOUT
+        // if we are in fitColumnToScreen mode and viewport width is not device-width, 
+        // and text align is auto, or justify or left in LTR, or right in RTL, we 
+        // will wrap text around screen width so that it doesn't need to scroll 
+        // horizontally when reading a paragraph.
+        const Settings* settings = document()->settings();
+        bool doTextWrap = settings && settings->viewportWidth() != 0 &&
+                settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen;
+        if (doTextWrap) {
+            int ta = style()->textAlign();
+            int dir = style()->direction();
+            doTextWrap = (ta == TAAUTO) || (ta == JUSTIFY) ||
+                    ((ta == LEFT || ta == WEBKIT_LEFT) && (dir == LTR)) ||
+                    ((ta == RIGHT || ta == WEBKIT_RIGHT) && (dir == RTL));
+        }
+        bool hasTextToWrap = false;
+#endif
+        // layout replaced elements
+        bool endOfInline = false;
+        RenderObject* o = bidiFirst(this, 0, false);
+        Vector<FloatWithRect> floats;
+        int containerWidth = max(0, containingBlockWidth());
+        while (o) {
+            o->invalidateVerticalPosition();
+            if (o->isReplaced() || o->isFloating() || o->isPositioned()) {
+                if (relayoutChildren || o->style()->width().isPercent() || o->style()->height().isPercent())
+                    o->setChildNeedsLayout(true, false);
+                    
+                // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
+                if (relayoutChildren && (o->style()->paddingLeft().isPercent() || o->style()->paddingRight().isPercent()))
+                    o->setPrefWidthsDirty(true, false);
+            
+                if (o->isPositioned())
+                    o->containingBlock()->insertPositionedObject(o);
+                else {
+#ifdef ANDROID_LAYOUT
+                    // ignore text wrap for textField or menuList
+	            	if (doTextWrap && (o->isTextField() || o->isMenuList()))
+	            	    doTextWrap = false;	
+#endif
+                    if (o->isFloating())
+                        floats.append(FloatWithRect(o));
+                    else if (fullLayout || o->needsLayout()) // Replaced elements
+                        o->dirtyLineBoxes(fullLayout);
+
+                    o->layoutIfNeeded();
+                }
+            } else if (o->isText() || (o->isInlineFlow() && !endOfInline)) {
+                if (fullLayout || o->selfNeedsLayout())
+                    o->dirtyLineBoxes(fullLayout);
+                
+                // Calculate margins of inline flows so that they can be used later by line layout.
+                if (o->isInlineFlow())
+                    static_cast<RenderFlow*>(o)->calcMargins(containerWidth);
+                o->setNeedsLayout(false);
+#ifdef ANDROID_LAYOUT
+                if (doTextWrap && !hasTextToWrap && o->isText()) {
+                    Node* node = o->element();
+			        // as it is very common for sites to use a serial of <a> as 
+			        // tabs, we don't force text to wrap if all the text are
+			        // short and within an <a> tag, or only separated by short 
+                    // word like "|" or ";".
+                    if (node && node->isTextNode() &&
+                            !static_cast<Text*>(node)->containsOnlyWhitespace()) {
+                        int length = static_cast<Text*>(node)->length();
+                        if (length > 20 || (length >3 &&
+								!node->parent()->hasTagName(HTMLNames::aTag)))                         	
+                        	hasTextToWrap = true;
+                    }
+                }
+#endif            
+            }
+            o = bidiNext(this, o, 0, false, &endOfInline);
+        }
+
+#ifdef ANDROID_LAYOUT
+        // try to make sure that inline text will not span wider than the
+        // screen size unless the container has a fixed height,
+        if (doTextWrap && hasTextToWrap) {
+            // check all the nested containing blocks, unless it is table or 
+            // table-cell, to make sure there is no fixed height as it implies 
+            // fixed layout. If we constrain the text to fit screen, we may 
+            // cause text overlap with the block after.
+            bool isConstrained = false;
+            RenderObject* obj = this;
+            while (obj) {
+                if (obj->style()->height().isFixed() && (!obj->isTable() && !obj->isTableCell())) {
+                    isConstrained = true;
+                    break;
+                }
+                if (obj->isFloating() || obj->isPositioned()) {
+                    // floating and absolute or fixed positioning are done out 
+                    // of normal flow. Don't need to worry about height any more.
+                    break;
+                }
+                obj = obj->container();                
+            }
+            if (!isConstrained) {
+                int maxWidth = view()->frameView()->screenWidth() - 2 * ANDROID_FCTS_MARGIN_PADDING;
+                if (maxWidth > 0) {
+                    m_width = min(m_width, maxWidth);
+                    m_minPrefWidth = min(m_minPrefWidth, maxWidth);
+                    m_maxPrefWidth = min(m_maxPrefWidth, maxWidth);
+                    m_overflowWidth = min(m_overflowWidth, maxWidth);
+                }
+            }
+        }
+#endif
+        // We want to skip ahead to the first dirty line
+        InlineBidiResolver resolver;
+        unsigned floatIndex;
+        RootInlineBox* startLine = determineStartPosition(fullLayout, resolver, floats, floatIndex);
+
+        if (fullLayout && !selfNeedsLayout()) {
+            setNeedsLayout(true, false);  // Mark ourselves as needing a full layout. This way we'll repaint like
+                                          // we're supposed to.
+            if (!document()->view()->needsFullRepaint() && m_layer) {
+                // Because we waited until we were already inside layout to discover
+                // that the block really needed a full layout, we missed our chance to repaint the layer
+                // before layout started.  Luckily the layer has cached the repaint rect for its original
+                // position and size, and so we can use that to make a repaint happen now.
+                RenderView* c = view();
+                if (c && !c->printing())
+                    c->repaintViewRectangle(m_layer->repaintRect());
+            }
+        }
+
+        FloatingObject* lastFloat = m_floatingObjects ? m_floatingObjects->last() : 0;
+
+        if (!smidpoints)
+            smidpoints = new Vector<InlineIterator>();
+
+        sNumMidpoints = 0;
+        sCurrMidpoint = 0;
+
+        // We also find the first clean line and extract these lines.  We will add them back
+        // if we determine that we're able to synchronize after handling all our dirty lines.
+        InlineIterator cleanLineStart;
+        BidiStatus cleanLineBidiStatus;
+        int endLineYPos = 0;
+        RootInlineBox* endLine = (fullLayout || !startLine) ? 
+                                 0 : determineEndPosition(startLine, cleanLineStart, cleanLineBidiStatus, endLineYPos);
+
+        if (startLine) {
+            useRepaintBounds = true;
+            repaintTop = m_height;
+            repaintBottom = m_height;
+            RenderArena* arena = renderArena();
+            RootInlineBox* box = startLine;
+            while (box) {
+                repaintTop = min(repaintTop, box->topOverflow());
+                repaintBottom = max(repaintBottom, box->bottomOverflow());
+                RootInlineBox* next = box->nextRootBox();
+                box->deleteLine(arena);
+                box = next;
+            }
+        }
+
+        InlineIterator end = resolver.position();
+
+        if (!fullLayout && lastRootBox() && lastRootBox()->endsWithBreak()) {
+            // If the last line before the start line ends with a line break that clear floats,
+            // adjust the height accordingly.
+            // A line break can be either the first or the last object on a line, depending on its direction.
+            if (InlineBox* lastLeafChild = lastRootBox()->lastLeafChild()) {
+                RenderObject* lastObject = lastLeafChild->object();
+                if (!lastObject->isBR())
+                    lastObject = lastRootBox()->firstLeafChild()->object();
+                if (lastObject->isBR()) {
+                    EClear clear = lastObject->style()->clear();
+                    if (clear != CNONE)
+                        newLine(clear);
+                }
+            }
+        }
+
+        bool endLineMatched = false;
+        bool checkForEndLineMatch = endLine;
+        bool checkForFloatsFromLastLine = false;
+        int lastHeight = m_height;
+
+        while (!end.atEnd()) {
+            // FIXME: Is this check necessary before the first iteration or can it be moved to the end?
+            if (checkForEndLineMatch && (endLineMatched = matchedEndLine(resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineYPos, repaintBottom, repaintTop)))
+                break;
+
+            betweenMidpoints = false;
+            isLineEmpty = true;
+            if (m_firstLine && firstChild()->isCompact() && firstChild()->isRenderBlock()) {
+                buildCompactRuns(firstChild(), resolver);
+                resolver.setPosition(InlineIterator(this, firstChild()->nextSibling(), 0));
+            }
+            EClear clear = CNONE;
+            end = findNextLineBreak(resolver, &clear);
+            if (resolver.position().atEnd()) {
+                resolver.deleteRuns();
+                checkForFloatsFromLastLine = true;
+                break;
+            }
+            ASSERT(end != resolver.position());
+
+            if (!isLineEmpty) {
+                bidiReorderLine(resolver, end);
+                ASSERT(resolver.position() == end);
+
+                BidiRun* trailingSpaceRun = 0;
+                if (!previousLineBrokeCleanly && resolver.runCount() && resolver.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace()) {
+                    trailingSpaceRun = resolver.logicallyLastRun();
+                    RenderObject* lastObject = trailingSpaceRun->m_object;
+                    if (lastObject->isText()) {
+                        RenderText* lastText = static_cast<RenderText*>(lastObject);
+                        const UChar* characters = lastText->characters();
+                        int firstSpace = trailingSpaceRun->stop();
+                        while (firstSpace > trailingSpaceRun->start()) {
+                            UChar current = characters[firstSpace - 1];
+                            if (!isCollapsibleSpace(current, lastText))
+                                break;
+                            firstSpace--;
+                        }
+                        if (firstSpace == trailingSpaceRun->stop())
+                            trailingSpaceRun = 0;
+                        else {
+                            TextDirection direction = style()->direction();
+                            bool shouldReorder = trailingSpaceRun != (direction == LTR ? resolver.lastRun() : resolver.firstRun());
+                            if (firstSpace != trailingSpaceRun->start()) {
+                                ETextAlign textAlign = style()->textAlign();
+                                // If the trailing white space is at the right hand side of a left-aligned line, then computeHorizontalPositionsForLine()
+                                // does not care if trailingSpaceRun includes non-spaces at the beginning. In all other cases, trailingSpaceRun has to
+                                // contain only the spaces, either because we re-order them or because computeHorizontalPositionsForLine() needs to know
+                                // their width.
+                                bool shouldSeparateSpaces = textAlign != LEFT && textAlign != WEBKIT_LEFT && textAlign != TAAUTO || trailingSpaceRun->m_level % 2 || direction == RTL || shouldReorder;
+                                if (shouldSeparateSpaces) {
+                                    BidiContext* baseContext = resolver.context();
+                                    while (BidiContext* parent = baseContext->parent())
+                                        baseContext = parent;
+
+                                    BidiRun* newTrailingRun = new (renderArena()) BidiRun(firstSpace, trailingSpaceRun->m_stop, trailingSpaceRun->m_object, baseContext, OtherNeutral);
+                                    trailingSpaceRun->m_stop = firstSpace;
+                                    if (direction == LTR)
+                                        resolver.addRun(newTrailingRun);
+                                    else
+                                        resolver.prependRun(newTrailingRun);
+                                    trailingSpaceRun = newTrailingRun;
+                                    shouldReorder = false;
+                                }
+                            }
+                            if (shouldReorder) {
+                                if (direction == LTR) {
+                                    resolver.moveRunToEnd(trailingSpaceRun);
+                                    trailingSpaceRun->m_level = 0;
+                                } else {
+                                    resolver.moveRunToBeginning(trailingSpaceRun);
+                                    trailingSpaceRun->m_level = 1;
+                                }
+                            }
+                        }
+                    } else
+                        trailingSpaceRun = 0;
+                }
+
+                // Now that the runs have been ordered, we create the line boxes.
+                // At the same time we figure out where border/padding/margin should be applied for
+                // inline flow boxes.
+
+                RootInlineBox* lineBox = 0;
+                if (resolver.runCount()) {
+                    lineBox = constructLine(resolver.runCount(), resolver.firstRun(), resolver.lastRun(), !end.obj, end.obj && !end.pos ? end.obj : 0);
+                    if (lineBox) {
+                        lineBox->setEndsWithBreak(previousLineBrokeCleanly);
+
+                        // Now we position all of our text runs horizontally.
+                        computeHorizontalPositionsForLine(lineBox, resolver.firstRun(), trailingSpaceRun, end.atEnd());
+
+                        // Now position our text runs vertically.
+                        computeVerticalPositionsForLine(lineBox, resolver.firstRun());
+
+#if ENABLE(SVG)
+                        // Special SVG text layout code
+                        lineBox->computePerCharacterLayoutInformation();
+#endif
+
+#if PLATFORM(MAC)
+                        // Highlight acts as an overflow inflation.
+                        if (style()->highlight() != nullAtom)
+                            lineBox->addHighlightOverflow();
+#endif
+                    }
+                }
+
+                resolver.deleteRuns();
+
+                if (lineBox) {
+                    lineBox->setLineBreakInfo(end.obj, end.pos, resolver.status());
+                    if (useRepaintBounds) {
+                        repaintTop = min(repaintTop, lineBox->topOverflow());
+                        repaintBottom = max(repaintBottom, lineBox->bottomOverflow());
+                    }
+                }
+
+                m_firstLine = false;
+                newLine(clear);
+            }
+
+            if (m_floatingObjects && lastRootBox()) {
+                if (lastFloat) {
+                    for (FloatingObject* f = m_floatingObjects->last(); f != lastFloat; f = m_floatingObjects->prev()) {
+                    }
+                    m_floatingObjects->next();
+                } else
+                    m_floatingObjects->first();
+                for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) {
+                    if (f->m_bottom > lastHeight)
+                        lastRootBox()->floats().append(f->m_renderer);
+                    ASSERT(f->m_renderer == floats[floatIndex].object);
+                    // If a float's geometry has changed, give up on syncing with clean lines.
+                    if (floats[floatIndex].rect != IntRect(f->m_left, f->m_top, f->m_width, f->m_bottom - f->m_top))
+                        checkForEndLineMatch = false;
+                    floatIndex++;
+                }
+                lastFloat = m_floatingObjects->last();
+            }
+
+            lastHeight = m_height;
+            sNumMidpoints = 0;
+            sCurrMidpoint = 0;
+            resolver.setPosition(end);
+        }
+
+        if (endLine) {
+            if (endLineMatched) {
+                // Attach all the remaining lines, and then adjust their y-positions as needed.
+                int delta = m_height - endLineYPos;
+                for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) {
+                    line->attachLine();
+                    if (delta) {
+                        repaintTop = min(repaintTop, line->topOverflow() + min(delta, 0));
+                        repaintBottom = max(repaintBottom, line->bottomOverflow() + max(delta, 0));
+                        line->adjustPosition(0, delta);
+                    }
+                    if (Vector<RenderObject*>* cleanLineFloats = line->floatsPtr()) {
+                        Vector<RenderObject*>::iterator end = cleanLineFloats->end();
+                        for (Vector<RenderObject*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
+                            int floatTop = (*f)->yPos() - (*f)->marginTop();
+                            insertFloatingObject(*f);
+                            m_height = floatTop + delta;
+                            positionNewFloats();
+                        }
+                    }
+                }
+                m_height = lastRootBox()->blockHeight();
+            } else {
+                // Delete all the remaining lines.
+                InlineRunBox* line = endLine;
+                RenderArena* arena = renderArena();
+                while (line) {
+                    repaintTop = min(repaintTop, line->topOverflow());
+                    repaintBottom = max(repaintBottom, line->bottomOverflow());
+                    InlineRunBox* next = line->nextLineBox();
+                    line->deleteLine(arena);
+                    line = next;
+                }
+            }
+        }
+        if (m_floatingObjects && (checkForFloatsFromLastLine || positionNewFloats()) && lastRootBox()) {
+            // In case we have a float on the last line, it might not be positioned up to now.
+            // This has to be done before adding in the bottom border/padding, or the float will
+            // include the padding incorrectly. -dwh
+            if (lastFloat) {
+                for (FloatingObject* f = m_floatingObjects->last(); f != lastFloat; f = m_floatingObjects->prev()) {
+                }
+                m_floatingObjects->next();
+            } else
+                m_floatingObjects->first();
+            for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) {
+                if (f->m_bottom > lastHeight)
+                    lastRootBox()->floats().append(f->m_renderer);
+            }
+            lastFloat = m_floatingObjects->last();
+        }
+    }
+
+    sNumMidpoints = 0;
+    sCurrMidpoint = 0;
+
+    // Now add in the bottom border/padding.
+    m_height += toAdd;
+
+    // Always make sure this is at least our height.
+    m_overflowHeight = max(m_height, m_overflowHeight);
+
+    // See if any lines spill out of the block.  If so, we need to update our overflow width.
+    checkLinesForOverflow();
+
+    if (!firstLineBox() && hasLineIfEmpty())
+        m_height += lineHeight(true, true);
+
+    // See if we have any lines that spill out of our block.  If we do, then we will possibly need to
+    // truncate text.
+    if (hasTextOverflow)
+        checkLinesForTextOverflow();
+}
+
+RootInlineBox* RenderBlock::determineStartPosition(bool& fullLayout, InlineBidiResolver& resolver, Vector<FloatWithRect>& floats, unsigned& numCleanFloats)
+{
+    RootInlineBox* curr = 0;
+    RootInlineBox* last = 0;
+
+    bool dirtiedByFloat = false;
+    if (!fullLayout) {
+        size_t floatIndex = 0;
+        for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) {
+            if (Vector<RenderObject*>* cleanLineFloats = curr->floatsPtr()) {
+                Vector<RenderObject*>::iterator end = cleanLineFloats->end();
+                for (Vector<RenderObject*>::iterator o = cleanLineFloats->begin(); o != end; ++o) {
+                    RenderObject* f = *o;
+                    IntSize newSize(f->width() + f->marginLeft() +f->marginRight(), f->height() + f->marginTop() + f->marginBottom());
+                    ASSERT(floatIndex < floats.size());
+                    if (floats[floatIndex].object != f) {
+                        // A new float has been inserted before this line or before its last known float.
+                        // Just do a full layout.
+                        fullLayout = true;
+                        break;
+                    }
+                    if (floats[floatIndex].rect.size() != newSize) {
+                        int floatTop = floats[floatIndex].rect.y();
+                        curr->markDirty();
+                        markLinesDirtyInVerticalRange(curr->blockHeight(), floatTop + max(floats[floatIndex].rect.height(), newSize.height()));
+                        floats[floatIndex].rect.setSize(newSize);
+                        dirtiedByFloat = true;
+                    }
+                    floatIndex++;
+                }
+            }
+            if (dirtiedByFloat || fullLayout)
+                break;
+        }
+        // Check if a new float has been inserted after the last known float.
+        if (!curr && floatIndex < floats.size())
+            fullLayout = true;
+    }
+
+    if (fullLayout) {
+        // Nuke all our lines.
+        if (firstRootBox()) {
+            RenderArena* arena = renderArena();
+            curr = firstRootBox(); 
+            while (curr) {
+                RootInlineBox* next = curr->nextRootBox();
+                curr->deleteLine(arena);
+                curr = next;
+            }
+            ASSERT(!firstLineBox() && !lastLineBox());
+        }
+    } else {
+        if (curr) {
+            // We have a dirty line.
+            if (RootInlineBox* prevRootBox = curr->prevRootBox()) {
+                // We have a previous line.
+                if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= static_cast<RenderText*>(prevRootBox->lineBreakObj())->textLength()))
+                    // The previous line didn't break cleanly or broke at a newline
+                    // that has been deleted, so treat it as dirty too.
+                    curr = prevRootBox;
+            }
+        } else {
+            // No dirty lines were found.
+            // If the last line didn't break cleanly, treat it as dirty.
+            if (lastRootBox() && !lastRootBox()->endsWithBreak())
+                curr = lastRootBox();
+        }
+
+        // If we have no dirty lines, then last is just the last root box.
+        last = curr ? curr->prevRootBox() : lastRootBox();
+    }
+
+    numCleanFloats = 0;
+    if (!floats.isEmpty()) {
+        int savedHeight = m_height;
+        // Restore floats from clean lines.
+        RootInlineBox* line = firstRootBox();
+        while (line != curr) {
+            if (Vector<RenderObject*>* cleanLineFloats = line->floatsPtr()) {
+                Vector<RenderObject*>::iterator end = cleanLineFloats->end();
+                for (Vector<RenderObject*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
+                    insertFloatingObject(*f);
+                    m_height = (*f)->yPos() - (*f)->marginTop();
+                    positionNewFloats();
+                    ASSERT(floats[numCleanFloats].object == *f);
+                    numCleanFloats++;
+                }
+            }
+            line = line->nextRootBox();
+        }
+        m_height = savedHeight;
+    }
+
+    m_firstLine = !last;
+    previousLineBrokeCleanly = !last || last->endsWithBreak();
+
+    RenderObject* startObj;
+    int pos = 0;
+    if (last) {
+        m_height = last->blockHeight();
+        startObj = last->lineBreakObj();
+        pos = last->lineBreakPos();
+        resolver.setStatus(last->lineBreakBidiStatus());
+    } else {
+        bool ltr = style()->direction() == LTR
+    #if ENABLE(SVG)   
+            || (style()->unicodeBidi() == UBNormal && isSVGText())
+    #endif
+            ;
+
+        BidiContext* context = new BidiContext(ltr ? 0 : 1, ltr ? LeftToRight : RightToLeft, style()->unicodeBidi() == Override);
+
+        resolver.setLastStrongDir(context->dir());
+        resolver.setLastDir(context->dir());
+        resolver.setEorDir(context->dir());
+        resolver.setContext(context);
+        startObj = bidiFirst(this, &resolver);
+    }
+
+    resolver.setPosition(InlineIterator(this, startObj, pos));
+
+    return curr;
+}
+
+RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus, int& yPos)
+{
+    RootInlineBox* last = 0;
+    if (!startLine)
+        last = 0;
+    else {
+        for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->nextRootBox()) {
+            if (curr->isDirty())
+                last = 0;
+            else if (!last)
+                last = curr;
+        }
+    }
+
+    if (!last)
+        return 0;
+
+    RootInlineBox* prev = last->prevRootBox();
+    cleanLineStart = InlineIterator(this, prev->lineBreakObj(), prev->lineBreakPos());
+    cleanLineBidiStatus = prev->lineBreakBidiStatus();
+    yPos = prev->blockHeight();
+
+    for (RootInlineBox* line = last; line; line = line->nextRootBox())
+        line->extractLine(); // Disconnect all line boxes from their render objects while preserving
+                             // their connections to one another.
+
+    return last;
+}
+
+bool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus, RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop)
+{
+    if (resolver.position() == endLineStart) {
+        if (resolver.status() != endLineStatus)
+            return false;
+
+        int delta = m_height - endYPos;
+        if (!delta || !m_floatingObjects)
+            return true;
+
+        // See if any floats end in the range along which we want to shift the lines vertically.
+        int top = min(m_height, endYPos);
+
+        RootInlineBox* lastLine = endLine;
+        while (RootInlineBox* nextLine = lastLine->nextRootBox())
+            lastLine = nextLine;
+
+        int bottom = lastLine->blockHeight() + abs(delta);
+
+        for (FloatingObject* f = m_floatingObjects->first(); f; f = m_floatingObjects->next()) {
+            if (f->m_bottom >= top && f->m_bottom < bottom)
+                return false;
+        }
+
+        return true;
+    }
+
+    // The first clean line doesn't match, but we can check a handful of following lines to try
+    // to match back up.
+    static int numLines = 8; // The # of lines we're willing to match against.
+    RootInlineBox* line = endLine;
+    for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) {
+        if (line->lineBreakObj() == resolver.position().obj && line->lineBreakPos() == resolver.position().pos) {
+            // We have a match.
+            if (line->lineBreakBidiStatus() != resolver.status())
+                return false; // ...but the bidi state doesn't match.
+            RootInlineBox* result = line->nextRootBox();
+
+            // Set our yPos to be the block height of endLine.
+            if (result)
+                endYPos = line->blockHeight();
+
+            int delta = m_height - endYPos;
+            if (delta && m_floatingObjects) {
+                // See if any floats end in the range along which we want to shift the lines vertically.
+                int top = min(m_height, endYPos);
+
+                RootInlineBox* lastLine = endLine;
+                while (RootInlineBox* nextLine = lastLine->nextRootBox())
+                    lastLine = nextLine;
+
+                int bottom = lastLine->blockHeight() + abs(delta);
+
+                for (FloatingObject* f = m_floatingObjects->first(); f; f = m_floatingObjects->next()) {
+                    if (f->m_bottom >= top && f->m_bottom < bottom)
+                        return false;
+                }
+            }
+
+            // Now delete the lines that we failed to sync.
+            RootInlineBox* boxToDelete = endLine;
+            RenderArena* arena = renderArena();
+            while (boxToDelete && boxToDelete != result) {
+                repaintTop = min(repaintTop, boxToDelete->topOverflow());
+                repaintBottom = max(repaintBottom, boxToDelete->bottomOverflow());
+                RootInlineBox* next = boxToDelete->nextRootBox();
+                boxToDelete->deleteLine(arena);
+                boxToDelete = next;
+            }
+
+            endLine = result;
+            return result;
+        }
+    }
+
+    return false;
+}
+
+static inline bool skipNonBreakingSpace(const InlineIterator& it)
+{
+    if (it.obj->style()->nbspMode() != SPACE || it.current() != noBreakSpace)
+        return false;
+
+    // FIXME: This is bad.  It makes nbsp inconsistent with space and won't work correctly
+    // with m_minWidth/m_maxWidth.
+    // Do not skip a non-breaking space if it is the first character
+    // on a line after a clean line break (or on the first line, since previousLineBrokeCleanly starts off
+    // |true|).
+    if (isLineEmpty && previousLineBrokeCleanly)
+        return false;
+
+    return true;
+}
+
+static inline bool shouldCollapseWhiteSpace(const RenderStyle* style)
+{
+    return style->collapseWhiteSpace() || (style->whiteSpace() == PRE_WRAP && (!isLineEmpty || !previousLineBrokeCleanly));
+}
+
+static inline bool shouldPreserveNewline(RenderObject* object)
+{
+#if ENABLE(SVG)
+    if (object->isSVGText())
+        return false;
+#endif
+
+    return object->style()->preserveNewline();
+}
+
+static bool inlineFlowRequiresLineBox(RenderObject* flow)
+{
+    // FIXME: Right now, we only allow line boxes for inlines that are truly empty.
+    // We need to fix this, though, because at the very least, inlines containing only
+    // ignorable whitespace should should also have line boxes. 
+    return flow->isInlineFlow() && !flow->firstChild() && flow->hasHorizontalBordersPaddingOrMargin();
+}
+
+static inline bool requiresLineBox(const InlineIterator& it)
+{
+    if (it.obj->isFloatingOrPositioned())
+        return false;
+
+    if (it.obj->isInlineFlow() && !inlineFlowRequiresLineBox(it.obj))
+        return false;
+
+    if (!shouldCollapseWhiteSpace(it.obj->style()) || it.obj->isBR())
+        return true;
+
+    UChar current = it.current();
+    return current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || shouldPreserveNewline(it.obj)) && !skipNonBreakingSpace(it);
+}
+
+bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj)
+{
+    ASSERT(inlineObj->parent() == this);
+
+    InlineIterator it(this, inlineObj, 0);
+    while (!it.atEnd() && !requiresLineBox(it))
+        it.increment();
+
+    return !it.atEnd();
+}
+
+// FIXME: The entire concept of the skipTrailingWhitespace function is flawed, since we really need to be building
+// line boxes even for containers that may ultimately collapse away.  Otherwise we'll never get positioned
+// elements quite right.  In other words, we need to build this function's work into the normal line
+// object iteration process.
+// NB. this function will insert any floating elements that would otherwise
+// be skipped but it will not position them.
+void RenderBlock::skipTrailingWhitespace(InlineIterator& iterator)
+{
+    while (!iterator.atEnd() && !requiresLineBox(iterator)) {
+        RenderObject* object = iterator.obj;
+        if (object->isFloating()) {
+            insertFloatingObject(object);
+        } else if (object->isPositioned()) {
+            // FIXME: The math here is actually not really right.  It's a best-guess approximation that
+            // will work for the common cases
+            RenderObject* c = object->container();
+            if (c->isInlineFlow()) {
+                // A relative positioned inline encloses us.  In this case, we also have to determine our
+                // position as though we were an inline.  Set |staticX| and |staticY| on the relative positioned
+                // inline so that we can obtain the value later.
+                c->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : rightOffset(m_height));
+                c->setStaticY(m_height);
+            }
+    
+            if (object->hasStaticX()) {
+                if (object->style()->isOriginalDisplayInlineType())
+                    object->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : width() - rightOffset(m_height));
+                else
+                    object->setStaticX(style()->direction() == LTR ? borderLeft() + paddingLeft() : borderRight() + paddingRight());
+            }
+    
+            if (object->hasStaticY())
+                object->setStaticY(m_height);
+        }
+        iterator.increment();
+    }
+}
+
+int RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver)
+{
+    int availableWidth = lineWidth(m_height);
+    while (!resolver.position().atEnd() && !requiresLineBox(resolver.position())) {
+        RenderObject* object = resolver.position().obj;
+        if (object->isFloating()) {
+            insertFloatingObject(object);
+            positionNewFloats();
+            availableWidth = lineWidth(m_height);
+        } else if (object->isPositioned()) {
+            // FIXME: The math here is actually not really right.  It's a best-guess approximation that
+            // will work for the common cases
+            RenderObject* c = object->container();
+            if (c->isInlineFlow()) {
+                // A relative positioned inline encloses us.  In this case, we also have to determine our
+                // position as though we were an inline.  Set |staticX| and |staticY| on the relative positioned
+                // inline so that we can obtain the value later.
+                c->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : rightOffset(m_height));
+                c->setStaticY(m_height);
+            }
+    
+            if (object->hasStaticX()) {
+                if (object->style()->isOriginalDisplayInlineType())
+                    object->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : width() - rightOffset(m_height));
+                else
+                    object->setStaticX(style()->direction() == LTR ? borderLeft() + paddingLeft() : borderRight() + paddingRight());
+            }
+    
+            if (object->hasStaticY())
+                object->setStaticY(m_height);
+        }
+        resolver.increment();
+    }
+    resolver.commitExplicitEmbedding();
+    return availableWidth;
+}
+
+// This is currently just used for list markers and inline flows that have line boxes. Neither should 
+// have an effect on whitespace at the start of the line. 
+static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o)
+{
+    RenderObject* next = bidiNext(block, o);
+    if (next && !next->isBR() && next->isText() && static_cast<RenderText*>(next)->textLength() > 0) {
+        RenderText* nextText = static_cast<RenderText*>(next);
+        UChar nextChar = nextText->characters()[0];
+        if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) {
+            addMidpoint(InlineIterator(0, o, 0));
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void RenderBlock::fitBelowFloats(int widthToFit, int& availableWidth)
+{
+    ASSERT(widthToFit > availableWidth);
+
+    int floatBottom;
+    int lastFloatBottom = m_height;
+    int newLineWidth = availableWidth;
+    while (true) {
+        floatBottom = nextFloatBottomBelow(lastFloatBottom);
+        if (!floatBottom)
+            break;
+
+        newLineWidth = lineWidth(floatBottom);
+        lastFloatBottom = floatBottom;
+        if (newLineWidth >= widthToFit)
+            break;
+    }
+
+    if (newLineWidth > availableWidth) {
+        m_height = lastFloatBottom;
+        availableWidth = newLineWidth;
+    }
+}
+
+InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, EClear* clear)
+{
+    ASSERT(resolver.position().block == this);
+
+    bool appliedStartWidth = resolver.position().pos > 0;
+
+    int width = skipLeadingWhitespace(resolver);
+
+    int w = 0;
+    int tmpW = 0;
+
+    if (resolver.position().atEnd())
+        return resolver.position();
+
+    // This variable is used only if whitespace isn't set to PRE, and it tells us whether
+    // or not we are currently ignoring whitespace.
+    bool ignoringSpaces = false;
+    InlineIterator ignoreStart;
+    
+    // This variable tracks whether the very last character we saw was a space.  We use
+    // this to detect when we encounter a second space so we know we have to terminate
+    // a run.
+    bool currentCharacterIsSpace = false;
+    bool currentCharacterIsWS = false;
+    RenderObject* trailingSpaceObject = 0;
+
+    InlineIterator lBreak = resolver.position();
+
+    RenderObject *o = resolver.position().obj;
+    RenderObject *last = o;
+    unsigned pos = resolver.position().pos;
+    int nextBreakable = resolver.position().nextBreakablePosition;
+    bool atStart = true;
+
+    bool prevLineBrokeCleanly = previousLineBrokeCleanly;
+    previousLineBrokeCleanly = false;
+
+    bool autoWrapWasEverTrueOnLine = false;
+    bool floatsFitOnLine = true;
+    
+    // Firefox and Opera will allow a table cell to grow to fit an image inside it under
+    // very specific circumstances (in order to match common WinIE renderings). 
+    // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.) 
+    bool allowImagesToBreak = !style()->htmlHacks() || !isTableCell() || !style()->width().isIntrinsicOrAuto();
+
+    EWhiteSpace currWS = style()->whiteSpace();
+    EWhiteSpace lastWS = currWS;
+    while (o) {
+        currWS = o->isReplaced() ? o->parent()->style()->whiteSpace() : o->style()->whiteSpace();
+        lastWS = last->isReplaced() ? last->parent()->style()->whiteSpace() : last->style()->whiteSpace();
+        
+        bool autoWrap = RenderStyle::autoWrap(currWS);
+        autoWrapWasEverTrueOnLine = autoWrapWasEverTrueOnLine || autoWrap;
+
+#if ENABLE(SVG)
+        bool preserveNewline = o->isSVGText() ? false : RenderStyle::preserveNewline(currWS);
+#else
+        bool preserveNewline = RenderStyle::preserveNewline(currWS);
+#endif
+
+        bool collapseWhiteSpace = RenderStyle::collapseWhiteSpace(currWS);
+            
+        if (o->isBR()) {
+            if (w + tmpW <= width) {
+                lBreak.obj = o;
+                lBreak.pos = 0;
+                lBreak.nextBreakablePosition = -1;
+                lBreak.increment();
+
+                // A <br> always breaks a line, so don't let the line be collapsed
+                // away. Also, the space at the end of a line with a <br> does not
+                // get collapsed away.  It only does this if the previous line broke
+                // cleanly.  Otherwise the <br> has no effect on whether the line is
+                // empty or not.
+                if (prevLineBrokeCleanly)
+                    isLineEmpty = false;
+                trailingSpaceObject = 0;
+                previousLineBrokeCleanly = true;
+
+                if (!isLineEmpty && clear)
+                    *clear = o->style()->clear();
+            }
+            goto end;
+        }
+
+        if (o->isFloatingOrPositioned()) {
+            // add to special objects...
+            if (o->isFloating()) {
+                insertFloatingObject(o);
+                // check if it fits in the current line.
+                // If it does, position it now, otherwise, position
+                // it after moving to next line (in newLine() func)
+                if (floatsFitOnLine && o->width() + o->marginLeft() + o->marginRight() + w + tmpW <= width) {
+                    positionNewFloats();
+                    width = lineWidth(m_height);
+                } else
+                    floatsFitOnLine = false;
+            } else if (o->isPositioned()) {
+                // If our original display wasn't an inline type, then we can
+                // go ahead and determine our static x position now.
+                bool isInlineType = o->style()->isOriginalDisplayInlineType();
+                bool needToSetStaticX = o->hasStaticX();
+                if (o->hasStaticX() && !isInlineType) {
+                    o->setStaticX(o->parent()->style()->direction() == LTR ?
+                                  borderLeft() + paddingLeft() :
+                                  borderRight() + paddingRight());
+                    needToSetStaticX = false;
+                }
+
+                // If our original display was an INLINE type, then we can go ahead
+                // and determine our static y position now.
+                bool needToSetStaticY = o->hasStaticY();
+                if (o->hasStaticY() && isInlineType) {
+                    o->setStaticY(m_height);
+                    needToSetStaticY = false;
+                }
+                
+                bool needToCreateLineBox = needToSetStaticX || needToSetStaticY;
+                RenderObject* c = o->container();
+                if (c->isInlineFlow() && (!needToSetStaticX || !needToSetStaticY))
+                    needToCreateLineBox = true;
+
+                // If we're ignoring spaces, we have to stop and include this object and
+                // then start ignoring spaces again.
+                if (needToCreateLineBox) {
+                    trailingSpaceObject = 0;
+                    ignoreStart.obj = o;
+                    ignoreStart.pos = 0;
+                    if (ignoringSpaces) {
+                        addMidpoint(ignoreStart); // Stop ignoring spaces.
+                        addMidpoint(ignoreStart); // Start ignoring again.
+                    }
+                    
+                }
+            }
+        } else if (o->isInlineFlow()) {
+            // Right now, we should only encounter empty inlines here.
+            ASSERT(!o->firstChild());
+    
+            // Now that some inline flows have line boxes, if we are already ignoring spaces, we need 
+            // to make sure that we stop to include this object and then start ignoring spaces again. 
+            // If this object is at the start of the line, we need to behave like list markers and 
+            // start ignoring spaces.
+            if (inlineFlowRequiresLineBox(o)) {
+                isLineEmpty = false;
+                if (ignoringSpaces) {
+                    trailingSpaceObject = 0;
+                    addMidpoint(InlineIterator(0, o, 0)); // Stop ignoring spaces.
+                    addMidpoint(InlineIterator(0, o, 0)); // Start ignoring again.
+                } else if (style()->collapseWhiteSpace() && resolver.position().obj == o
+                    && shouldSkipWhitespaceAfterStartObject(this, o)) {
+                    // Like with list markers, we start ignoring spaces to make sure that any 
+                    // additional spaces we see will be discarded.
+                    currentCharacterIsSpace = true;
+                    currentCharacterIsWS = true;
+                    ignoringSpaces = true;
+                }
+            }
+
+            tmpW += o->marginLeft() + o->borderLeft() + o->paddingLeft() +
+                    o->marginRight() + o->borderRight() + o->paddingRight();
+        } else if (o->isReplaced()) {
+            // Break on replaced elements if either has normal white-space.
+            if ((autoWrap || RenderStyle::autoWrap(lastWS)) && (!o->isImage() || allowImagesToBreak)) {
+                w += tmpW;
+                tmpW = 0;
+                lBreak.obj = o;
+                lBreak.pos = 0;
+                lBreak.nextBreakablePosition = -1;
+            }
+
+            if (ignoringSpaces)
+                addMidpoint(InlineIterator(0, o, 0));
+
+            isLineEmpty = false;
+            ignoringSpaces = false;
+            currentCharacterIsSpace = false;
+            currentCharacterIsWS = false;
+            trailingSpaceObject = 0;
+            
+            // Optimize for a common case. If we can't find whitespace after the list
+            // item, then this is all moot. -dwh
+            if (o->isListMarker() && !static_cast<RenderListMarker*>(o)->isInside()) {
+                if (style()->collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(this, o)) {
+                    // Like with inline flows, we start ignoring spaces to make sure that any 
+                    // additional spaces we see will be discarded.
+                    currentCharacterIsSpace = true;
+                    currentCharacterIsWS = true;
+                    ignoringSpaces = true;
+                }
+            } else
+                tmpW += o->width() + o->marginLeft() + o->marginRight() + inlineWidth(o);
+        } else if (o->isText()) {
+            if (!pos)
+                appliedStartWidth = false;
+
+            RenderText* t = static_cast<RenderText*>(o);
+
+            int strlen = t->textLength();
+            int len = strlen - pos;
+            const UChar* str = t->characters();
+
+            const Font& f = t->style(m_firstLine)->font();
+
+            int lastSpace = pos;
+            int wordSpacing = o->style()->wordSpacing();
+            int lastSpaceWordSpacing = 0;
+
+            int wrapW = tmpW + inlineWidth(o, !appliedStartWidth, true);
+            int charWidth = 0;
+            bool breakNBSP = autoWrap && o->style()->nbspMode() == SPACE;
+            // Auto-wrapping text should wrap in the middle of a word only if it could not wrap before the word,
+            // which is only possible if the word is the first thing on the line, that is, if |w| is zero.
+            bool breakWords = o->style()->breakWords() && ((autoWrap && !w) || currWS == PRE);
+            bool midWordBreak = false;
+            bool breakAll = o->style()->wordBreak() == BreakAllWordBreak && autoWrap;
+
+            if (t->isWordBreak()) {
+                w += tmpW;
+                tmpW = 0;
+                lBreak.obj = o;
+                lBreak.pos = 0;
+                lBreak.nextBreakablePosition = -1;
+                ASSERT(!len);
+            }
+
+            while (len) {
+                bool previousCharacterIsSpace = currentCharacterIsSpace;
+                bool previousCharacterIsWS = currentCharacterIsWS;
+                UChar c = str[pos];
+                currentCharacterIsSpace = c == ' ' || c == '\t' || (!preserveNewline && (c == '\n'));
+
+                if (!collapseWhiteSpace || !currentCharacterIsSpace)
+                    isLineEmpty = false;
+                
+                // Check for soft hyphens.  Go ahead and ignore them.
+                if (c == softHyphen) {
+                    if (!ignoringSpaces) {
+                        // Ignore soft hyphens
+                        InlineIterator beforeSoftHyphen;
+                        if (pos)
+                            beforeSoftHyphen = InlineIterator(0, o, pos - 1);
+                        else
+                            beforeSoftHyphen = InlineIterator(0, last, last->isText() ? static_cast<RenderText*>(last)->textLength() - 1 : 0);
+                        // Two consecutive soft hyphens. Avoid overlapping midpoints.
+                        if (sNumMidpoints && smidpoints->at(sNumMidpoints - 1).obj == o && smidpoints->at(sNumMidpoints - 1).pos == pos)
+                            sNumMidpoints--;
+                        else
+                            addMidpoint(beforeSoftHyphen);
+
+                        // Add the width up to but not including the hyphen.
+                        tmpW += t->width(lastSpace, pos - lastSpace, f, w + tmpW) + lastSpaceWordSpacing;
+
+                        // For wrapping text only, include the hyphen.  We need to ensure it will fit
+                        // on the line if it shows when we break.
+                        if (autoWrap)
+                            tmpW += t->width(pos, 1, f, w + tmpW);
+
+                        InlineIterator afterSoftHyphen(0, o, pos);
+                        afterSoftHyphen.increment();
+                        addMidpoint(afterSoftHyphen);
+                    }
+
+                    pos++;
+                    len--;
+                    lastSpaceWordSpacing = 0;
+                    lastSpace = pos; // Cheesy hack to prevent adding in widths of the run twice.
+                    continue;
+                }
+                
+                bool applyWordSpacing = false;
+                
+                currentCharacterIsWS = currentCharacterIsSpace || (breakNBSP && c == noBreakSpace);
+
+                if ((breakAll || breakWords) && !midWordBreak) {
+                    wrapW += charWidth;
+                    charWidth = t->width(pos, 1, f, w + wrapW);
+                    midWordBreak = w + wrapW + charWidth > width;
+                }
+
+                bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(str, pos, strlen, nextBreakable, breakNBSP));
+    
+                if (betweenWords || midWordBreak) {
+                    bool stoppedIgnoringSpaces = false;
+                    if (ignoringSpaces) {
+                        if (!currentCharacterIsSpace) {
+                            // Stop ignoring spaces and begin at this
+                            // new point.
+                            ignoringSpaces = false;
+                            lastSpaceWordSpacing = 0;
+                            lastSpace = pos; // e.g., "Foo    goo", don't add in any of the ignored spaces.
+                            addMidpoint(InlineIterator(0, o, pos));
+                            stoppedIgnoringSpaces = true;
+                        } else {
+                            // Just keep ignoring these spaces.
+                            pos++;
+                            len--;
+                            continue;
+                        }
+                    }
+
+                    int additionalTmpW = t->width(lastSpace, pos - lastSpace, f, w+tmpW) + lastSpaceWordSpacing;
+                    tmpW += additionalTmpW;
+                    if (!appliedStartWidth) {
+                        tmpW += inlineWidth(o, true, false);
+                        appliedStartWidth = true;
+                    }
+                    
+                    applyWordSpacing =  wordSpacing && currentCharacterIsSpace && !previousCharacterIsSpace;
+
+                    if (!w && autoWrap && tmpW > width)
+                        fitBelowFloats(tmpW, width);
+
+                    if (autoWrap || breakWords) {
+                        // If we break only after white-space, consider the current character
+                        // as candidate width for this line.
+                        bool lineWasTooWide = false;
+                        if (w + tmpW <= width && currentCharacterIsWS && o->style()->breakOnlyAfterWhiteSpace() && !midWordBreak) {
+                            int charWidth = t->width(pos, 1, f, w + tmpW) + (applyWordSpacing ? wordSpacing : 0);
+                            // Check if line is too big even without the extra space
+                            // at the end of the line. If it is not, do nothing. 
+                            // If the line needs the extra whitespace to be too long, 
+                            // then move the line break to the space and skip all 
+                            // additional whitespace.
+                            if (w + tmpW + charWidth > width) {
+                                lineWasTooWide = true;
+                                lBreak.obj = o;
+                                lBreak.pos = pos;
+                                lBreak.nextBreakablePosition = nextBreakable;
+                                skipTrailingWhitespace(lBreak);
+                            }
+                        }
+                        if (lineWasTooWide || w + tmpW > width) {
+                            if (lBreak.obj && shouldPreserveNewline(lBreak.obj) && lBreak.obj->isText() && !static_cast<RenderText*>(lBreak.obj)->isWordBreak() && static_cast<RenderText*>(lBreak.obj)->characters()[lBreak.pos] == '\n') {
+                                if (!stoppedIgnoringSpaces && pos > 0) {
+                                    // We need to stop right before the newline and then start up again.
+                                    addMidpoint(InlineIterator(0, o, pos - 1)); // Stop
+                                    addMidpoint(InlineIterator(0, o, pos)); // Start
+                                }
+                                lBreak.increment();
+                                previousLineBrokeCleanly = true;
+                            }
+                            goto end; // Didn't fit. Jump to the end.
+                        } else {
+                            if (!betweenWords || (midWordBreak && !autoWrap))
+                                tmpW -= additionalTmpW;
+                            if (pos > 0 && str[pos-1] == softHyphen)
+                                // Subtract the width of the soft hyphen out since we fit on a line.
+                                tmpW -= t->width(pos-1, 1, f, w+tmpW);
+                        }
+                    }
+
+                    if (c == '\n' && preserveNewline) {
+                        if (!stoppedIgnoringSpaces && pos > 0) {
+                            // We need to stop right before the newline and then start up again.
+                            addMidpoint(InlineIterator(0, o, pos - 1)); // Stop
+                            addMidpoint(InlineIterator(0, o, pos)); // Start
+                        }
+                        lBreak.obj = o;
+                        lBreak.pos = pos;
+                        lBreak.nextBreakablePosition = nextBreakable;
+                        lBreak.increment();
+                        previousLineBrokeCleanly = true;
+                        return lBreak;
+                    }
+
+                    if (autoWrap && betweenWords) {
+                        w += tmpW;
+                        wrapW = 0;
+                        tmpW = 0;
+                        lBreak.obj = o;
+                        lBreak.pos = pos;
+                        lBreak.nextBreakablePosition = nextBreakable;
+                        // Auto-wrapping text should not wrap in the middle of a word once it has had an
+                        // opportunity to break after a word.
+                        breakWords = false;
+                    }
+                    
+                    if (midWordBreak) {
+                        // Remember this as a breakable position in case
+                        // adding the end width forces a break.
+                        lBreak.obj = o;
+                        lBreak.pos = pos;
+                        lBreak.nextBreakablePosition = nextBreakable;
+                        midWordBreak &= (breakWords || breakAll);
+                    }
+
+                    if (betweenWords) {
+                        lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
+                        lastSpace = pos;
+                    }
+                    
+                    if (!ignoringSpaces && o->style()->collapseWhiteSpace()) {
+                        // If we encounter a newline, or if we encounter a
+                        // second space, we need to go ahead and break up this
+                        // run and enter a mode where we start collapsing spaces.
+                        if (currentCharacterIsSpace && previousCharacterIsSpace) {
+                            ignoringSpaces = true;
+                            
+                            // We just entered a mode where we are ignoring
+                            // spaces. Create a midpoint to terminate the run
+                            // before the second space. 
+                            addMidpoint(ignoreStart);
+                        }
+                    }
+                } else if (ignoringSpaces) {
+                    // Stop ignoring spaces and begin at this
+                    // new point.
+                    ignoringSpaces = false;
+                    lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
+                    lastSpace = pos; // e.g., "Foo    goo", don't add in any of the ignored spaces.
+                    addMidpoint(InlineIterator(0, o, pos));
+                }
+
+                if (currentCharacterIsSpace && !previousCharacterIsSpace) {
+                    ignoreStart.obj = o;
+                    ignoreStart.pos = pos;
+                }
+
+                if (!currentCharacterIsWS && previousCharacterIsWS) {
+                    if (autoWrap && o->style()->breakOnlyAfterWhiteSpace()) {
+                        lBreak.obj = o;
+                        lBreak.pos = pos;
+                        lBreak.nextBreakablePosition = nextBreakable;
+                    }
+                }
+                
+                if (collapseWhiteSpace && currentCharacterIsSpace && !ignoringSpaces)
+                    trailingSpaceObject = o;
+                else if (!o->style()->collapseWhiteSpace() || !currentCharacterIsSpace)
+                    trailingSpaceObject = 0;
+                    
+                pos++;
+                len--;
+                atStart = false;
+            }
+
+            // IMPORTANT: pos is > length here!
+            if (!ignoringSpaces)
+                tmpW += t->width(lastSpace, pos - lastSpace, f, w+tmpW) + lastSpaceWordSpacing;
+            tmpW += inlineWidth(o, !appliedStartWidth, true);
+        } else
+            ASSERT_NOT_REACHED();
+
+        RenderObject* next = bidiNext(this, o);
+        bool checkForBreak = autoWrap;
+        if (w && w + tmpW > width && lBreak.obj && currWS == NOWRAP)
+            checkForBreak = true;
+        else if (next && o->isText() && next->isText() && !next->isBR()) {
+            if (autoWrap || (next->style()->autoWrap())) {
+                if (currentCharacterIsSpace)
+                    checkForBreak = true;
+                else {
+                    checkForBreak = false;
+                    RenderText* nextText = static_cast<RenderText*>(next);
+                    if (nextText->textLength()) {
+                        UChar c = nextText->characters()[0];
+                        if (c == ' ' || c == '\t' || (c == '\n' && !shouldPreserveNewline(next)))
+                            // If the next item on the line is text, and if we did not end with
+                            // a space, then the next text run continues our word (and so it needs to
+                            // keep adding to |tmpW|.  Just update and continue.
+                            checkForBreak = true;
+                    } else if (nextText->isWordBreak())
+                        checkForBreak = true;
+                    bool willFitOnLine = w + tmpW <= width;
+                    if (!willFitOnLine && !w) {
+                        fitBelowFloats(tmpW, width);
+                        willFitOnLine = tmpW <= width;
+                    }
+                    bool canPlaceOnLine = willFitOnLine || !autoWrapWasEverTrueOnLine;
+                    if (canPlaceOnLine && checkForBreak) {
+                        w += tmpW;
+                        tmpW = 0;
+                        lBreak.obj = next;
+                        lBreak.pos = 0;
+                        lBreak.nextBreakablePosition = -1;
+                    }
+                }
+            }
+        }
+
+        if (checkForBreak && (w + tmpW > width)) {
+            // if we have floats, try to get below them.
+            if (currentCharacterIsSpace && !ignoringSpaces && o->style()->collapseWhiteSpace())
+                trailingSpaceObject = 0;
+
+            if (w)
+                goto end;
+
+            fitBelowFloats(tmpW, width);
+
+            // |width| may have been adjusted because we got shoved down past a float (thus
+            // giving us more room), so we need to retest, and only jump to
+            // the end label if we still don't fit on the line. -dwh
+            if (w + tmpW > width)
+                goto end;
+        }
+
+        if (!o->isFloatingOrPositioned()) {
+            last = o;
+            if (last->isReplaced() && autoWrap && (!last->isImage() || allowImagesToBreak) && (!last->isListMarker() || static_cast<RenderListMarker*>(last)->isInside())) {
+                w += tmpW;
+                tmpW = 0;
+                lBreak.obj = next;
+                lBreak.pos = 0;
+                lBreak.nextBreakablePosition = -1;
+            }
+        }
+
+        o = next;
+        nextBreakable = -1;
+
+        // Clear out our character space bool, since inline <pre>s don't collapse whitespace
+        // with adjacent inline normal/nowrap spans.
+        if (!collapseWhiteSpace)
+            currentCharacterIsSpace = false;
+        
+        pos = 0;
+        atStart = false;
+    }
+
+    
+    if (w + tmpW <= width || lastWS == NOWRAP) {
+        lBreak.obj = 0;
+        lBreak.pos = 0;
+        lBreak.nextBreakablePosition = -1;
+    }
+
+ end:
+
+    if (lBreak == resolver.position() && !lBreak.obj->isBR()) {
+        // we just add as much as possible
+        if (style()->whiteSpace() == PRE) {
+            // FIXME: Don't really understand this case.
+            if (pos != 0) {
+                lBreak.obj = o;
+                lBreak.pos = pos - 1;
+            } else {
+                lBreak.obj = last;
+                lBreak.pos = last->isText() ? last->length() : 0;
+                lBreak.nextBreakablePosition = -1;
+            }
+        } else if (lBreak.obj) {
+            if (last != o && !last->isListMarker()) {
+                // better to break between object boundaries than in the middle of a word (except for list markers)
+                lBreak.obj = o;
+                lBreak.pos = 0;
+                lBreak.nextBreakablePosition = -1;
+            } else {
+                // Don't ever break in the middle of a word if we can help it.
+                // There's no room at all. We just have to be on this line,
+                // even though we'll spill out.
+                lBreak.obj = o;
+                lBreak.pos = pos;
+                lBreak.nextBreakablePosition = -1;
+            }
+        }
+    }
+
+    // make sure we consume at least one char/object.
+    if (lBreak == resolver.position())
+        lBreak.increment();
+
+    // Sanity check our midpoints.
+    checkMidpoints(lBreak);
+        
+    if (trailingSpaceObject) {
+        // This object is either going to be part of the last midpoint, or it is going
+        // to be the actual endpoint.  In both cases we just decrease our pos by 1 level to
+        // exclude the space, allowing it to - in effect - collapse into the newline.
+        if (sNumMidpoints%2==1) {
+            InlineIterator* midpoints = smidpoints->data();
+            midpoints[sNumMidpoints-1].pos--;
+        }
+        //else if (lBreak.pos > 0)
+        //    lBreak.pos--;
+        else if (lBreak.obj == 0 && trailingSpaceObject->isText()) {
+            // Add a new end midpoint that stops right at the very end.
+            RenderText* text = static_cast<RenderText *>(trailingSpaceObject);
+            unsigned length = text->textLength();
+            unsigned pos = length >= 2 ? length - 2 : UINT_MAX;
+            InlineIterator endMid(0, trailingSpaceObject, pos);
+            addMidpoint(endMid);
+        }
+    }
+
+    // We might have made lBreak an iterator that points past the end
+    // of the object. Do this adjustment to make it point to the start
+    // of the next object instead to avoid confusing the rest of the
+    // code.
+    if (lBreak.pos > 0) {
+        lBreak.pos--;
+        lBreak.increment();
+    }
+
+    if (lBreak.obj && lBreak.pos >= 2 && lBreak.obj->isText()) {
+        // For soft hyphens on line breaks, we have to chop out the midpoints that made us
+        // ignore the hyphen so that it will render at the end of the line.
+        UChar c = static_cast<RenderText*>(lBreak.obj)->characters()[lBreak.pos-1];
+        if (c == softHyphen)
+            chopMidpointsAt(lBreak.obj, lBreak.pos-2);
+    }
+    
+    return lBreak;
+}
+
+void RenderBlock::checkLinesForOverflow()
+{
+    m_overflowWidth = m_width;
+    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+        m_overflowLeft = min(curr->leftOverflow(), m_overflowLeft);
+        m_overflowTop = min(curr->topOverflow(), m_overflowTop);
+        m_overflowWidth = max(curr->rightOverflow(), m_overflowWidth);
+        m_overflowHeight = max(curr->bottomOverflow(), m_overflowHeight);
+    }
+}
+
+void RenderBlock::deleteEllipsisLineBoxes()
+{
+    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox())
+        curr->clearTruncation();
+}
+
+void RenderBlock::checkLinesForTextOverflow()
+{
+    // Determine the width of the ellipsis using the current font.
+    // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if horizontal ellipsis is "not renderable"
+    TextRun ellipsisRun(&horizontalEllipsis, 1);
+    static AtomicString ellipsisStr(&horizontalEllipsis, 1);
+    const Font& firstLineFont = firstLineStyle()->font();
+    const Font& font = style()->font();
+    int firstLineEllipsisWidth = firstLineFont.width(ellipsisRun);
+    int ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(ellipsisRun);
+
+    // For LTR text truncation, we want to get the right edge of our padding box, and then we want to see
+    // if the right edge of a line box exceeds that.  For RTL, we use the left edge of the padding box and
+    // check the left edge of the line box to see if it is less
+    // Include the scrollbar for overflow blocks, which means we want to use "contentWidth()"
+    bool ltr = style()->direction() == LTR;
+    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+        int blockEdge = ltr ? rightOffset(curr->yPos()) : leftOffset(curr->yPos());
+        int lineBoxEdge = ltr ? curr->xPos() + curr->width() : curr->xPos();
+        if ((ltr && lineBoxEdge > blockEdge) || (!ltr && lineBoxEdge < blockEdge)) {
+            // This line spills out of our box in the appropriate direction.  Now we need to see if the line
+            // can be truncated.  In order for truncation to be possible, the line must have sufficient space to
+            // accommodate our truncation string, and no replaced elements (images, tables) can overlap the ellipsis
+            // space.
+            int width = curr == firstRootBox() ? firstLineEllipsisWidth : ellipsisWidth;
+            if (curr->canAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width))
+                curr->placeEllipsis(ellipsisStr, ltr, blockEdge, width);
+        }
+    }
+}
+
+}
diff --git a/WebCore/rendering/bidi.h b/WebCore/rendering/bidi.h
new file mode 100644
index 0000000..fc6de5b
--- /dev/null
+++ b/WebCore/rendering/bidi.h
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ * Copyright (C) 2003 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef bidi_h
+#define bidi_h
+
+#include "BidiResolver.h"
+
+namespace WebCore {
+
+class RenderArena;
+class RenderBlock;
+class RenderObject;
+class InlineBox;
+
+struct BidiRun : BidiCharacterRun {
+    BidiRun(int start, int stop, RenderObject* object, BidiContext* context, WTF::Unicode::Direction dir)
+        : BidiCharacterRun(start, stop, context, dir)
+        , m_object(object)
+        , m_box(0)
+        , m_compact(false)
+    {
+    }
+
+    void destroy();
+
+    // Overloaded new operator.
+    void* operator new(size_t, RenderArena*) throw();
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void*, size_t);
+
+    BidiRun* next() { return static_cast<BidiRun*>(m_next); }
+
+private:
+    // The normal operator new is disallowed.
+    void* operator new(size_t) throw();
+
+public:
+    RenderObject* m_object;
+    InlineBox* m_box;
+    bool m_compact;
+};
+
+} // namespace WebCore
+
+#endif // bidi_h
diff --git a/WebCore/rendering/break_lines.cpp b/WebCore/rendering/break_lines.cpp
new file mode 100644
index 0000000..87029b9
--- /dev/null
+++ b/WebCore/rendering/break_lines.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "break_lines.h"
+
+#include "CharacterNames.h"
+#include "TextBreakIterator.h"
+
+#if PLATFORM(MAC)
+#include <CoreServices/CoreServices.h>
+#endif
+
+namespace WebCore {
+
+static inline bool isBreakableSpace(UChar ch, bool treatNoBreakSpaceAsBreak)
+{
+    switch (ch) {
+        case ' ':
+        case '\n':
+        case '\t':
+            return true;
+        case noBreakSpace:
+            return treatNoBreakSpaceAsBreak;
+        default:
+            return false;
+    }
+}
+
+static inline bool shouldBreakAfter(UChar ch)
+{
+    // Match WinIE's breaking strategy, which is to always allow breaks after hyphens and question marks.
+    // FIXME: it appears that IE behavior is more complex, see <http://bugs.webkit.org/show_bug.cgi?id=17475>.
+    switch (ch) {
+        case '-':
+        case '?':
+#ifdef ANDROID_LAYOUT
+        // as '/' is used in uri which is always long, we would like to break it 
+        case '/':
+#endif
+        case softHyphen:
+        // FIXME: cases for ideographicComma and ideographicFullStop are a workaround for an issue in Unicode 5.0
+        // which is likely to be resolved in Unicode 5.1 <http://bugs.webkit.org/show_bug.cgi?id=17411>.
+        // We may want to remove or conditionalize this workaround at some point.
+        case ideographicComma:
+        case ideographicFullStop:
+            return true;
+        default:
+            return false;
+    }
+}
+
+static inline bool needsLineBreakIterator(UChar ch)
+{
+    return ch > 0x7F && ch != noBreakSpace;
+}
+
+#ifdef BUILDING_ON_TIGER
+static inline TextBreakLocatorRef lineBreakLocator()
+{
+    TextBreakLocatorRef locator = 0;
+    UCCreateTextBreakLocator(0, 0, kUCTextBreakLineMask, &locator);
+    return locator;
+}
+#endif
+
+int nextBreakablePosition(const UChar* str, int pos, int len, bool treatNoBreakSpaceAsBreak)
+{
+#ifndef BUILDING_ON_TIGER
+    TextBreakIterator* breakIterator = 0;
+#endif
+    int nextBreak = -1;
+
+    UChar lastCh = pos > 0 ? str[pos - 1] : 0;
+    for (int i = pos; i < len; i++) {
+        UChar ch = str[i];
+
+        if (isBreakableSpace(ch, treatNoBreakSpaceAsBreak) || shouldBreakAfter(lastCh))
+            return i;
+
+        if (needsLineBreakIterator(ch) || needsLineBreakIterator(lastCh)) {
+            if (nextBreak < i && i) {
+#ifndef BUILDING_ON_TIGER
+                if (!breakIterator)
+                    breakIterator = lineBreakIterator(str, len);
+                if (breakIterator)
+                    nextBreak = textBreakFollowing(breakIterator, i - 1);
+#else
+                static TextBreakLocatorRef breakLocator = lineBreakLocator();
+                if (breakLocator) {
+                    UniCharArrayOffset nextUCBreak;
+                    if (UCFindTextBreak(breakLocator, kUCTextBreakLineMask, 0, str, len, i, &nextUCBreak) == 0)
+                        nextBreak = nextUCBreak;
+                }
+#endif
+            }
+            if (i == nextBreak && !isBreakableSpace(lastCh, treatNoBreakSpaceAsBreak))
+                return i;
+        }
+
+        lastCh = ch;
+    }
+
+    return len;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/break_lines.h b/WebCore/rendering/break_lines.h
new file mode 100644
index 0000000..14f740f
--- /dev/null
+++ b/WebCore/rendering/break_lines.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2005 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef break_lines_h
+#define break_lines_h
+
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+    int nextBreakablePosition(const UChar*, int pos, int len, bool breakNBSP = false);
+
+    inline bool isBreakable(const UChar* str, int pos, int len, int& nextBreakable, bool breakNBSP = false)
+    {
+        if (pos > nextBreakable)
+            nextBreakable = nextBreakablePosition(str, pos, len, breakNBSP);
+        return pos == nextBreakable;
+    }
+
+} // namespace WebCore
+
+#endif // break_lines_h
diff --git a/WebCore/rendering/style/Animation.cpp b/WebCore/rendering/style/Animation.cpp
new file mode 100644
index 0000000..ed3a7e7
--- /dev/null
+++ b/WebCore/rendering/style/Animation.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Animation.h"
+
+#include "RenderStyle.h"
+
+namespace WebCore {
+
+Animation::Animation()
+    : m_delay(RenderStyle::initialAnimationDelay())
+    , m_direction(RenderStyle::initialAnimationDirection())
+    , m_duration(RenderStyle::initialAnimationDuration())
+    , m_iterationCount(RenderStyle::initialAnimationIterationCount())
+    , m_name(RenderStyle::initialAnimationName())
+    , m_property(RenderStyle::initialAnimationProperty())
+    , m_timingFunction(RenderStyle::initialAnimationTimingFunction())
+    , m_playState(RenderStyle::initialAnimationPlayState())
+    , m_delaySet(false)
+    , m_directionSet(false)
+    , m_durationSet(false)
+    , m_iterationCountSet(false)
+    , m_nameSet(false)
+    , m_playStateSet(false)
+    , m_propertySet(false)
+    , m_timingFunctionSet(false)
+    , m_isNone(false)
+{
+}
+
+Animation::Animation(const Animation& o)
+    : RefCounted<Animation>()
+    , m_delay(o.m_delay)
+    , m_direction(o.m_direction)
+    , m_duration(o.m_duration)
+    , m_iterationCount(o.m_iterationCount)
+    , m_name(o.m_name)
+    , m_property(o.m_property)
+    , m_timingFunction(o.m_timingFunction)
+    , m_playState(o.m_playState)
+    , m_delaySet(o.m_delaySet)
+    , m_directionSet(o.m_directionSet)
+    , m_durationSet(o.m_durationSet)
+    , m_iterationCountSet(o.m_iterationCountSet)
+    , m_nameSet(o.m_nameSet)
+    , m_playStateSet(o.m_playStateSet)
+    , m_propertySet(o.m_propertySet)
+    , m_timingFunctionSet(o.m_timingFunctionSet)
+    , m_isNone(o.m_isNone)
+{
+}
+
+Animation& Animation::operator=(const Animation& o)
+{
+    m_delay = o.m_delay;
+    m_direction = o.m_direction;
+    m_duration = o.m_duration;
+    m_iterationCount = o.m_iterationCount;
+    m_name = o.m_name;
+    m_playState = o.m_playState;
+    m_property = o.m_property;
+    m_timingFunction = o.m_timingFunction;
+
+    m_delaySet = o.m_delaySet;
+    m_directionSet = o.m_directionSet;
+    m_durationSet = o.m_durationSet;
+    m_iterationCountSet = o.m_iterationCountSet;
+    m_nameSet = o.m_nameSet;
+    m_playStateSet = o.m_playStateSet;
+    m_propertySet = o.m_propertySet;
+    m_timingFunctionSet = o.m_timingFunctionSet;
+
+    m_isNone = o.m_isNone;
+
+    return *this;
+}
+
+Animation::~Animation()
+{
+}
+
+bool Animation::animationsMatch(const Animation* o, bool matchPlayStates) const
+{
+    if (!o)
+        return false;
+    
+    bool result = m_delay == o->m_delay &&
+                  m_direction == o->m_direction &&
+                  m_duration == o->m_duration &&
+                  m_iterationCount == o->m_iterationCount &&
+                  m_name == o->m_name &&
+                  m_property == o->m_property && 
+                  m_timingFunction == o->m_timingFunction &&
+                  m_delaySet == o->m_delaySet &&
+                  m_directionSet == o->m_directionSet &&
+                  m_durationSet == o->m_durationSet &&
+                  m_iterationCountSet == o->m_iterationCountSet &&
+                  m_nameSet == o->m_nameSet &&
+                  m_propertySet == o->m_propertySet &&
+                  m_timingFunctionSet == o->m_timingFunctionSet &&
+                  m_isNone == o->m_isNone;
+
+    if (!result)
+        return false;
+
+    return !matchPlayStates || (m_playState == o->m_playState && m_playStateSet == o->m_playStateSet);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/Animation.h b/WebCore/rendering/style/Animation.h
new file mode 100644
index 0000000..8930e30
--- /dev/null
+++ b/WebCore/rendering/style/Animation.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Animation_h
+#define Animation_h
+
+#include "PlatformString.h"
+#include "TimingFunction.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class Animation : public RefCounted<Animation> {
+public:
+    ~Animation();
+
+    static PassRefPtr<Animation> create() { return adoptRef(new Animation); };
+    
+    bool isDelaySet() const { return m_delaySet; }
+    bool isDirectionSet() const { return m_directionSet; }
+    bool isDurationSet() const { return m_durationSet; }
+    bool isIterationCountSet() const { return m_iterationCountSet; }
+    bool isNameSet() const { return m_nameSet; }
+    bool isPlayStateSet() const { return m_playStateSet; }
+    bool isPropertySet() const { return m_propertySet; }
+    bool isTimingFunctionSet() const { return m_timingFunctionSet; }
+
+    // Flags this to be the special "none" animation (animation-name: none)
+    bool isNoneAnimation() const { return m_isNone; }
+    // We can make placeholder Animation objects to keep the comma-separated lists
+    // of properties in sync. isValidAnimation means this is not a placeholder.
+    bool isValidAnimation() const { return !m_isNone && !m_name.isEmpty(); }
+
+    bool isEmpty() const
+    {
+        return (!m_directionSet && !m_durationSet && !m_nameSet && !m_playStateSet && 
+               !m_iterationCountSet && !m_delaySet && !m_timingFunctionSet && !m_propertySet);
+    }
+
+    bool isEmptyOrZeroDuration() const
+    {
+        return isEmpty() || (m_duration == 0 && m_delay <= 0);
+    }
+
+    void clearDelay() { m_delaySet = false; }
+    void clearDirection() { m_directionSet = false; }
+    void clearDuration() { m_durationSet = false; }
+    void clearIterationCount() { m_iterationCountSet = false; }
+    void clearName() { m_nameSet = false; }
+    void clearPlayState() { m_playStateSet = AnimPlayStatePlaying; }
+    void clearProperty() { m_propertySet = false; }
+    void clearTimingFunction() { m_timingFunctionSet = false; }
+
+    double delay() const { return m_delay; }
+    bool direction() const { return m_direction; }
+    double duration() const { return m_duration; }
+    int iterationCount() const { return m_iterationCount; }
+    const String& name() const { return m_name; }
+    unsigned playState() const { return m_playState; }
+    int property() const { return m_property; }
+    const TimingFunction& timingFunction() const { return m_timingFunction; }
+
+    void setDelay(double c) { m_delay = c; m_delaySet = true; }
+    void setDirection(bool d) { m_direction = d; m_directionSet = true; }
+    void setDuration(double d) { ASSERT(d >= 0); m_duration = d; m_durationSet = true; }
+    void setIterationCount(int c) { m_iterationCount = c; m_iterationCountSet = true; }
+    void setName(const String& n) { m_name = n; m_nameSet = true; }
+    void setPlayState(unsigned d) { m_playState = d; m_playStateSet = true; }
+    void setProperty(int t) { m_property = t; m_propertySet = true; }
+    void setTimingFunction(const TimingFunction& f) { m_timingFunction = f; m_timingFunctionSet = true; }
+
+    void setIsNoneAnimation(bool n) { m_isNone = n; }
+
+    Animation& operator=(const Animation& o);
+
+    // return true if all members of this class match (excluding m_next)
+    bool animationsMatch(const Animation*, bool matchPlayStates = true) const;
+
+    // return true every Animation in the chain (defined by m_next) match 
+    bool operator==(const Animation& o) const { return animationsMatch(&o); }
+    bool operator!=(const Animation& o) const { return !(*this == o); }
+
+private:
+    Animation();
+    Animation(const Animation& o);
+    
+    double m_delay;
+    bool m_direction;
+    double m_duration;
+    int m_iterationCount;
+    String m_name;
+    int m_property;
+    TimingFunction m_timingFunction;
+
+    unsigned m_playState     : 2;
+
+    bool m_delaySet          : 1;
+    bool m_directionSet      : 1;
+    bool m_durationSet       : 1;
+    bool m_iterationCountSet : 1;
+    bool m_nameSet           : 1;
+    bool m_playStateSet      : 1;
+    bool m_propertySet       : 1;
+    bool m_timingFunctionSet : 1;
+    
+    bool m_isNone            : 1;
+};
+
+} // namespace WebCore
+
+#endif // Animation_h
diff --git a/WebCore/rendering/style/AnimationList.cpp b/WebCore/rendering/style/AnimationList.cpp
new file mode 100644
index 0000000..804dede
--- /dev/null
+++ b/WebCore/rendering/style/AnimationList.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "AnimationList.h"
+
+namespace WebCore {
+
+#define FILL_UNSET_PROPERTY(test, propGet, propSet) \
+for (i = 0; i < size() && animation(i)->test(); ++i) { } \
+if (i < size() && i != 0) { \
+    for (size_t j = 0; i < size(); ++i, ++j) \
+        animation(i)->propSet(animation(j)->propGet()); \
+}
+
+void AnimationList::fillUnsetProperties()
+{
+    size_t i;
+    FILL_UNSET_PROPERTY(isDelaySet, delay, setDelay);
+    FILL_UNSET_PROPERTY(isDirectionSet, direction, setDirection);
+    FILL_UNSET_PROPERTY(isDurationSet, duration, setDuration);
+    FILL_UNSET_PROPERTY(isIterationCountSet, iterationCount, setIterationCount);
+    FILL_UNSET_PROPERTY(isPlayStateSet, playState, setPlayState);
+    FILL_UNSET_PROPERTY(isNameSet, name, setName);
+    FILL_UNSET_PROPERTY(isTimingFunctionSet, timingFunction, setTimingFunction);
+    FILL_UNSET_PROPERTY(isPropertySet, property, setProperty);
+}
+
+bool AnimationList::operator==(const AnimationList& o) const
+{
+    if (size() != o.size())
+        return false;
+    for (size_t i = 0; i < size(); ++i)
+        if (*animation(i) != *o.animation(i))
+            return false;
+    return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/AnimationList.h b/WebCore/rendering/style/AnimationList.h
new file mode 100644
index 0000000..9901424
--- /dev/null
+++ b/WebCore/rendering/style/AnimationList.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef AnimationList_h
+#define AnimationList_h
+
+#include "Animation.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class AnimationList {
+public:
+    void fillUnsetProperties();
+    bool operator==(const AnimationList& o) const;
+    bool operator!=(const AnimationList& o) const
+    {
+        return !(*this == o);
+    }
+    
+    size_t size() const { return m_animations.size(); }
+    bool isEmpty() const { return m_animations.isEmpty(); }
+    
+    void resize(size_t n) { m_animations.resize(n); }
+    void remove(size_t i) { m_animations.remove(i); }
+    void append(PassRefPtr<Animation> anim) { m_animations.append(anim); }
+    
+    Animation* animation(size_t i) { return m_animations[i].get(); }
+    const Animation* animation(size_t i) const { return m_animations[i].get(); }
+    
+private:
+    Vector<RefPtr<Animation> > m_animations;
+};    
+
+
+} // namespace WebCore
+
+#endif // AnimationList_h
diff --git a/WebCore/rendering/style/BindingURI.cpp b/WebCore/rendering/style/BindingURI.cpp
new file mode 100644
index 0000000..fd96de4
--- /dev/null
+++ b/WebCore/rendering/style/BindingURI.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "BindingURI.h"
+
+#if ENABLE(XBL)
+
+namespace WebCore {
+
+BindingURI::BindingURI(StringImpl* uri) 
+    : m_next(0)
+{ 
+    m_uri = uri;
+    if (uri)
+        uri->ref();
+}
+
+BindingURI::~BindingURI()
+{
+    if (m_uri)
+        m_uri->deref();
+    delete m_next;
+}
+
+BindingURI* BindingURI::copy()
+{
+    BindingURI* newBinding = new BindingURI(m_uri);
+    if (next()) {
+        BindingURI* nextCopy = next()->copy();
+        newBinding->setNext(nextCopy);
+    }
+    
+    return newBinding;
+}
+
+bool BindingURI::operator==(const BindingURI& o) const
+{
+    if ((m_next && !o.m_next) || (!m_next && o.m_next) ||
+        (m_next && o.m_next && *m_next != *o.m_next))
+        return false;
+    
+    if (m_uri == o.m_uri)
+        return true;
+    if (!m_uri || !o.m_uri)
+        return false;
+    
+    return String(m_uri) == String(o.m_uri);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XBL)
diff --git a/WebCore/rendering/style/BindingURI.h b/WebCore/rendering/style/BindingURI.h
new file mode 100644
index 0000000..923f1aa
--- /dev/null
+++ b/WebCore/rendering/style/BindingURI.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BindingURI_h
+#define BindingURI_h
+#if ENABLE(XBL)
+
+#include "StringImpl.h"
+
+namespace WebCore {
+
+// This struct holds information about shadows for the text-shadow and box-shadow properties.
+
+struct BindingURI {
+    BindingURI(StringImpl*);
+    ~BindingURI();
+
+    BindingURI* copy();
+
+    bool operator==(const BindingURI& o) const;
+    bool operator!=(const BindingURI& o) const
+    {
+        return !(*this == o);
+    }
+
+    BindingURI* next() { return m_next; }
+    void setNext(BindingURI* n) { m_next = n; }
+
+    StringImpl* uri() { return m_uri; }
+
+    BindingURI* m_next;
+    StringImpl* m_uri;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(XBL)
+#endif // BindingURI_h
diff --git a/WebCore/rendering/style/BorderData.h b/WebCore/rendering/style/BorderData.h
new file mode 100644
index 0000000..8ca0d65
--- /dev/null
+++ b/WebCore/rendering/style/BorderData.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BorderData_h
+#define BorderData_h
+
+#include "BorderValue.h"
+#include "IntSize.h"
+#include "NinePieceImage.h"
+
+namespace WebCore {
+
+class BorderData {
+public:
+    BorderValue left;
+    BorderValue right;
+    BorderValue top;
+    BorderValue bottom;
+
+    NinePieceImage image;
+
+    IntSize topLeft;
+    IntSize topRight;
+    IntSize bottomLeft;
+    IntSize bottomRight;
+
+    bool hasBorder() const
+    {
+        bool haveImage = image.hasImage();
+        return left.nonZero(!haveImage) || right.nonZero(!haveImage) || top.nonZero(!haveImage) || bottom.nonZero(!haveImage);
+    }
+
+    bool hasBorderRadius() const
+    {
+        if (topLeft.width() > 0)
+            return true;
+        if (topRight.width() > 0)
+            return true;
+        if (bottomLeft.width() > 0)
+            return true;
+        if (bottomRight.width() > 0)
+            return true;
+        return false;
+    }
+    
+    unsigned short borderLeftWidth() const
+    {
+        if (!image.hasImage() && (left.style() == BNONE || left.style() == BHIDDEN))
+            return 0; 
+        return left.width;
+    }
+    
+    unsigned short borderRightWidth() const
+    {
+        if (!image.hasImage() && (right.style() == BNONE || right.style() == BHIDDEN))
+            return 0;
+        return right.width;
+    }
+    
+    unsigned short borderTopWidth() const
+    {
+        if (!image.hasImage() && (top.style() == BNONE || top.style() == BHIDDEN))
+            return 0;
+        return top.width;
+    }
+    
+    unsigned short borderBottomWidth() const
+    {
+        if (!image.hasImage() && (bottom.style() == BNONE || bottom.style() == BHIDDEN))
+            return 0;
+        return bottom.width;
+    }
+    
+    bool operator==(const BorderData& o) const
+    {
+        return left == o.left && right == o.right && top == o.top && bottom == o.bottom && image == o.image &&
+               topLeft == o.topLeft && topRight == o.topRight && bottomLeft == o.bottomLeft && bottomRight == o.bottomRight;
+    }
+    
+    bool operator!=(const BorderData& o) const
+    {
+        return !(*this == o);
+    }
+};
+
+} // namespace WebCore
+
+#endif // BorderData_h
diff --git a/WebCore/rendering/style/BorderValue.h b/WebCore/rendering/style/BorderValue.h
new file mode 100644
index 0000000..e61e708
--- /dev/null
+++ b/WebCore/rendering/style/BorderValue.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BorderValue_h
+#define BorderValue_h
+
+#include "Color.h"
+#include "RenderStyleConstants.h"
+
+namespace WebCore {
+
+class BorderValue {
+public:
+    BorderValue()
+        : width(3)
+        , m_style(BNONE)
+    {
+    }
+
+    Color color;
+    unsigned width : 12;
+    unsigned m_style : 4; // EBorderStyle 
+
+    EBorderStyle style() const { return static_cast<EBorderStyle>(m_style); }
+    
+    bool nonZero(bool checkStyle = true) const
+    {
+        return width != 0 && (!checkStyle || m_style != BNONE);
+    }
+
+    bool isTransparent() const
+    {
+        return color.isValid() && color.alpha() == 0;
+    }
+
+    bool isVisible(bool checkStyle = true) const
+    {
+        return nonZero(checkStyle) && !isTransparent() && (!checkStyle || m_style != BHIDDEN);
+    }
+
+    bool operator==(const BorderValue& o) const
+    {
+        return width == o.width && m_style == o.m_style && color == o.color;
+    }
+
+    bool operator!=(const BorderValue& o) const
+    {
+        return !(*this == o);
+    }
+};
+
+} // namespace WebCore
+
+#endif // BorderValue_h
diff --git a/WebCore/rendering/style/CollapsedBorderValue.h b/WebCore/rendering/style/CollapsedBorderValue.h
new file mode 100644
index 0000000..805f474
--- /dev/null
+++ b/WebCore/rendering/style/CollapsedBorderValue.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CollapsedBorderValue_h
+#define CollapsedBorderValue_h
+
+#include "BorderValue.h"
+
+namespace WebCore {
+
+struct CollapsedBorderValue {
+    CollapsedBorderValue()
+        : border(0)
+        , precedence(BOFF)
+    {
+    }
+
+    CollapsedBorderValue(const BorderValue* b, EBorderPrecedence p)
+        : border(b)
+        , precedence(p)
+    {
+    }
+
+    int width() const { return border && border->nonZero() ? border->width : 0; }
+    EBorderStyle style() const { return border ? border->style() : BHIDDEN; }
+    bool exists() const { return border; }
+    Color color() const { return border ? border->color : Color(); }
+    bool isTransparent() const { return border ? border->isTransparent() : true; }
+    
+    bool operator==(const CollapsedBorderValue& o) const
+    {
+        if (!border)
+            return !o.border;
+        if (!o.border)
+            return false;
+        return *border == *o.border && precedence == o.precedence;
+    }
+    
+    const BorderValue* border;
+    EBorderPrecedence precedence;    
+};
+
+} // namespace WebCore
+
+#endif // CollapsedBorderValue_h
diff --git a/WebCore/rendering/style/ContentData.cpp b/WebCore/rendering/style/ContentData.cpp
new file mode 100644
index 0000000..b38cc49
--- /dev/null
+++ b/WebCore/rendering/style/ContentData.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ContentData.h"
+
+#include "CounterContent.h"
+#include "StringImpl.h"
+#include "StyleImage.h"
+
+namespace WebCore {
+
+void ContentData::clear()
+{
+    switch (m_type) {
+        case CONTENT_NONE:
+            break;
+        case CONTENT_OBJECT:
+            m_content.m_image->deref();
+            break;
+        case CONTENT_TEXT:
+            m_content.m_text->deref();
+            break;
+        case CONTENT_COUNTER:
+            delete m_content.m_counter;
+            break;
+    }
+
+    ContentData* n = m_next;
+    m_type = CONTENT_NONE;
+    m_next = 0;
+
+    // Reverse the list so we can delete without recursing.
+    ContentData* last = 0;
+    ContentData* c;
+    while ((c = n)) {
+        n = c->m_next;
+        c->m_next = last;
+        last = c;
+    }
+    for (c = last; c; c = n) {
+        n = c->m_next;
+        c->m_next = 0;
+        delete c;
+    }
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/ContentData.h b/WebCore/rendering/style/ContentData.h
new file mode 100644
index 0000000..d924d1a
--- /dev/null
+++ b/WebCore/rendering/style/ContentData.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ContentData_h
+#define ContentData_h
+
+#include "RenderStyleConstants.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class CounterContent;
+class StringImpl;
+class StyleImage;
+
+struct ContentData : Noncopyable {
+    ContentData()
+        : m_type(CONTENT_NONE)
+        , m_next(0)
+    {
+    }
+
+    ~ContentData()
+    {
+        clear();
+    }
+
+    void clear();
+
+    ContentType m_type;
+    union {
+        StyleImage* m_image;
+        StringImpl* m_text;
+        CounterContent* m_counter;
+    } m_content;
+    ContentData* m_next;
+};
+
+} // namespace WebCore
+
+#endif // ContentData_h
diff --git a/WebCore/rendering/style/CounterContent.h b/WebCore/rendering/style/CounterContent.h
new file mode 100644
index 0000000..06440ad
--- /dev/null
+++ b/WebCore/rendering/style/CounterContent.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CounterContent_h
+#define CounterContent_h
+
+#include "AtomicString.h"
+#include "RenderStyleConstants.h"
+
+namespace WebCore {
+
+class CounterContent {
+public:
+    CounterContent(const AtomicString& identifier, EListStyleType style, const AtomicString& separator)
+        : m_identifier(identifier)
+        , m_listStyle(style)
+        , m_separator(separator)
+    {
+    }
+
+    const AtomicString& identifier() const { return m_identifier; }
+    EListStyleType listStyle() const { return m_listStyle; }
+    const AtomicString& separator() const { return m_separator; }
+
+private:
+    AtomicString m_identifier;
+    EListStyleType m_listStyle;
+    AtomicString m_separator;
+};
+
+static inline bool operator!=(const CounterContent& a, const CounterContent& b)
+{
+    return a.identifier() != b.identifier()
+        || a.listStyle() != b.listStyle()
+        || a.separator() != b.separator();
+}
+
+
+} // namespace WebCore
+
+#endif // CounterContent_h
diff --git a/WebCore/rendering/style/CounterDirectives.cpp b/WebCore/rendering/style/CounterDirectives.cpp
new file mode 100644
index 0000000..a0ff52f
--- /dev/null
+++ b/WebCore/rendering/style/CounterDirectives.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "CounterDirectives.h"
+
+namespace WebCore {
+
+bool operator==(const CounterDirectives& a, const CounterDirectives& b)
+{
+    if (a.m_reset != b.m_reset || a.m_increment != b.m_increment)
+        return false;
+    if (a.m_reset && a.m_resetValue != b.m_resetValue)
+        return false;
+    if (a.m_increment && a.m_incrementValue != b.m_incrementValue)
+        return false;
+    return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/CounterDirectives.h b/WebCore/rendering/style/CounterDirectives.h
new file mode 100644
index 0000000..9cbdeae
--- /dev/null
+++ b/WebCore/rendering/style/CounterDirectives.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CounterDirectives_h
+#define CounterDirectives_h
+
+#include "AtomicStringImpl.h"
+#include <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+struct CounterDirectives {
+    CounterDirectives()
+        : m_reset(false)
+        , m_increment(false)
+    {
+    }
+
+    bool m_reset;
+    int m_resetValue;
+    bool m_increment;
+    int m_incrementValue;
+};
+
+bool operator==(const CounterDirectives&, const CounterDirectives&);
+inline bool operator!=(const CounterDirectives& a, const CounterDirectives& b) { return !(a == b); }
+
+typedef HashMap<RefPtr<AtomicStringImpl>, CounterDirectives> CounterDirectiveMap;
+
+} // namespace WebCore
+
+#endif // CounterDirectives_h
diff --git a/WebCore/rendering/style/CursorData.h b/WebCore/rendering/style/CursorData.h
new file mode 100644
index 0000000..7c6b31d
--- /dev/null
+++ b/WebCore/rendering/style/CursorData.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CursorData_h
+#define CursorData_h
+
+#include "CachedImage.h"
+#include "CachedResourceHandle.h"
+#include "IntPoint.h"
+
+namespace WebCore {
+
+struct CursorData {
+    CursorData()
+        : cursorImage(0)
+    {
+    }
+
+    bool operator==(const CursorData& o) const
+    {
+        return hotSpot == o.hotSpot && cursorImage == o.cursorImage;
+    }
+
+    bool operator!=(const CursorData& o) const
+    {
+        return !(*this == o);
+    }
+
+    IntPoint hotSpot; // for CSS3 support
+    CachedResourceHandle<CachedImage> cursorImage;
+};
+
+} // namespace WebCore
+
+#endif // CursorData_h
diff --git a/WebCore/rendering/style/CursorList.h b/WebCore/rendering/style/CursorList.h
new file mode 100644
index 0000000..bdd65d4
--- /dev/null
+++ b/WebCore/rendering/style/CursorList.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CursorList_h
+#define CursorList_h
+
+#include "CursorData.h"
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CursorList : public RefCounted<CursorList> {
+public:
+    static PassRefPtr<CursorList> create()
+    {
+        return adoptRef(new CursorList);
+    }
+
+    const CursorData& operator[](int i) const { return m_vector[i]; }
+
+    bool operator==(const CursorList& o) const { return m_vector == o.m_vector; }
+    bool operator!=(const CursorList& o) const { return m_vector != o.m_vector; }
+
+    size_t size() const { return m_vector.size(); }
+    void append(const CursorData& cursorData) { m_vector.append(cursorData); }
+
+private:
+    CursorList()
+    {
+    }
+
+    Vector<CursorData> m_vector;
+};
+
+} // namespace WebCore
+
+#endif // CursorList_h
diff --git a/WebCore/rendering/style/DataRef.h b/WebCore/rendering/style/DataRef.h
new file mode 100644
index 0000000..c8d8072
--- /dev/null
+++ b/WebCore/rendering/style/DataRef.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DataRef_h
+#define DataRef_h
+
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+template <typename T> class DataRef {
+public:
+    const T* get() const { return m_data.get(); }
+
+    const T& operator*() const { return *get(); }
+    const T* operator->() const { return get(); }
+
+    T* access()
+    {
+        if (!m_data->hasOneRef())
+            m_data = m_data->copy();
+        return m_data.get();
+    }
+
+    void init()
+    {
+        ASSERT(!m_data);
+        m_data = T::create();
+    }
+
+    bool operator==(const DataRef<T>& o) const
+    {
+        ASSERT(m_data);
+        ASSERT(o.m_data);
+        return m_data == o.m_data || *m_data == *o.m_data;
+    }
+    
+    bool operator!=(const DataRef<T>& o) const
+    {
+        ASSERT(m_data);
+        ASSERT(o.m_data);
+        return m_data != o.m_data && *m_data != *o.m_data;
+    }
+
+private:
+    RefPtr<T> m_data;
+};
+
+} // namespace WebCore
+
+#endif // DataRef_h
diff --git a/WebCore/rendering/style/FillLayer.cpp b/WebCore/rendering/style/FillLayer.cpp
new file mode 100644
index 0000000..9c491aa
--- /dev/null
+++ b/WebCore/rendering/style/FillLayer.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "FillLayer.h"
+
+namespace WebCore {
+
+FillLayer::FillLayer(EFillLayerType type)
+    : m_image(FillLayer::initialFillImage(type))
+    , m_xPosition(FillLayer::initialFillXPosition(type))
+    , m_yPosition(FillLayer::initialFillYPosition(type))
+    , m_attachment(FillLayer::initialFillAttachment(type))
+    , m_clip(FillLayer::initialFillClip(type))
+    , m_origin(FillLayer::initialFillOrigin(type))
+    , m_repeat(FillLayer::initialFillRepeat(type))
+    , m_composite(FillLayer::initialFillComposite(type))
+    , m_size(FillLayer::initialFillSize(type))
+    , m_imageSet(false)
+    , m_attachmentSet(false)
+    , m_clipSet(false)
+    , m_originSet(false)
+    , m_repeatSet(false)
+    , m_xPosSet(false)
+    , m_yPosSet(false)
+    , m_compositeSet(type == MaskFillLayer)
+    , m_sizeSet(false)
+    , m_type(type)
+    , m_next(0)
+{
+}
+
+FillLayer::FillLayer(const FillLayer& o)
+    : m_image(o.m_image)
+    , m_xPosition(o.m_xPosition)
+    , m_yPosition(o.m_yPosition)
+    , m_attachment(o.m_attachment)
+    , m_clip(o.m_clip)
+    , m_origin(o.m_origin)
+    , m_repeat(o.m_repeat)
+    , m_composite(o.m_composite)
+    , m_size(o.m_size)
+    , m_imageSet(o.m_imageSet)
+    , m_attachmentSet(o.m_attachmentSet)
+    , m_clipSet(o.m_clipSet)
+    , m_originSet(o.m_originSet)
+    , m_repeatSet(o.m_repeatSet)
+    , m_xPosSet(o.m_xPosSet)
+    , m_yPosSet(o.m_yPosSet)
+    , m_compositeSet(o.m_compositeSet)
+    , m_sizeSet(o.m_sizeSet)
+    , m_type(o.m_type)
+    , m_next(o.m_next ? new FillLayer(*o.m_next) : 0)
+{
+}
+
+FillLayer::~FillLayer()
+{
+    delete m_next;
+}
+
+FillLayer& FillLayer::operator=(const FillLayer& o)
+{
+    if (m_next != o.m_next) {
+        delete m_next;
+        m_next = o.m_next ? new FillLayer(*o.m_next) : 0;
+    }
+
+    m_image = o.m_image;
+    m_xPosition = o.m_xPosition;
+    m_yPosition = o.m_yPosition;
+    m_attachment = o.m_attachment;
+    m_clip = o.m_clip;
+    m_composite = o.m_composite;
+    m_origin = o.m_origin;
+    m_repeat = o.m_repeat;
+    m_size = o.m_size;
+
+    m_imageSet = o.m_imageSet;
+    m_attachmentSet = o.m_attachmentSet;
+    m_clipSet = o.m_clipSet;
+    m_compositeSet = o.m_compositeSet;
+    m_originSet = o.m_originSet;
+    m_repeatSet = o.m_repeatSet;
+    m_xPosSet = o.m_xPosSet;
+    m_yPosSet = o.m_yPosSet;
+    m_sizeSet = o.m_sizeSet;
+    
+    m_type = o.m_type;
+
+    return *this;
+}
+
+bool FillLayer::operator==(const FillLayer& o) const
+{
+    // We do not check the "isSet" booleans for each property, since those are only used during initial construction
+    // to propagate patterns into layers.  All layer comparisons happen after values have all been filled in anyway.
+    return StyleImage::imagesEquivalent(m_image.get(), o.m_image.get()) && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition &&
+           m_attachment == o.m_attachment && m_clip == o.m_clip && 
+           m_composite == o.m_composite && m_origin == o.m_origin && m_repeat == o.m_repeat &&
+           m_size == o.m_size && m_type == o.m_type &&
+           ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next);
+}
+
+void FillLayer::fillUnsetProperties()
+{
+    FillLayer* curr;
+    for (curr = this; curr && curr->isImageSet(); curr = curr->next()) { }
+    if (curr && curr != this) {
+        // We need to fill in the remaining values with the pattern specified.
+        for (FillLayer* pattern = this; curr; curr = curr->next()) {
+            curr->m_image = pattern->m_image;
+            pattern = pattern->next();
+            if (pattern == curr || !pattern)
+                pattern = this;
+        }
+    }
+    
+    for (curr = this; curr && curr->isXPositionSet(); curr = curr->next()) { }
+    if (curr && curr != this) {
+        // We need to fill in the remaining values with the pattern specified.
+        for (FillLayer* pattern = this; curr; curr = curr->next()) {
+            curr->m_xPosition = pattern->m_xPosition;
+            pattern = pattern->next();
+            if (pattern == curr || !pattern)
+                pattern = this;
+        }
+    }
+    
+    for (curr = this; curr && curr->isYPositionSet(); curr = curr->next()) { }
+    if (curr && curr != this) {
+        // We need to fill in the remaining values with the pattern specified.
+        for (FillLayer* pattern = this; curr; curr = curr->next()) {
+            curr->m_yPosition = pattern->m_yPosition;
+            pattern = pattern->next();
+            if (pattern == curr || !pattern)
+                pattern = this;
+        }
+    }
+    
+    for (curr = this; curr && curr->isAttachmentSet(); curr = curr->next()) { }
+    if (curr && curr != this) {
+        // We need to fill in the remaining values with the pattern specified.
+        for (FillLayer* pattern = this; curr; curr = curr->next()) {
+            curr->m_attachment = pattern->m_attachment;
+            pattern = pattern->next();
+            if (pattern == curr || !pattern)
+                pattern = this;
+        }
+    }
+    
+    for (curr = this; curr && curr->isClipSet(); curr = curr->next()) { }
+    if (curr && curr != this) {
+        // We need to fill in the remaining values with the pattern specified.
+        for (FillLayer* pattern = this; curr; curr = curr->next()) {
+            curr->m_clip = pattern->m_clip;
+            pattern = pattern->next();
+            if (pattern == curr || !pattern)
+                pattern = this;
+        }
+    }
+
+    for (curr = this; curr && curr->isCompositeSet(); curr = curr->next()) { }
+    if (curr && curr != this) {
+        // We need to fill in the remaining values with the pattern specified.
+        for (FillLayer* pattern = this; curr; curr = curr->next()) {
+            curr->m_composite = pattern->m_composite;
+            pattern = pattern->next();
+            if (pattern == curr || !pattern)
+                pattern = this;
+        }
+    }
+
+    for (curr = this; curr && curr->isOriginSet(); curr = curr->next()) { }
+    if (curr && curr != this) {
+        // We need to fill in the remaining values with the pattern specified.
+        for (FillLayer* pattern = this; curr; curr = curr->next()) {
+            curr->m_origin = pattern->m_origin;
+            pattern = pattern->next();
+            if (pattern == curr || !pattern)
+                pattern = this;
+        }
+    }
+
+    for (curr = this; curr && curr->isRepeatSet(); curr = curr->next()) { }
+    if (curr && curr != this) {
+        // We need to fill in the remaining values with the pattern specified.
+        for (FillLayer* pattern = this; curr; curr = curr->next()) {
+            curr->m_repeat = pattern->m_repeat;
+            pattern = pattern->next();
+            if (pattern == curr || !pattern)
+                pattern = this;
+        }
+    }
+    
+    for (curr = this; curr && curr->isSizeSet(); curr = curr->next()) { }
+    if (curr && curr != this) {
+        // We need to fill in the remaining values with the pattern specified.
+        for (FillLayer* pattern = this; curr; curr = curr->next()) {
+            curr->m_size = pattern->m_size;
+            pattern = pattern->next();
+            if (pattern == curr || !pattern)
+                pattern = this;
+        }
+    }
+}
+
+void FillLayer::cullEmptyLayers()
+{
+    FillLayer* next;
+    for (FillLayer* p = this; p; p = next) {
+        next = p->m_next;
+        if (next && !next->isImageSet() &&
+            !next->isXPositionSet() && !next->isYPositionSet() &&
+            !next->isAttachmentSet() && !next->isClipSet() &&
+            !next->isCompositeSet() && !next->isOriginSet() &&
+            !next->isRepeatSet() && !next->isSizeSet()) {
+            delete next;
+            p->m_next = 0;
+            break;
+        }
+    }
+}
+
+bool FillLayer::containsImage(StyleImage* s) const
+{
+    if (!s)
+        return false;
+    if (m_image && *s == *m_image)
+        return true;
+    if (m_next)
+        return m_next->containsImage(s);
+    return false;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/FillLayer.h b/WebCore/rendering/style/FillLayer.h
new file mode 100644
index 0000000..8f0ad94
--- /dev/null
+++ b/WebCore/rendering/style/FillLayer.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FillLayer_h
+#define FillLayer_h
+
+#include "GraphicsTypes.h"
+#include "Length.h"
+#include "LengthSize.h"
+#include "RenderStyleConstants.h"
+#include "StyleImage.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+struct FillLayer {
+public:
+    FillLayer(EFillLayerType);
+    ~FillLayer();
+
+    StyleImage* image() const { return m_image.get(); }
+    Length xPosition() const { return m_xPosition; }
+    Length yPosition() const { return m_yPosition; }
+    bool attachment() const { return m_attachment; }
+    EFillBox clip() const { return static_cast<EFillBox>(m_clip); }
+    EFillBox origin() const { return static_cast<EFillBox>(m_origin); }
+    EFillRepeat repeat() const { return static_cast<EFillRepeat>(m_repeat); }
+    CompositeOperator composite() const { return static_cast<CompositeOperator>(m_composite); }
+    LengthSize size() const { return m_size; }
+
+    const FillLayer* next() const { return m_next; }
+    FillLayer* next() { return m_next; }
+
+    bool isImageSet() const { return m_imageSet; }
+    bool isXPositionSet() const { return m_xPosSet; }
+    bool isYPositionSet() const { return m_yPosSet; }
+    bool isAttachmentSet() const { return m_attachmentSet; }
+    bool isClipSet() const { return m_clipSet; }
+    bool isOriginSet() const { return m_originSet; }
+    bool isRepeatSet() const { return m_repeatSet; }
+    bool isCompositeSet() const { return m_compositeSet; }
+    bool isSizeSet() const { return m_sizeSet; }
+    
+    void setImage(StyleImage* i) { m_image = i; m_imageSet = true; }
+    void setXPosition(const Length& l) { m_xPosition = l; m_xPosSet = true; }
+    void setYPosition(const Length& l) { m_yPosition = l; m_yPosSet = true; }
+    void setAttachment(bool b) { m_attachment = b; m_attachmentSet = true; }
+    void setClip(EFillBox b) { m_clip = b; m_clipSet = true; }
+    void setOrigin(EFillBox b) { m_origin = b; m_originSet = true; }
+    void setRepeat(EFillRepeat r) { m_repeat = r; m_repeatSet = true; }
+    void setComposite(CompositeOperator c) { m_composite = c; m_compositeSet = true; }
+    void setSize(const LengthSize& b) { m_size = b; m_sizeSet = true; }
+    
+    void clearImage() { m_imageSet = false; }
+    void clearXPosition() { m_xPosSet = false; }
+    void clearYPosition() { m_yPosSet = false; }
+    void clearAttachment() { m_attachmentSet = false; }
+    void clearClip() { m_clipSet = false; }
+    void clearOrigin() { m_originSet = false; }
+    void clearRepeat() { m_repeatSet = false; }
+    void clearComposite() { m_compositeSet = false; }
+    void clearSize() { m_sizeSet = false; }
+
+    void setNext(FillLayer* n) { if (m_next != n) { delete m_next; m_next = n; } }
+
+    FillLayer& operator=(const FillLayer& o);    
+    FillLayer(const FillLayer& o);
+
+    bool operator==(const FillLayer& o) const;
+    bool operator!=(const FillLayer& o) const
+    {
+        return !(*this == o);
+    }
+
+    bool containsImage(StyleImage*) const;
+
+    bool hasImage() const
+    {
+        if (m_image)
+            return true;
+        return m_next ? m_next->hasImage() : false;
+    }
+
+    bool hasFixedImage() const
+    {
+        if (m_image && !m_attachment)
+            return true;
+        return m_next ? m_next->hasFixedImage() : false;
+    }
+
+    EFillLayerType type() const { return static_cast<EFillLayerType>(m_type); }
+
+    void fillUnsetProperties();
+    void cullEmptyLayers();
+
+    static bool initialFillAttachment(EFillLayerType) { return true; }
+    static EFillBox initialFillClip(EFillLayerType) { return BorderFillBox; }
+    static EFillBox initialFillOrigin(EFillLayerType type) { return type == BackgroundFillLayer ? PaddingFillBox : BorderFillBox; }
+    static EFillRepeat initialFillRepeat(EFillLayerType) { return RepeatFill; }
+    static CompositeOperator initialFillComposite(EFillLayerType) { return CompositeSourceOver; }
+    static LengthSize initialFillSize(EFillLayerType) { return LengthSize(); }
+    static Length initialFillXPosition(EFillLayerType type) { return Length(0.0, Percent); }
+    static Length initialFillYPosition(EFillLayerType type) { return Length(0.0, Percent); }
+    static StyleImage* initialFillImage(EFillLayerType) { return 0; }
+
+private:
+    FillLayer() { }
+
+public:
+    RefPtr<StyleImage> m_image;
+
+    Length m_xPosition;
+    Length m_yPosition;
+
+    bool m_attachment : 1;
+    unsigned m_clip : 2; // EFillBox
+    unsigned m_origin : 2; // EFillBox
+    unsigned m_repeat : 2; // EFillRepeat
+    unsigned m_composite : 4; // CompositeOperator
+
+    LengthSize m_size;
+
+    bool m_imageSet : 1;
+    bool m_attachmentSet : 1;
+    bool m_clipSet : 1;
+    bool m_originSet : 1;
+    bool m_repeatSet : 1;
+    bool m_xPosSet : 1;
+    bool m_yPosSet : 1;
+    bool m_compositeSet : 1;
+    bool m_sizeSet : 1;
+    
+    unsigned m_type : 1; // EFillLayerType
+
+    FillLayer* m_next;
+};
+
+} // namespace WebCore
+
+#endif // FillLayer_h
diff --git a/WebCore/rendering/style/IdentityTransformOperation.h b/WebCore/rendering/style/IdentityTransformOperation.h
new file mode 100644
index 0000000..54c49a3
--- /dev/null
+++ b/WebCore/rendering/style/IdentityTransformOperation.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef IdentityTransformOperation_h
+#define IdentityTransformOperation_h
+
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class IdentityTransformOperation : public TransformOperation {
+public:
+    static PassRefPtr<IdentityTransformOperation> create()
+    {
+        return adoptRef(new IdentityTransformOperation());
+    }
+        
+    virtual bool isIdentity() const { return true; }
+    virtual OperationType getOperationType() const { return IDENTITY; }
+    virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == IDENTITY; }
+
+    virtual bool operator==(const TransformOperation& o) const
+    {
+        return isSameType(o);
+    }
+
+    virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
+    {
+        return false;
+    }
+
+    virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false)
+    {
+        return this;
+    }
+
+private:
+    IdentityTransformOperation()
+    {
+    }
+
+};
+
+} // namespace WebCore
+
+#endif // IdentityTransformOperation_h
diff --git a/WebCore/rendering/style/KeyframeList.cpp b/WebCore/rendering/style/KeyframeList.cpp
new file mode 100644
index 0000000..41fbbe2
--- /dev/null
+++ b/WebCore/rendering/style/KeyframeList.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "KeyframeList.h"
+#include "RenderObject.h"
+
+namespace WebCore {
+
+KeyframeList::~KeyframeList()
+{
+    clear();
+}
+
+void KeyframeList::clear()
+{
+    m_keyframes.clear();
+    m_properties.clear();
+}
+
+bool KeyframeList::operator==(const KeyframeList& o) const
+{
+    if (m_keyframes.size() != o.m_keyframes.size())
+        return false;
+
+    Vector<KeyframeValue>::const_iterator it2 = o.m_keyframes.begin();
+    for (Vector<KeyframeValue>::const_iterator it1 = m_keyframes.begin(); it1 != m_keyframes.end(); ++it1) {
+        if (it1->m_key != it2->m_key)
+            return false;
+        const RenderStyle& style1 = *it1->m_style;
+        const RenderStyle& style2 = *it2->m_style;
+        if (style1 != style2)
+            return false;
+        ++it2;
+    }
+
+    return true;
+}
+
+void KeyframeList::insert(float key, PassRefPtr<RenderStyle> style)
+{
+    if (key < 0 || key > 1)
+        return;
+
+    int index = -1;
+    
+    for (size_t i = 0; i < m_keyframes.size(); ++i) {
+        if (m_keyframes[i].m_key == key) {
+            index = (int) i;
+            break;
+        }
+        if (m_keyframes[i].m_key > key) {
+            // insert before
+            m_keyframes.insert(i, KeyframeValue());
+            index = (int) i;
+            break;
+        }
+    }
+    
+    if (index < 0) {
+        // append
+        index = (int) m_keyframes.size();
+        m_keyframes.append(KeyframeValue());
+    }
+    
+    m_keyframes[index].m_key = key;
+    m_keyframes[index].m_style = style;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/KeyframeList.h b/WebCore/rendering/style/KeyframeList.h
new file mode 100644
index 0000000..b1009d2
--- /dev/null
+++ b/WebCore/rendering/style/KeyframeList.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef KeyframeList_h
+#define KeyframeList_h
+
+#include "AtomicString.h"
+#include <wtf/Vector.h>
+#include <wtf/HashSet.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class RenderObject;
+class RenderStyle;
+
+class KeyframeValue {
+public:
+    KeyframeValue()
+        : m_key(-1)
+    {
+    }
+
+    float key() const { return m_key; }
+    const RenderStyle* style() const { return m_style.get(); }
+
+    float m_key;
+    RefPtr<RenderStyle> m_style;
+};
+
+class KeyframeList {
+public:
+    KeyframeList(RenderObject* renderer, const AtomicString& animationName)
+        : m_animationName(animationName)
+        , m_renderer(renderer)
+    {
+        insert(0, 0);
+        insert(1, 0);
+    }
+    ~KeyframeList();
+        
+    bool operator==(const KeyframeList& o) const;
+    bool operator!=(const KeyframeList& o) const { return !(*this == o); }
+    
+    const AtomicString& animationName() const { return m_animationName; }
+    
+    void insert(float key, PassRefPtr<RenderStyle> style);
+    
+    void addProperty(int prop) { m_properties.add(prop); }
+    bool containsProperty(int prop) const { return m_properties.contains(prop); }
+    HashSet<int>::const_iterator beginProperties() const { return m_properties.begin(); }
+    HashSet<int>::const_iterator endProperties() const { return m_properties.end(); }
+    
+    void clear();
+    bool isEmpty() const { return m_keyframes.isEmpty(); }
+    size_t size() const { return m_keyframes.size(); }
+    Vector<KeyframeValue>::const_iterator beginKeyframes() const { return m_keyframes.begin(); }
+    Vector<KeyframeValue>::const_iterator endKeyframes() const { return m_keyframes.end(); }
+
+private:
+    AtomicString m_animationName;
+    Vector<KeyframeValue> m_keyframes;
+    HashSet<int> m_properties;       // the properties being animated
+    RenderObject* m_renderer;
+};
+
+} // namespace WebCore
+
+#endif // KeyframeList_h
diff --git a/WebCore/rendering/style/MatrixTransformOperation.cpp b/WebCore/rendering/style/MatrixTransformOperation.cpp
new file mode 100644
index 0000000..c41ae3e
--- /dev/null
+++ b/WebCore/rendering/style/MatrixTransformOperation.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "MatrixTransformOperation.h"
+
+#include <algorithm>
+
+namespace WebCore {
+
+PassRefPtr<TransformOperation> MatrixTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
+{
+    if (from && !from->isSameType(*this))
+        return this;
+
+    // convert the TransformOperations into matrices
+    IntSize size;
+    AffineTransform fromT;
+    AffineTransform toT(m_a, m_b, m_c, m_d, m_e, m_f);
+    if (from) {
+        const MatrixTransformOperation* m = static_cast<const MatrixTransformOperation*>(from);
+        fromT.setMatrix(m->m_a, m->m_b, m->m_c, m->m_d, m->m_e, m->m_f);
+    }
+    
+    if (blendToIdentity)
+        std::swap(fromT, toT);
+
+    toT.blend(fromT, progress);
+    return MatrixTransformOperation::create(toT.a(), toT.b(), toT.c(), toT.d(), toT.e(), toT.f());
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/MatrixTransformOperation.h b/WebCore/rendering/style/MatrixTransformOperation.h
new file mode 100644
index 0000000..574f2a8
--- /dev/null
+++ b/WebCore/rendering/style/MatrixTransformOperation.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MatrixTransformOperation_h
+#define MatrixTransformOperation_h
+
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class MatrixTransformOperation : public TransformOperation {
+public:
+    static PassRefPtr<MatrixTransformOperation> create(double a, double b, double c, double d, double e, double f)
+    {
+        return adoptRef(new MatrixTransformOperation(a, b, c, d, e, f));
+    }
+
+    virtual bool isIdentity() const { return m_a == 1 && m_b == 0 && m_c == 0 && m_d == 1 && m_e == 0 && m_f == 0; }
+    virtual OperationType getOperationType() const { return MATRIX; }
+    virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == MATRIX; }
+
+    virtual bool operator==(const TransformOperation& o) const
+    {
+        if (!isSameType(o))
+            return false;
+
+        const MatrixTransformOperation* m = static_cast<const MatrixTransformOperation*>(&o);
+        return m_a == m->m_a && m_b == m->m_b && m_c == m->m_c && m_d == m->m_d && m_e == m->m_e && m_f == m->m_f;
+    }
+
+    virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
+    {
+        AffineTransform matrix(m_a, m_b, m_c, m_d, m_e, m_f);
+        transform = matrix * transform;
+        return false;
+    }
+
+    virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
+    
+private:
+    MatrixTransformOperation(double a, double b, double c, double d, double e, double f)
+        : m_a(a)
+        , m_b(b)
+        , m_c(c)
+        , m_d(d)
+        , m_e(e)
+        , m_f(f)
+    {
+    }
+    
+    double m_a;
+    double m_b;
+    double m_c;
+    double m_d;
+    double m_e;
+    double m_f;
+};
+
+} // namespace WebCore
+
+#endif // MatrixTransformOperation_h
diff --git a/WebCore/rendering/style/NinePieceImage.cpp b/WebCore/rendering/style/NinePieceImage.cpp
new file mode 100644
index 0000000..d585e8f
--- /dev/null
+++ b/WebCore/rendering/style/NinePieceImage.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "NinePieceImage.h"
+
+namespace WebCore {
+
+bool NinePieceImage::operator==(const NinePieceImage& o) const
+{
+    return StyleImage::imagesEquivalent(m_image.get(), o.m_image.get()) && m_slices == o.m_slices && m_horizontalRule == o.m_horizontalRule &&
+           m_verticalRule == o.m_verticalRule;
+}
+
+}
diff --git a/WebCore/rendering/style/NinePieceImage.h b/WebCore/rendering/style/NinePieceImage.h
new file mode 100644
index 0000000..bf47ce6
--- /dev/null
+++ b/WebCore/rendering/style/NinePieceImage.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NinePieceImage_h
+#define NinePieceImage_h
+
+#include "LengthBox.h"
+#include "StyleImage.h"
+
+namespace WebCore {
+
+enum ENinePieceImageRule {
+    StretchImageRule, RoundImageRule, RepeatImageRule
+};
+
+class NinePieceImage {
+public:
+    NinePieceImage()
+        : m_image(0)
+        , m_horizontalRule(StretchImageRule)
+        , m_verticalRule(StretchImageRule)
+    {
+    }
+
+    NinePieceImage(StyleImage* image, LengthBox slices, ENinePieceImageRule h, ENinePieceImageRule v) 
+      : m_image(image)
+      , m_slices(slices)
+      , m_horizontalRule(h)
+      , m_verticalRule(v)
+    {
+    }
+
+    bool operator==(const NinePieceImage& o) const;
+    bool operator!=(const NinePieceImage& o) const { return !(*this == o); }
+
+    bool hasImage() const { return m_image != 0; }
+    StyleImage* image() const { return m_image.get(); }
+    
+    ENinePieceImageRule horizontalRule() const { return static_cast<ENinePieceImageRule>(m_horizontalRule); }
+    ENinePieceImageRule verticalRule() const { return static_cast<ENinePieceImageRule>(m_verticalRule); }
+    
+    RefPtr<StyleImage> m_image;
+    LengthBox m_slices;
+    unsigned m_horizontalRule : 2; // ENinePieceImageRule
+    unsigned m_verticalRule : 2; // ENinePieceImageRule
+};
+
+} // namespace WebCore
+
+#endif // NinePieceImage_h
diff --git a/WebCore/rendering/style/OutlineValue.h b/WebCore/rendering/style/OutlineValue.h
new file mode 100644
index 0000000..2628b7f
--- /dev/null
+++ b/WebCore/rendering/style/OutlineValue.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef OutlineValue_h
+#define OutlineValue_h
+
+#include "BorderValue.h"
+
+namespace WebCore {
+
+class OutlineValue : public BorderValue {
+public:
+    OutlineValue()
+        : _offset(0)
+        , _auto(false)
+    {
+    }
+    
+    bool operator==(const OutlineValue& o) const
+    {
+        return width == o.width && m_style == o.m_style && color == o.color && _offset == o._offset && _auto == o._auto;
+    }
+    
+    bool operator!=(const OutlineValue& o) const
+    {
+        return !(*this == o);
+    }
+    
+    int _offset;
+    bool _auto;
+};
+
+} // namespace WebCore
+
+#endif // OutlineValue_h
diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp
new file mode 100644
index 0000000..5088c33
--- /dev/null
+++ b/WebCore/rendering/style/RenderStyle.cpp
@@ -0,0 +1,841 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderStyle.h"
+
+#include "CSSStyleSelector.h"
+#include "CachedImage.h"
+#include "CounterContent.h"
+#include "FontSelector.h"
+#include "RenderArena.h"
+#include "RenderObject.h"
+#include "StyleImage.h"
+#include <algorithm>
+
+namespace WebCore {
+
+inline RenderStyle* defaultStyle()
+{
+    static RenderStyle* s_defaultStyle = RenderStyle::createDefaultStyle().releaseRef();
+    return s_defaultStyle;
+}
+
+PassRefPtr<RenderStyle> RenderStyle::create()
+{
+    return adoptRef(new RenderStyle());
+}
+
+PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle()
+{
+    return adoptRef(new RenderStyle(true));
+}
+
+PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other)
+{
+    return adoptRef(new RenderStyle(*other));
+}
+
+RenderStyle::RenderStyle()
+    : box(defaultStyle()->box)
+    , visual(defaultStyle()->visual)
+    , background(defaultStyle()->background)
+    , surround(defaultStyle()->surround)
+    , rareNonInheritedData(defaultStyle()->rareNonInheritedData)
+    , rareInheritedData(defaultStyle()->rareInheritedData)
+    , inherited(defaultStyle()->inherited)
+    , m_pseudoState(PseudoUnknown)
+    , m_affectedByAttributeSelectors(false)
+    , m_unique(false)
+    , m_affectedByEmpty(false)
+    , m_emptyState(false)
+    , m_childrenAffectedByFirstChildRules(false)
+    , m_childrenAffectedByLastChildRules(false)
+    , m_childrenAffectedByDirectAdjacentRules(false)
+    , m_childrenAffectedByForwardPositionalRules(false)
+    , m_childrenAffectedByBackwardPositionalRules(false)
+    , m_firstChildState(false)
+    , m_lastChildState(false)
+    , m_childIndex(0)
+#if ENABLE(SVG)
+    , m_svgStyle(defaultStyle()->m_svgStyle)
+#endif
+{
+    setBitDefaults(); // Would it be faster to copy this from the default style?
+}
+
+RenderStyle::RenderStyle(bool)
+    : m_pseudoState(PseudoUnknown)
+    , m_affectedByAttributeSelectors(false)
+    , m_unique(false)
+    , m_affectedByEmpty(false)
+    , m_emptyState(false)
+    , m_childrenAffectedByFirstChildRules(false)
+    , m_childrenAffectedByLastChildRules(false)
+    , m_childrenAffectedByDirectAdjacentRules(false)
+    , m_childrenAffectedByForwardPositionalRules(false)
+    , m_childrenAffectedByBackwardPositionalRules(false)
+    , m_firstChildState(false)
+    , m_lastChildState(false)
+    , m_childIndex(0)
+{
+    setBitDefaults();
+
+    box.init();
+    visual.init();
+    background.init();
+    surround.init();
+    rareNonInheritedData.init();
+    rareNonInheritedData.access()->flexibleBox.init();
+    rareNonInheritedData.access()->marquee.init();
+    rareNonInheritedData.access()->m_multiCol.init();
+    rareNonInheritedData.access()->m_transform.init();
+    rareInheritedData.init();
+    inherited.init();
+
+#if ENABLE(SVG)
+    m_svgStyle.init();
+#endif
+}
+
+RenderStyle::RenderStyle(const RenderStyle& o)
+    : RefCounted<RenderStyle>()
+    , inherited_flags(o.inherited_flags)
+    , noninherited_flags(o.noninherited_flags)
+    , box(o.box)
+    , visual(o.visual)
+    , background(o.background)
+    , surround(o.surround)
+    , rareNonInheritedData(o.rareNonInheritedData)
+    , rareInheritedData(o.rareInheritedData)
+    , inherited(o.inherited)
+    , m_pseudoState(o.m_pseudoState)
+    , m_affectedByAttributeSelectors(false)
+    , m_unique(false)
+    , m_affectedByEmpty(false)
+    , m_emptyState(false)
+    , m_childrenAffectedByFirstChildRules(false)
+    , m_childrenAffectedByLastChildRules(false)
+    , m_childrenAffectedByDirectAdjacentRules(false)
+    , m_childrenAffectedByForwardPositionalRules(false)
+    , m_childrenAffectedByBackwardPositionalRules(false)
+    , m_firstChildState(false)
+    , m_lastChildState(false)
+    , m_childIndex(0)
+#if ENABLE(SVG)
+    , m_svgStyle(o.m_svgStyle)
+#endif
+{
+}
+
+void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
+{
+    rareInheritedData = inheritParent->rareInheritedData;
+    inherited = inheritParent->inherited;
+    inherited_flags = inheritParent->inherited_flags;
+#if ENABLE(SVG)
+    if (m_svgStyle != inheritParent->m_svgStyle)
+        m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
+#endif
+}
+
+RenderStyle::~RenderStyle()
+{
+}
+
+bool RenderStyle::operator==(const RenderStyle& o) const
+{
+    // compare everything except the pseudoStyle pointer
+    return inherited_flags == o.inherited_flags &&
+            noninherited_flags == o.noninherited_flags &&
+            box == o.box &&
+            visual == o.visual &&
+            background == o.background &&
+            surround == o.surround &&
+            rareNonInheritedData == o.rareNonInheritedData &&
+            rareInheritedData == o.rareInheritedData &&
+            inherited == o.inherited
+#if ENABLE(SVG)
+            && m_svgStyle == o.m_svgStyle
+#endif
+            ;
+}
+
+bool RenderStyle::isStyleAvailable() const
+{
+    return this != CSSStyleSelector::styleNotYetAvailable();
+}
+
+static inline int pseudoBit(RenderStyle::PseudoId pseudo)
+{
+    return 1 << (pseudo - 1);
+}
+
+bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
+{
+    ASSERT(pseudo > NOPSEUDO);
+    ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
+    return pseudoBit(pseudo) & noninherited_flags._pseudoBits;
+}
+
+void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
+{
+    ASSERT(pseudo > NOPSEUDO);
+    ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
+    noninherited_flags._pseudoBits |= pseudoBit(pseudo);
+}
+
+RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid)
+{
+    if (!m_cachedPseudoStyle || styleType() != NOPSEUDO)
+        return 0;
+    RenderStyle* ps = m_cachedPseudoStyle.get();
+    while (ps && ps->styleType() != pid)
+        ps = ps->m_cachedPseudoStyle.get();
+    return ps;
+}
+
+RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
+{
+    if (!pseudo)
+        return 0;
+    pseudo->m_cachedPseudoStyle = m_cachedPseudoStyle;
+    m_cachedPseudoStyle = pseudo;
+    return m_cachedPseudoStyle.get();
+}
+
+bool RenderStyle::inheritedNotEqual(RenderStyle* other) const
+{
+    return inherited_flags != other->inherited_flags ||
+           inherited != other->inherited ||
+#if ENABLE(SVG)
+           m_svgStyle->inheritedNotEqual(other->m_svgStyle.get()) ||
+#endif
+           rareInheritedData != other->rareInheritedData;
+}
+
+bool positionedObjectMoved(const LengthBox& a, const LengthBox& b)
+{
+    // If any unit types are different, then we can't guarantee
+    // that this was just a movement.
+    if (a.left().type() != b.left().type() ||
+        a.right().type() != b.right().type() ||
+        a.top().type() != b.top().type() ||
+        a.bottom().type() != b.bottom().type())
+        return false;
+
+    // Only one unit can be non-auto in the horizontal direction and
+    // in the vertical direction.  Otherwise the adjustment of values
+    // is changing the size of the box.
+    if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
+        return false;
+    if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
+        return false;
+
+    // One of the units is fixed or percent in both directions and stayed
+    // that way in the new style.  Therefore all we are doing is moving.
+    return true;
+}
+
+/*
+  compares two styles. The result gives an idea of the action that
+  needs to be taken when replacing the old style with a new one.
+
+  CbLayout: The containing block of the object needs a relayout.
+  Layout: the RenderObject needs a relayout after the style change
+  Visible: The change is visible, but no relayout is needed
+  NonVisible: The object does need neither repaint nor relayout after
+       the change.
+
+  ### TODO:
+  A lot can be optimised here based on the display type, lots of
+  optimisations are unimplemented, and currently result in the
+  worst case result causing a relayout of the containing block.
+*/
+RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
+{
+#if ENABLE(SVG)
+    // This is horribly inefficient.  Eventually we'll have to integrate
+    // this more directly by calling: Diff svgDiff = svgStyle->diff(other)
+    // and then checking svgDiff and returning from the appropriate places below.
+    if (m_svgStyle != other->m_svgStyle)
+        return Layout;
+#endif
+
+    if (box->width != other->box->width ||
+        box->min_width != other->box->min_width ||
+        box->max_width != other->box->max_width ||
+        box->height != other->box->height ||
+        box->min_height != other->box->min_height ||
+        box->max_height != other->box->max_height)
+        return Layout;
+
+    if (box->vertical_align != other->box->vertical_align || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
+        return Layout;
+
+    if (box->boxSizing != other->box->boxSizing)
+        return Layout;
+
+    if (surround->margin != other->surround->margin)
+        return Layout;
+
+    if (surround->padding != other->surround->padding)
+        return Layout;
+
+    if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
+        if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance ||
+            rareNonInheritedData->marginTopCollapse != other->rareNonInheritedData->marginTopCollapse ||
+            rareNonInheritedData->marginBottomCollapse != other->rareNonInheritedData->marginBottomCollapse ||
+            rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp ||
+            rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
+            return Layout;
+
+        if (rareNonInheritedData->flexibleBox.get() != other->rareNonInheritedData->flexibleBox.get() &&
+            *rareNonInheritedData->flexibleBox.get() != *other->rareNonInheritedData->flexibleBox.get())
+            return Layout;
+
+        if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
+            return Layout;
+
+        if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
+            return Layout;
+
+        if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get() &&
+            *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
+            return Layout;
+
+        if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get() &&
+            *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get())
+            return Layout;
+
+#if ENABLE(DASHBOARD_SUPPORT)
+        // If regions change, trigger a relayout to re-calc regions.
+        if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions)
+            return Layout;
+#endif
+    }
+
+    if (rareInheritedData.get() != other->rareInheritedData.get()) {
+        if (rareInheritedData->highlight != other->rareInheritedData->highlight ||
+            rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust ||
+            rareInheritedData->wordBreak != other->rareInheritedData->wordBreak ||
+            rareInheritedData->wordWrap != other->rareInheritedData->wordWrap ||
+            rareInheritedData->nbspMode != other->rareInheritedData->nbspMode ||
+            rareInheritedData->khtmlLineBreak != other->rareInheritedData->khtmlLineBreak ||
+            rareInheritedData->textSecurity != other->rareInheritedData->textSecurity)
+            return Layout;
+
+        if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
+            return Layout;
+
+        if (textStrokeWidth() != other->textStrokeWidth())
+            return Layout;
+    }
+
+    if (inherited->indent != other->inherited->indent ||
+        inherited->line_height != other->inherited->line_height ||
+        inherited->list_style_image != other->inherited->list_style_image ||
+        inherited->font != other->inherited->font ||
+        inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing ||
+        inherited->vertical_border_spacing != other->inherited->vertical_border_spacing ||
+        inherited_flags._box_direction != other->inherited_flags._box_direction ||
+        inherited_flags._visuallyOrdered != other->inherited_flags._visuallyOrdered ||
+        inherited_flags._htmlHacks != other->inherited_flags._htmlHacks ||
+        noninherited_flags._position != other->noninherited_flags._position ||
+        noninherited_flags._floating != other->noninherited_flags._floating ||
+        noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
+        return Layout;
+
+
+    if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
+        if (inherited_flags._border_collapse != other->inherited_flags._border_collapse ||
+            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;
+
+        // 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;
+    }
+
+    if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
+        if (inherited_flags._list_style_type != other->inherited_flags._list_style_type ||
+            inherited_flags._list_style_position != other->inherited_flags._list_style_position)
+            return Layout;
+    }
+
+    if (inherited_flags._text_align != other->inherited_flags._text_align ||
+        inherited_flags._text_transform != other->inherited_flags._text_transform ||
+        inherited_flags._direction != other->inherited_flags._direction ||
+        inherited_flags._white_space != other->inherited_flags._white_space ||
+        noninherited_flags._clear != other->noninherited_flags._clear)
+        return Layout;
+
+    // Overflow returns a layout hint.
+    if (noninherited_flags._overflowX != other->noninherited_flags._overflowX ||
+        noninherited_flags._overflowY != other->noninherited_flags._overflowY)
+        return Layout;
+
+    // If our border widths change, then we need to layout.  Other changes to borders
+    // only necessitate a repaint.
+    if (borderLeftWidth() != other->borderLeftWidth() ||
+        borderTopWidth() != other->borderTopWidth() ||
+        borderBottomWidth() != other->borderBottomWidth() ||
+        borderRightWidth() != other->borderRightWidth())
+        return Layout;
+
+    // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
+    const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
+    const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
+    if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
+        return Layout;
+    if (visual->counterIncrement != other->visual->counterIncrement ||
+        visual->counterReset != other->visual->counterReset)
+        return Layout;
+
+    if (inherited->m_effectiveZoom != other->inherited->m_effectiveZoom)
+        return Layout;
+
+    // Make sure these left/top/right/bottom checks stay below all layout checks and above
+    // all visible checks.
+    if (position() != StaticPosition) {
+        if (surround->offset != other->surround->offset) {
+             // Optimize for the case where a positioned layer is moving but not changing size.
+            if (position() == AbsolutePosition && positionedObjectMoved(surround->offset, other->surround->offset))
+                return LayoutPositionedMovementOnly;
+
+            // FIXME: We will need to do a bit of work in RenderObject/Box::setStyle before we
+            // can stop doing a layout when relative positioned objects move.  In particular, we'll need
+            // to update scrolling positions and figure out how to do a repaint properly of the updated layer.
+            //if (other->position() == RelativePosition)
+            //    return RepaintLayer;
+            //else
+                return Layout;
+        } else if (box->z_index != other->box->z_index || box->z_auto != other->box->z_auto ||
+                 visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip)
+            return RepaintLayer;
+    }
+
+    if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity ||
+        rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask ||
+        rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
+        return RepaintLayer;
+
+    if (inherited->color != other->inherited->color ||
+        inherited_flags._visibility != other->inherited_flags._visibility ||
+        inherited_flags._text_decorations != other->inherited_flags._text_decorations ||
+        inherited_flags._force_backgrounds_to_white != other->inherited_flags._force_backgrounds_to_white ||
+        surround->border != other->surround->border ||
+        *background.get() != *other->background.get() ||
+        visual->textDecoration != other->visual->textDecoration ||
+        rareInheritedData->userModify != other->rareInheritedData->userModify ||
+        rareInheritedData->userSelect != other->rareInheritedData->userSelect ||
+        rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag ||
+        rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit ||
+        rareInheritedData->textFillColor != other->rareInheritedData->textFillColor ||
+        rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor)
+        return Repaint;
+
+    // Cursors are not checked, since they will be set appropriately in response to mouse events,
+    // so they don't need to cause any repaint or layout.
+
+    // Animations don't need to be checked either.  We always set the new style on the RenderObject, so we will get a chance to fire off
+    // the resulting transition properly.
+    return Equal;
+}
+
+void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
+{
+    StyleVisualData *data = visual.access();
+    data->clip.m_top = top;
+    data->clip.m_right = right;
+    data->clip.m_bottom = bottom;
+    data->clip.m_left = left;
+}
+
+void RenderStyle::addCursor(CachedImage* image, const IntPoint& hotSpot)
+{
+    CursorData data;
+    data.cursorImage = image;
+    data.hotSpot = hotSpot;
+    if (!inherited.access()->cursorData)
+        inherited.access()->cursorData = CursorList::create();
+    inherited.access()->cursorData->append(data);
+}
+
+void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
+{
+    inherited.access()->cursorData = other;
+}
+
+void RenderStyle::clearCursorList()
+{
+    inherited.access()->cursorData = CursorList::create();
+}
+
+bool RenderStyle::contentDataEquivalent(const RenderStyle* otherStyle) const
+{
+    ContentData* c1 = rareNonInheritedData->m_content.get();
+    ContentData* c2 = otherStyle->rareNonInheritedData->m_content.get();
+
+    while (c1 && c2) {
+        if (c1->m_type != c2->m_type)
+            return false;
+
+        switch (c1->m_type) {
+            case CONTENT_NONE:
+                break;
+            case CONTENT_TEXT:
+                if (!equal(c1->m_content.m_text, c2->m_content.m_text))
+                    return false;
+                break;
+            case CONTENT_OBJECT:
+                if (!StyleImage::imagesEquivalent(c1->m_content.m_image, c2->m_content.m_image))
+                    return false;
+                break;
+            case CONTENT_COUNTER:
+                if (*c1->m_content.m_counter != *c2->m_content.m_counter)
+                    return false;
+                break;
+        }
+
+        c1 = c1->m_next;
+        c2 = c2->m_next;
+    }
+
+    return !c1 && !c2;
+}
+
+void RenderStyle::clearContent()
+{
+    if (rareNonInheritedData->m_content)
+        rareNonInheritedData->m_content->clear();
+}
+
+void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
+{
+    if (!image)
+        return; // The object is null. Nothing to do. Just bail.
+
+    OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
+    ContentData* lastContent = content.get();
+    while (lastContent && lastContent->m_next)
+        lastContent = lastContent->m_next;
+
+    bool reuseContent = !add;
+    ContentData* newContentData;
+    if (reuseContent && content) {
+        content->clear();
+        newContentData = content.release();
+    } else
+        newContentData = new ContentData;
+
+    if (lastContent && !reuseContent)
+        lastContent->m_next = newContentData;
+    else
+        content.set(newContentData);
+
+    newContentData->m_content.m_image = image.releaseRef();
+    newContentData->m_type = CONTENT_OBJECT;
+}
+
+void RenderStyle::setContent(StringImpl* s, bool add)
+{
+    if (!s)
+        return; // The string is null. Nothing to do. Just bail.
+
+    OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
+    ContentData* lastContent = content.get();
+    while (lastContent && lastContent->m_next)
+        lastContent = lastContent->m_next;
+
+    bool reuseContent = !add;
+    if (add && lastContent) {
+        if (lastContent->m_type == CONTENT_TEXT) {
+            // We can augment the existing string and share this ContentData node.
+            StringImpl* oldStr = lastContent->m_content.m_text;
+            String newStr = oldStr;
+            newStr.append(s);
+            newStr.impl()->ref();
+            oldStr->deref();
+            lastContent->m_content.m_text = newStr.impl();
+            return;
+        }
+    }
+
+    ContentData* newContentData = 0;
+    if (reuseContent && content) {
+        content->clear();
+        newContentData = content.release();
+    } else
+        newContentData = new ContentData;
+
+    if (lastContent && !reuseContent)
+        lastContent->m_next = newContentData;
+    else
+        content.set(newContentData);
+
+    newContentData->m_content.m_text = s;
+    newContentData->m_content.m_text->ref();
+    newContentData->m_type = CONTENT_TEXT;
+}
+
+void RenderStyle::setContent(CounterContent* c, bool add)
+{
+    if (!c)
+        return;
+
+    OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
+    ContentData* lastContent = content.get();
+    while (lastContent && lastContent->m_next)
+        lastContent = lastContent->m_next;
+
+    bool reuseContent = !add;
+    ContentData* newContentData = 0;
+    if (reuseContent && content) {
+        content->clear();
+        newContentData = content.release();
+    } else
+        newContentData = new ContentData;
+
+    if (lastContent && !reuseContent)
+        lastContent->m_next = newContentData;
+    else
+        content.set(newContentData);
+
+    newContentData->m_content.m_counter = c;
+    newContentData->m_type = CONTENT_COUNTER;
+}
+
+void RenderStyle::applyTransform(AffineTransform& transform, const IntSize& borderBoxSize, bool includeTransformOrigin) const
+{
+    // transform-origin brackets the transform with translate operations.
+    // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
+    // in that case.
+    bool applyTransformOrigin = false;
+    unsigned s = rareNonInheritedData->m_transform->m_operations.operations().size();
+    unsigned i;
+    if (includeTransformOrigin) {
+        for (i = 0; i < s; i++) {
+            TransformOperation::OperationType type = rareNonInheritedData->m_transform->m_operations.operations()[i]->getOperationType();
+            if (type != TransformOperation::TRANSLATE_X &&
+                    type != TransformOperation::TRANSLATE_Y &&
+                    type != TransformOperation::TRANSLATE) {
+                applyTransformOrigin = true;
+                break;
+            }
+        }
+    }
+
+    if (applyTransformOrigin)
+        transform.translate(transformOriginX().calcFloatValue(borderBoxSize.width()), transformOriginY().calcFloatValue(borderBoxSize.height()));
+
+    for (i = 0; i < s; i++)
+        rareNonInheritedData->m_transform->m_operations.operations()[i]->apply(transform, borderBoxSize);
+
+    if (applyTransformOrigin)
+        transform.translate(-transformOriginX().calcFloatValue(borderBoxSize.width()), -transformOriginY().calcFloatValue(borderBoxSize.height()));
+}
+
+#if ENABLE(XBL)
+void RenderStyle::addBindingURI(StringImpl* uri)
+{
+    BindingURI* binding = new BindingURI(uri);
+    if (!bindingURIs())
+        SET_VAR(rareNonInheritedData, bindingURI, binding)
+    else
+        for (BindingURI* b = bindingURIs(); b; b = b->next()) {
+            if (!b->next())
+                b->setNext(binding);
+        }
+}
+#endif
+
+void RenderStyle::setTextShadow(ShadowData* val, bool add)
+{
+    StyleRareInheritedData* rareData = rareInheritedData.access();
+    if (!add) {
+        delete rareData->textShadow;
+        rareData->textShadow = val;
+        return;
+    }
+
+    val->next = rareData->textShadow;
+    rareData->textShadow = val;
+}
+
+void RenderStyle::setBoxShadow(ShadowData* shadowData, bool add)
+{
+    StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
+    if (!add) {
+        rareData->m_boxShadow.set(shadowData);
+        return;
+    }
+
+    shadowData->next = rareData->m_boxShadow.release();
+    rareData->m_boxShadow.set(shadowData);
+}
+
+const CounterDirectiveMap* RenderStyle::counterDirectives() const
+{
+    return rareNonInheritedData->m_counterDirectives.get();
+}
+
+CounterDirectiveMap& RenderStyle::accessCounterDirectives()
+{
+    OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives;
+    if (!map)
+        map.set(new CounterDirectiveMap);
+    return *map.get();
+}
+
+#if ENABLE(DASHBOARD_SUPPORT)
+const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
+{
+    static Vector<StyleDashboardRegion> emptyList;
+    return emptyList;
+}
+
+const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
+{
+    static Vector<StyleDashboardRegion> noneList;
+    static bool noneListInitialized = false;
+
+    if (!noneListInitialized) {
+        StyleDashboardRegion region;
+        region.label = "";
+        region.offset.m_top  = Length();
+        region.offset.m_right = Length();
+        region.offset.m_bottom = Length();
+        region.offset.m_left = Length();
+        region.type = StyleDashboardRegion::None;
+        noneList.append(region);
+        noneListInitialized = true;
+    }
+    return noneList;
+}
+#endif
+
+void RenderStyle::adjustAnimations()
+{
+    AnimationList* animationList = rareNonInheritedData->m_animations.get();
+    if (!animationList)
+        return;
+
+    // get rid of empty transitions and anything beyond them
+    for (size_t i = 0; i < animationList->size(); ++i) {
+        if (animationList->animation(i)->isEmpty()) {
+            animationList->resize(i);
+            break;
+        }
+    }
+
+    if (animationList->isEmpty()) {
+        clearAnimations();
+        return;
+    }
+
+    // Repeat patterns into layers that don't have some properties set.
+    animationList->fillUnsetProperties();
+}
+
+void RenderStyle::adjustTransitions()
+{
+    AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
+    if (!transitionList)
+        return;
+
+    // get rid of empty transitions and anything beyond them
+    for (size_t i = 0; i < transitionList->size(); ++i) {
+        if (transitionList->animation(i)->isEmpty()) {
+            transitionList->resize(i);
+            break;
+        }
+    }
+
+    if (transitionList->isEmpty()) {
+        clearTransitions();
+        return;
+    }
+
+    // Repeat patterns into layers that don't have some properties set.
+    transitionList->fillUnsetProperties();
+
+    // Make sure there are no duplicate properties. This is an O(n^2) algorithm
+    // but the lists tend to be very short, so it is probably ok
+    for (size_t i = 0; i < transitionList->size(); ++i) {
+        for (size_t j = i+1; j < transitionList->size(); ++j) {
+            if (transitionList->animation(i)->property() == transitionList->animation(j)->property()) {
+                // toss i
+                transitionList->remove(i);
+                j = i;
+            }
+        }
+    }
+}
+
+AnimationList* RenderStyle::accessAnimations()
+{
+    if (!rareNonInheritedData.access()->m_animations)
+        rareNonInheritedData.access()->m_animations.set(new AnimationList());
+    return rareNonInheritedData->m_animations.get();
+}
+
+AnimationList* RenderStyle::accessTransitions()
+{
+    if (!rareNonInheritedData.access()->m_transitions)
+        rareNonInheritedData.access()->m_transitions.set(new AnimationList());
+    return rareNonInheritedData->m_transitions.get();
+}
+
+const Animation* RenderStyle::transitionForProperty(int property)
+{
+    if (transitions()) {
+        for (size_t i = 0; i < transitions()->size(); ++i) {
+            const Animation* p = transitions()->animation(i);
+            if (p->property() == cAnimateAll || p->property() == property) {
+                return p;
+            }
+        }
+    }
+    return 0;
+}
+
+void RenderStyle::setBlendedFontSize(int size)
+{
+    FontDescription desc(fontDescription());
+    desc.setSpecifiedSize(size);
+    desc.setComputedSize(size);
+    setFontDescription(desc);
+    font().update(font().fontSelector());
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h
new file mode 100644
index 0000000..084bdc8
--- /dev/null
+++ b/WebCore/rendering/style/RenderStyle.h
@@ -0,0 +1,1138 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderStyle_h
+#define RenderStyle_h
+
+#include "AffineTransform.h"
+#include "AnimationList.h"
+#include "BorderData.h"
+#include "BorderValue.h"
+#include "CSSHelper.h"
+#include "CSSImageGeneratorValue.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSReflectionDirection.h"
+#include "CSSValueList.h"
+#include "CachedImage.h"
+#include "CollapsedBorderValue.h"
+#include "Color.h"
+#include "ContentData.h"
+#include "CounterDirectives.h"
+#include "CursorList.h"
+#include "DataRef.h"
+#include "FillLayer.h"
+#include "FloatPoint.h"
+#include "Font.h"
+#include "GraphicsTypes.h"
+#include "IntRect.h"
+#include "Length.h"
+#include "LengthBox.h"
+#include "LengthSize.h"
+#include "NinePieceImage.h"
+#include "OutlineValue.h"
+#include "Pair.h"
+#include "RenderStyleConstants.h"
+#include "ShadowData.h"
+#include "StyleBackgroundData.h"
+#include "StyleBoxData.h"
+#include "StyleFlexibleBoxData.h"
+#include "StyleInheritedData.h"
+#include "StyleMarqueeData.h"
+#include "StyleMultiColData.h"
+#include "StyleRareInheritedData.h"
+#include "StyleRareNonInheritedData.h"
+#include "StyleReflection.h"
+#include "StyleSurroundData.h"
+#include "StyleTransformData.h"
+#include "StyleVisualData.h"
+#include "TextDirection.h"
+#include "ThemeTypes.h"
+#include "TimingFunction.h"
+#include "TransformOperations.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+#if ENABLE(DASHBOARD_SUPPORT)
+#include "StyleDashboardRegion.h"
+#endif
+
+#if ENABLE(SVG)
+#include "SVGRenderStyle.h"
+#endif
+
+#if ENABLE(XBL)
+#include "BindingURI.h"
+#endif
+
+template<typename T, typename U> inline bool compareEqual(const T& t, const U& u) { return t == static_cast<T>(u); }
+
+#define SET_VAR(group, variable, value) \
+    if (!compareEqual(group->variable, value)) \
+        group.access()->variable = value;
+
+namespace WebCore {
+
+using std::max;
+
+class CSSStyleSelector;
+class CSSValueList;
+class CachedImage;
+class Pair;
+class StringImpl;
+class StyleImage;
+
+class RenderStyle: public RefCounted<RenderStyle> {
+    friend class CSSStyleSelector;
+
+public:
+    // static pseudo styles. Dynamic ones are produced on the fly.
+    enum PseudoId { NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR, FILE_UPLOAD_BUTTON, INPUT_PLACEHOLDER,
+                    SLIDER_THUMB, SEARCH_CANCEL_BUTTON, SEARCH_DECORATION, SEARCH_RESULTS_DECORATION, SEARCH_RESULTS_BUTTON, MEDIA_CONTROLS_PANEL,
+                    MEDIA_CONTROLS_PLAY_BUTTON, MEDIA_CONTROLS_MUTE_BUTTON, MEDIA_CONTROLS_TIMELINE, MEDIA_CONTROLS_TIME_DISPLAY,
+                    MEDIA_CONTROLS_SEEK_BACK_BUTTON, MEDIA_CONTROLS_SEEK_FORWARD_BUTTON , MEDIA_CONTROLS_FULLSCREEN_BUTTON,
+                    SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER };
+    static const int FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON;
+
+protected:
+
+// !START SYNC!: Keep this in sync with the copy constructor in RenderStyle.cpp
+
+    // inherit
+    struct InheritedFlags {
+        bool operator==(const InheritedFlags& other) const
+        {
+            return (_empty_cells == other._empty_cells) &&
+                   (_caption_side == other._caption_side) &&
+                   (_list_style_type == other._list_style_type) &&
+                   (_list_style_position == other._list_style_position) &&
+                   (_visibility == other._visibility) &&
+                   (_text_align == other._text_align) &&
+                   (_text_transform == other._text_transform) &&
+                   (_text_decorations == other._text_decorations) &&
+                   (_text_transform == other._text_transform) &&
+                   (_cursor_style == other._cursor_style) &&
+                   (_direction == other._direction) &&
+                   (_border_collapse == other._border_collapse) &&
+                   (_white_space == other._white_space) &&
+                   (_box_direction == other._box_direction) &&
+                   (_visuallyOrdered == other._visuallyOrdered) &&
+                   (_htmlHacks == other._htmlHacks) &&
+                   (_force_backgrounds_to_white == other._force_backgrounds_to_white);
+        }
+
+        bool operator!=(const InheritedFlags& other) const { return !(*this == other); }
+
+        unsigned _empty_cells : 1; // EEmptyCell
+        unsigned _caption_side : 2; // ECaptionSide
+        unsigned _list_style_type : 5 ; // EListStyleType
+        unsigned _list_style_position : 1; // EListStylePosition
+        unsigned _visibility : 2; // EVisibility
+        unsigned _text_align : 3; // ETextAlign
+        unsigned _text_transform : 2; // ETextTransform
+        unsigned _text_decorations : 4;
+        unsigned _cursor_style : 6; // ECursor
+        unsigned _direction : 1; // TextDirection
+        bool _border_collapse : 1 ;
+        unsigned _white_space : 3; // EWhiteSpace
+        unsigned _box_direction : 1; // EBoxDirection (CSS3 box_direction property, flexible box layout module)
+
+        // non CSS2 inherited
+        bool _visuallyOrdered : 1;
+        bool _htmlHacks :1;
+        bool _force_backgrounds_to_white : 1;
+    } inherited_flags;
+
+// don't inherit
+    struct NonInheritedFlags {
+        bool operator==(const NonInheritedFlags& other) const
+        {
+            return (_effectiveDisplay == other._effectiveDisplay) &&
+            (_originalDisplay == other._originalDisplay) &&
+            (_overflowX == other._overflowX) &&
+            (_overflowY == other._overflowY) &&
+            (_vertical_align == other._vertical_align) &&
+            (_clear == other._clear) &&
+            (_position == other._position) &&
+            (_floating == other._floating) &&
+            (_table_layout == other._table_layout) &&
+            (_page_break_before == other._page_break_before) &&
+            (_page_break_after == other._page_break_after) &&
+            (_styleType == other._styleType) &&
+            (_affectedByHover == other._affectedByHover) &&
+            (_affectedByActive == other._affectedByActive) &&
+            (_affectedByDrag == other._affectedByDrag) &&
+            (_pseudoBits == other._pseudoBits) &&
+            (_unicodeBidi == other._unicodeBidi);
+        }
+
+        bool operator!=(const NonInheritedFlags& other) const { return !(*this == other); }
+
+        unsigned _effectiveDisplay : 5; // EDisplay
+        unsigned _originalDisplay : 5; // EDisplay
+        unsigned _overflowX : 3; // EOverflow
+        unsigned _overflowY : 3; // EOverflow
+        unsigned _vertical_align : 4; // EVerticalAlign
+        unsigned _clear : 2; // EClear
+        unsigned _position : 2; // EPosition
+        unsigned _floating : 2; // EFloat
+        unsigned _table_layout : 1; // ETableLayout
+
+        unsigned _page_break_before : 2; // EPageBreak
+        unsigned _page_break_after : 2; // EPageBreak
+
+        unsigned _styleType : 5; // PseudoId
+        bool _affectedByHover : 1;
+        bool _affectedByActive : 1;
+        bool _affectedByDrag : 1;
+        unsigned _pseudoBits : 7;
+        unsigned _unicodeBidi : 2; // EUnicodeBidi
+    } noninherited_flags;
+
+    // non-inherited attributes
+    DataRef<StyleBoxData> box;
+    DataRef<StyleVisualData> visual;
+    DataRef<StyleBackgroundData> background;
+    DataRef<StyleSurroundData> surround;
+    DataRef<StyleRareNonInheritedData> rareNonInheritedData;
+
+    // inherited attributes
+    DataRef<StyleRareInheritedData> rareInheritedData;
+    DataRef<StyleInheritedData> inherited;
+
+    // list of associated pseudo styles
+    RefPtr<RenderStyle> m_cachedPseudoStyle;
+
+    unsigned m_pseudoState : 3; // PseudoState
+    bool m_affectedByAttributeSelectors : 1;
+    bool m_unique : 1;
+
+    // Bits for dynamic child matching.
+    bool m_affectedByEmpty : 1;
+    bool m_emptyState : 1;
+
+    // We optimize for :first-child and :last-child.  The other positional child selectors like nth-child or
+    // *-child-of-type, we will just give up and re-evaluate whenever children change at all.
+    bool m_childrenAffectedByFirstChildRules : 1;
+    bool m_childrenAffectedByLastChildRules : 1;
+    bool m_childrenAffectedByDirectAdjacentRules : 1;
+    bool m_childrenAffectedByForwardPositionalRules : 1;
+    bool m_childrenAffectedByBackwardPositionalRules : 1;
+    bool m_firstChildState : 1;
+    bool m_lastChildState : 1;
+    unsigned m_childIndex : 18; // Plenty of bits to cache an index.
+
+#if ENABLE(SVG)
+    DataRef<SVGRenderStyle> m_svgStyle;
+#endif
+
+// !END SYNC!
+
+protected:
+    void setBitDefaults()
+    {
+        inherited_flags._empty_cells = initialEmptyCells();
+        inherited_flags._caption_side = initialCaptionSide();
+        inherited_flags._list_style_type = initialListStyleType();
+        inherited_flags._list_style_position = initialListStylePosition();
+        inherited_flags._visibility = initialVisibility();
+        inherited_flags._text_align = initialTextAlign();
+        inherited_flags._text_transform = initialTextTransform();
+        inherited_flags._text_decorations = initialTextDecoration();
+        inherited_flags._cursor_style = initialCursor();
+        inherited_flags._direction = initialDirection();
+        inherited_flags._border_collapse = initialBorderCollapse();
+        inherited_flags._white_space = initialWhiteSpace();
+        inherited_flags._visuallyOrdered = initialVisuallyOrdered();
+        inherited_flags._htmlHacks=false;
+        inherited_flags._box_direction = initialBoxDirection();
+        inherited_flags._force_backgrounds_to_white = false;
+
+        noninherited_flags._effectiveDisplay = noninherited_flags._originalDisplay = initialDisplay();
+        noninherited_flags._overflowX = initialOverflowX();
+        noninherited_flags._overflowY = initialOverflowY();
+        noninherited_flags._vertical_align = initialVerticalAlign();
+        noninherited_flags._clear = initialClear();
+        noninherited_flags._position = initialPosition();
+        noninherited_flags._floating = initialFloating();
+        noninherited_flags._table_layout = initialTableLayout();
+        noninherited_flags._page_break_before = initialPageBreak();
+        noninherited_flags._page_break_after = initialPageBreak();
+        noninherited_flags._styleType = NOPSEUDO;
+        noninherited_flags._affectedByHover = false;
+        noninherited_flags._affectedByActive = false;
+        noninherited_flags._affectedByDrag = false;
+        noninherited_flags._pseudoBits = 0;
+        noninherited_flags._unicodeBidi = initialUnicodeBidi();
+    }
+
+protected:
+    RenderStyle();
+    // used to create the default style.
+    RenderStyle(bool);
+    RenderStyle(const RenderStyle&);
+
+public:
+    static PassRefPtr<RenderStyle> create();
+    static PassRefPtr<RenderStyle> createDefaultStyle();
+    static PassRefPtr<RenderStyle> clone(const RenderStyle*);
+
+    ~RenderStyle();
+
+    void inheritFrom(const RenderStyle* inheritParent);
+
+    PseudoId styleType() { return static_cast<PseudoId>(noninherited_flags._styleType); }
+    void setStyleType(PseudoId styleType) { noninherited_flags._styleType = styleType; }
+
+    RenderStyle* getCachedPseudoStyle(PseudoId);
+    RenderStyle* addCachedPseudoStyle(PassRefPtr<RenderStyle>);
+
+    bool affectedByHoverRules() const { return noninherited_flags._affectedByHover; }
+    bool affectedByActiveRules() const { return noninherited_flags._affectedByActive; }
+    bool affectedByDragRules() const { return noninherited_flags._affectedByDrag; }
+
+    void setAffectedByHoverRules(bool b) { noninherited_flags._affectedByHover = b; }
+    void setAffectedByActiveRules(bool b) { noninherited_flags._affectedByActive = b; }
+    void setAffectedByDragRules(bool b) { noninherited_flags._affectedByDrag = b; }
+
+    bool operator==(const RenderStyle& other) const;
+    bool operator!=(const RenderStyle& other) const { return !(*this == other); }
+    bool isFloating() const { return !(noninherited_flags._floating == FNONE); }
+    bool hasMargin() const { return surround->margin.nonZero(); }
+    bool hasBorder() const { return surround->border.hasBorder(); }
+    bool hasPadding() const { return surround->padding.nonZero(); }
+    bool hasOffset() const { return surround->offset.nonZero(); }
+
+    bool hasBackground() const
+    {
+        if (backgroundColor().isValid() && backgroundColor().alpha() > 0)
+            return true;
+        return background->m_background.hasImage();
+    }
+    bool hasFixedBackgroundImage() const { return background->m_background.hasFixedImage(); }
+    bool hasAppearance() const { return appearance() != NoControlPart; }
+
+    bool visuallyOrdered() const { return inherited_flags._visuallyOrdered; }
+    void setVisuallyOrdered(bool b) { inherited_flags._visuallyOrdered = b; }
+
+    bool isStyleAvailable() const;
+
+    bool hasPseudoStyle(PseudoId pseudo) const;
+    void setHasPseudoStyle(PseudoId pseudo);
+
+    // attribute getter methods
+
+    EDisplay display() const { return static_cast<EDisplay>(noninherited_flags._effectiveDisplay); }
+    EDisplay originalDisplay() const { return static_cast<EDisplay>(noninherited_flags._originalDisplay); }
+
+    Length left() const { return surround->offset.left(); }
+    Length right() const { return surround->offset.right(); }
+    Length top() const { return surround->offset.top(); }
+    Length bottom() const { return surround->offset.bottom(); }
+
+    EPosition position() const { return static_cast<EPosition>(noninherited_flags._position); }
+    EFloat floating() const { return static_cast<EFloat>(noninherited_flags._floating); }
+
+    Length width() const { return box->width; }
+    Length height() const { return box->height; }
+    Length minWidth() const { return box->min_width; }
+    Length maxWidth() const { return box->max_width; }
+    Length minHeight() const { return box->min_height; }
+    Length maxHeight() const { return box->max_height; }
+
+    const BorderData& border() const { return surround->border; }
+    const BorderValue& borderLeft() const { return surround->border.left; }
+    const BorderValue& borderRight() const { return surround->border.right; }
+    const BorderValue& borderTop() const { return surround->border.top; }
+    const BorderValue& borderBottom() const { return surround->border.bottom; }
+
+    const NinePieceImage& borderImage() const { return surround->border.image; }
+
+    const IntSize& borderTopLeftRadius() const { return surround->border.topLeft; }
+    const IntSize& borderTopRightRadius() const { return surround->border.topRight; }
+    const IntSize& borderBottomLeftRadius() const { return surround->border.bottomLeft; }
+    const IntSize& borderBottomRightRadius() const { return surround->border.bottomRight; }
+    bool hasBorderRadius() const { return surround->border.hasBorderRadius(); }
+
+    unsigned short borderLeftWidth() const { return surround->border.borderLeftWidth(); }
+    EBorderStyle borderLeftStyle() const { return surround->border.left.style(); }
+    const Color& borderLeftColor() const { return surround->border.left.color; }
+    bool borderLeftIsTransparent() const { return surround->border.left.isTransparent(); }
+    unsigned short borderRightWidth() const { return surround->border.borderRightWidth(); }
+    EBorderStyle borderRightStyle() const { return surround->border.right.style(); }
+    const Color& borderRightColor() const { return surround->border.right.color; }
+    bool borderRightIsTransparent() const { return surround->border.right.isTransparent(); }
+    unsigned short borderTopWidth() const { return surround->border.borderTopWidth(); }
+    EBorderStyle borderTopStyle() const { return surround->border.top.style(); }
+    const Color& borderTopColor() const { return surround->border.top.color; }
+    bool borderTopIsTransparent() const { return surround->border.top.isTransparent(); }
+    unsigned short borderBottomWidth() const { return surround->border.borderBottomWidth(); }
+    EBorderStyle borderBottomStyle() const { return surround->border.bottom.style(); }
+    const Color& borderBottomColor() const { return surround->border.bottom.color; }
+    bool borderBottomIsTransparent() const { return surround->border.bottom.isTransparent(); }
+
+    unsigned short outlineSize() const { return max(0, outlineWidth() + outlineOffset()); }
+    unsigned short outlineWidth() const
+    {
+        if (background->m_outline.style() == BNONE)
+            return 0;
+        return background->m_outline.width;
+    }
+    bool hasOutline() const { return outlineWidth() > 0 && outlineStyle() > BHIDDEN; }
+    EBorderStyle outlineStyle() const { return background->m_outline.style(); }
+    bool outlineStyleIsAuto() const { return background->m_outline._auto; }
+    const Color& outlineColor() const { return background->m_outline.color; }
+
+    EOverflow overflowX() const { return static_cast<EOverflow>(noninherited_flags._overflowX); }
+    EOverflow overflowY() const { return static_cast<EOverflow>(noninherited_flags._overflowY); }
+
+    EVisibility visibility() const { return static_cast<EVisibility>(inherited_flags._visibility); }
+    EVerticalAlign verticalAlign() const { return static_cast<EVerticalAlign>(noninherited_flags._vertical_align); }
+    Length verticalAlignLength() const { return box->vertical_align; }
+
+    Length clipLeft() const { return visual->clip.left(); }
+    Length clipRight() const { return visual->clip.right(); }
+    Length clipTop() const { return visual->clip.top(); }
+    Length clipBottom() const { return visual->clip.bottom(); }
+    LengthBox clip() const { return visual->clip; }
+    bool hasClip() const { return visual->hasClip; }
+
+    EUnicodeBidi unicodeBidi() const { return static_cast<EUnicodeBidi>(noninherited_flags._unicodeBidi); }
+
+    EClear clear() const { return static_cast<EClear>(noninherited_flags._clear); }
+    ETableLayout tableLayout() const { return static_cast<ETableLayout>(noninherited_flags._table_layout); }
+
+    const Font& font() const { return inherited->font; }
+    const FontDescription& fontDescription() const { return inherited->font.fontDescription(); }
+    int fontSize() const { return inherited->font.pixelSize(); }
+
+    const Color& color() const { return inherited->color; }
+    Length textIndent() const { return inherited->indent; }
+    ETextAlign textAlign() const { return static_cast<ETextAlign>(inherited_flags._text_align); }
+    ETextTransform textTransform() const { return static_cast<ETextTransform>(inherited_flags._text_transform); }
+    int textDecorationsInEffect() const { return inherited_flags._text_decorations; }
+    int textDecoration() const { return visual->textDecoration; }
+    int wordSpacing() const { return inherited->font.wordSpacing(); }
+    int letterSpacing() const { return inherited->font.letterSpacing(); }
+
+    float zoom() const { return visual->m_zoom; }
+    float effectiveZoom() const { return inherited->m_effectiveZoom; }
+
+    TextDirection direction() const { return static_cast<TextDirection>(inherited_flags._direction); }
+    Length lineHeight() const { return inherited->line_height; }
+
+    EWhiteSpace whiteSpace() const { return static_cast<EWhiteSpace>(inherited_flags._white_space); }
+    static bool autoWrap(EWhiteSpace ws)
+    {
+        // Nowrap and pre don't automatically wrap.
+        return ws != NOWRAP && ws != PRE;
+    }
+
+    bool autoWrap() const
+    {
+        return autoWrap(whiteSpace());
+    }
+
+    static bool preserveNewline(EWhiteSpace ws)
+    {
+        // Normal and nowrap do not preserve newlines.
+        return ws != NORMAL && ws != NOWRAP;
+    }
+
+    bool preserveNewline() const
+    {
+        return preserveNewline(whiteSpace());
+    }
+
+    static bool collapseWhiteSpace(EWhiteSpace ws)
+    {
+        // Pre and prewrap do not collapse whitespace.
+        return ws != PRE && ws != PRE_WRAP;
+    }
+
+    bool collapseWhiteSpace() const
+    {
+        return collapseWhiteSpace(whiteSpace());
+    }
+
+    bool isCollapsibleWhiteSpace(UChar c) const
+    {
+        switch (c) {
+            case ' ':
+            case '\t':
+                return collapseWhiteSpace();
+            case '\n':
+                return !preserveNewline();
+        }
+        return false;
+    }
+
+    bool breakOnlyAfterWhiteSpace() const
+    {
+        return whiteSpace() == PRE_WRAP || khtmlLineBreak() == AFTER_WHITE_SPACE;
+    }
+
+    bool breakWords() const
+    {
+        return wordBreak() == BreakWordBreak || wordWrap() == BreakWordWrap;
+    }
+
+    const Color& backgroundColor() const { return background->m_color; }
+    StyleImage* backgroundImage() const { return background->m_background.m_image.get(); }
+    EFillRepeat backgroundRepeat() const { return static_cast<EFillRepeat>(background->m_background.m_repeat); }
+    CompositeOperator backgroundComposite() const { return static_cast<CompositeOperator>(background->m_background.m_composite); }
+    bool backgroundAttachment() const { return background->m_background.m_attachment; }
+    EFillBox backgroundClip() const { return static_cast<EFillBox>(background->m_background.m_clip); }
+    EFillBox backgroundOrigin() const { return static_cast<EFillBox>(background->m_background.m_origin); }
+    Length backgroundXPosition() const { return background->m_background.m_xPosition; }
+    Length backgroundYPosition() const { return background->m_background.m_yPosition; }
+    LengthSize backgroundSize() const { return background->m_background.m_size; }
+    FillLayer* accessBackgroundLayers() { return &(background.access()->m_background); }
+    const FillLayer* backgroundLayers() const { return &(background->m_background); }
+
+    StyleImage* maskImage() const { return rareNonInheritedData->m_mask.m_image.get(); }
+    EFillRepeat maskRepeat() const { return static_cast<EFillRepeat>(rareNonInheritedData->m_mask.m_repeat); }
+    CompositeOperator maskComposite() const { return static_cast<CompositeOperator>(rareNonInheritedData->m_mask.m_composite); }
+    bool maskAttachment() const { return rareNonInheritedData->m_mask.m_attachment; }
+    EFillBox maskClip() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.m_clip); }
+    EFillBox maskOrigin() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.m_origin); }
+    Length maskXPosition() const { return rareNonInheritedData->m_mask.m_xPosition; }
+    Length maskYPosition() const { return rareNonInheritedData->m_mask.m_yPosition; }
+    LengthSize maskSize() const { return rareNonInheritedData->m_mask.m_size; }
+    FillLayer* accessMaskLayers() { return &(rareNonInheritedData.access()->m_mask); }
+    const FillLayer* maskLayers() const { return &(rareNonInheritedData->m_mask); }
+    const NinePieceImage& maskBoxImage() const { return rareNonInheritedData->m_maskBoxImage; }
+
+    // returns true for collapsing borders, false for separate borders
+    bool borderCollapse() const { return inherited_flags._border_collapse; }
+    short horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; }
+    short verticalBorderSpacing() const { return inherited->vertical_border_spacing; }
+    EEmptyCell emptyCells() const { return static_cast<EEmptyCell>(inherited_flags._empty_cells); }
+    ECaptionSide captionSide() const { return static_cast<ECaptionSide>(inherited_flags._caption_side); }
+
+    short counterIncrement() const { return visual->counterIncrement; }
+    short counterReset() const { return visual->counterReset; }
+
+    EListStyleType listStyleType() const { return static_cast<EListStyleType>(inherited_flags._list_style_type); }
+    StyleImage* listStyleImage() const { return inherited->list_style_image.get(); }
+    EListStylePosition listStylePosition() const { return static_cast<EListStylePosition>(inherited_flags._list_style_position); }
+
+    Length marginTop() const { return surround->margin.top(); }
+    Length marginBottom() const { return surround->margin.bottom(); }
+    Length marginLeft() const { return surround->margin.left(); }
+    Length marginRight() const { return surround->margin.right(); }
+
+    LengthBox paddingBox() const { return surround->padding; }
+    Length paddingTop() const { return surround->padding.top(); }
+    Length paddingBottom() const { return surround->padding.bottom(); }
+    Length paddingLeft() const { return surround->padding.left(); }
+    Length paddingRight() const { return surround->padding.right(); }
+
+    ECursor cursor() const { return static_cast<ECursor>(inherited_flags._cursor_style); }
+
+    CursorList* cursors() const { return inherited->cursorData.get(); }
+
+    short widows() const { return inherited->widows; }
+    short orphans() const { return inherited->orphans; }
+    EPageBreak pageBreakInside() const { return static_cast<EPageBreak>(inherited->page_break_inside); }
+    EPageBreak pageBreakBefore() const { return static_cast<EPageBreak>(noninherited_flags._page_break_before); }
+    EPageBreak pageBreakAfter() const { return static_cast<EPageBreak>(noninherited_flags._page_break_after); }
+
+    // CSS3 Getter Methods
+#if ENABLE(XBL)
+    BindingURI* bindingURIs() const { return rareNonInheritedData->bindingURI; }
+#endif
+
+    int outlineOffset() const
+    {
+        if (background->m_outline.style() == BNONE)
+            return 0;
+        return background->m_outline._offset;
+    }
+
+    ShadowData* textShadow() const { return rareInheritedData->textShadow; }
+    const Color& textStrokeColor() const { return rareInheritedData->textStrokeColor; }
+    float textStrokeWidth() const { return rareInheritedData->textStrokeWidth; }
+    const Color& textFillColor() const { return rareInheritedData->textFillColor; }
+    float opacity() const { return rareNonInheritedData->opacity; }
+    ControlPart appearance() const { return static_cast<ControlPart>(rareNonInheritedData->m_appearance); }
+    EBoxAlignment boxAlign() const { return static_cast<EBoxAlignment>(rareNonInheritedData->flexibleBox->align); }
+    EBoxDirection boxDirection() const { return static_cast<EBoxDirection>(inherited_flags._box_direction); }
+    float boxFlex() { return rareNonInheritedData->flexibleBox->flex; }
+    unsigned int boxFlexGroup() const { return rareNonInheritedData->flexibleBox->flex_group; }
+    EBoxLines boxLines() { return static_cast<EBoxLines>(rareNonInheritedData->flexibleBox->lines); }
+    unsigned int boxOrdinalGroup() const { return rareNonInheritedData->flexibleBox->ordinal_group; }
+    EBoxOrient boxOrient() const { return static_cast<EBoxOrient>(rareNonInheritedData->flexibleBox->orient); }
+    EBoxAlignment boxPack() const { return static_cast<EBoxAlignment>(rareNonInheritedData->flexibleBox->pack); }
+    ShadowData* boxShadow() const { return rareNonInheritedData->m_boxShadow.get(); }
+    StyleReflection* boxReflect() const { return rareNonInheritedData->m_boxReflect.get(); }
+    EBoxSizing boxSizing() const { return static_cast<EBoxSizing>(box->boxSizing); }
+    Length marqueeIncrement() const { return rareNonInheritedData->marquee->increment; }
+    int marqueeSpeed() const { return rareNonInheritedData->marquee->speed; }
+    int marqueeLoopCount() const { return rareNonInheritedData->marquee->loops; }
+    EMarqueeBehavior marqueeBehavior() const { return static_cast<EMarqueeBehavior>(rareNonInheritedData->marquee->behavior); }
+    EMarqueeDirection marqueeDirection() const { return static_cast<EMarqueeDirection>(rareNonInheritedData->marquee->direction); }
+    EUserModify userModify() const { return static_cast<EUserModify>(rareInheritedData->userModify); }
+    EUserDrag userDrag() const { return static_cast<EUserDrag>(rareNonInheritedData->userDrag); }
+    EUserSelect userSelect() const { return static_cast<EUserSelect>(rareInheritedData->userSelect); }
+    bool textOverflow() const { return rareNonInheritedData->textOverflow; }
+    EMarginCollapse marginTopCollapse() const { return static_cast<EMarginCollapse>(rareNonInheritedData->marginTopCollapse); }
+    EMarginCollapse marginBottomCollapse() const { return static_cast<EMarginCollapse>(rareNonInheritedData->marginBottomCollapse); }
+    EWordBreak wordBreak() const { return static_cast<EWordBreak>(rareInheritedData->wordBreak); }
+    EWordWrap wordWrap() const { return static_cast<EWordWrap>(rareInheritedData->wordWrap); }
+    ENBSPMode nbspMode() const { return static_cast<ENBSPMode>(rareInheritedData->nbspMode); }
+    EKHTMLLineBreak khtmlLineBreak() const { return static_cast<EKHTMLLineBreak>(rareInheritedData->khtmlLineBreak); }
+    EMatchNearestMailBlockquoteColor matchNearestMailBlockquoteColor() const { return static_cast<EMatchNearestMailBlockquoteColor>(rareNonInheritedData->matchNearestMailBlockquoteColor); }
+    const AtomicString& highlight() const { return rareInheritedData->highlight; }
+    EBorderFit borderFit() const { return static_cast<EBorderFit>(rareNonInheritedData->m_borderFit); }
+    EResize resize() const { return static_cast<EResize>(rareInheritedData->resize); }
+    float columnWidth() const { return rareNonInheritedData->m_multiCol->m_width; }
+    bool hasAutoColumnWidth() const { return rareNonInheritedData->m_multiCol->m_autoWidth; }
+    unsigned short columnCount() const { return rareNonInheritedData->m_multiCol->m_count; }
+    bool hasAutoColumnCount() const { return rareNonInheritedData->m_multiCol->m_autoCount; }
+    float columnGap() const { return rareNonInheritedData->m_multiCol->m_gap; }
+    bool hasNormalColumnGap() const { return rareNonInheritedData->m_multiCol->m_normalGap; }
+    const Color& columnRuleColor() const { return rareNonInheritedData->m_multiCol->m_rule.color; }
+    EBorderStyle columnRuleStyle() const { return rareNonInheritedData->m_multiCol->m_rule.style(); }
+    unsigned short columnRuleWidth() const { return rareNonInheritedData->m_multiCol->ruleWidth(); }
+    bool columnRuleIsTransparent() const { return rareNonInheritedData->m_multiCol->m_rule.isTransparent(); }
+    EPageBreak columnBreakBefore() const { return static_cast<EPageBreak>(rareNonInheritedData->m_multiCol->m_breakBefore); }
+    EPageBreak columnBreakInside() const { return static_cast<EPageBreak>(rareNonInheritedData->m_multiCol->m_breakInside); }
+    EPageBreak columnBreakAfter() const { return static_cast<EPageBreak>(rareNonInheritedData->m_multiCol->m_breakAfter); }
+    const TransformOperations& transform() const { return rareNonInheritedData->m_transform->m_operations; }
+    Length transformOriginX() const { return rareNonInheritedData->m_transform->m_x; }
+    Length transformOriginY() const { return rareNonInheritedData->m_transform->m_y; }
+    bool hasTransform() const { return !rareNonInheritedData->m_transform->m_operations.operations().isEmpty(); }
+    void applyTransform(AffineTransform&, const IntSize& borderBoxSize, bool includeTransformOrigin = true) const;
+    bool hasMask() const { return rareNonInheritedData->m_mask.hasImage() || rareNonInheritedData->m_maskBoxImage.hasImage(); }
+    // End CSS3 Getters
+
+    // Apple-specific property getter methods
+    const AnimationList* animations() const { return rareNonInheritedData->m_animations.get(); }
+    const AnimationList* transitions() const { return rareNonInheritedData->m_transitions.get(); }
+
+    AnimationList* accessAnimations();
+    AnimationList* accessTransitions();
+
+    bool hasAnimations() const { return rareNonInheritedData->m_animations && rareNonInheritedData->m_animations->size() > 0; }
+    bool hasTransitions() const { return rareNonInheritedData->m_transitions && rareNonInheritedData->m_transitions->size() > 0; }
+
+    // return the first found Animation (including 'all' transitions)
+    const Animation* transitionForProperty(int property);
+
+    int lineClamp() const { return rareNonInheritedData->lineClamp; }
+    bool textSizeAdjust() const { return rareInheritedData->textSizeAdjust; }
+    ETextSecurity textSecurity() const { return static_cast<ETextSecurity>(rareInheritedData->textSecurity); }
+
+#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
+    Color tapHighlightColor() const { return rareInheritedData->tapHighlightColor; }
+#endif
+
+// attribute setter methods
+
+    void setDisplay(EDisplay v) { noninherited_flags._effectiveDisplay = v; }
+    void setOriginalDisplay(EDisplay v) { noninherited_flags._originalDisplay = v; }
+    void setPosition(EPosition v) { noninherited_flags._position = v; }
+    void setFloating(EFloat v) { noninherited_flags._floating = v; }
+
+    void setLeft(Length v) { SET_VAR(surround, offset.m_left, v) }
+    void setRight(Length v) { SET_VAR(surround, offset.m_right, v) }
+    void setTop(Length v) { SET_VAR(surround, offset.m_top, v) }
+    void setBottom(Length v) { SET_VAR(surround, offset.m_bottom, v) }
+
+    void setWidth(Length v) { SET_VAR(box, width, v) }
+    void setHeight(Length v) { SET_VAR(box, height, v) }
+
+    void setMinWidth(Length v) { SET_VAR(box, min_width, v) }
+    void setMaxWidth(Length v) { SET_VAR(box, max_width, v) }
+    void setMinHeight(Length v) { SET_VAR(box, min_height, v) }
+    void setMaxHeight(Length v) { SET_VAR(box, max_height, v) }
+
+#if ENABLE(DASHBOARD_SUPPORT)
+    Vector<StyleDashboardRegion> dashboardRegions() const { return rareNonInheritedData->m_dashboardRegions; }
+    void setDashboardRegions(Vector<StyleDashboardRegion> regions) { SET_VAR(rareNonInheritedData, m_dashboardRegions, regions); }
+
+    void setDashboardRegion(int type, const String& label, Length t, Length r, Length b, Length l, bool append)
+    {
+        StyleDashboardRegion region;
+        region.label = label;
+        region.offset.m_top = t;
+        region.offset.m_right = r;
+        region.offset.m_bottom = b;
+        region.offset.m_left = l;
+        region.type = type;
+        if (!append)
+            rareNonInheritedData.access()->m_dashboardRegions.clear();
+        rareNonInheritedData.access()->m_dashboardRegions.append(region);
+    }
+#endif
+
+    void resetBorder() { resetBorderImage(); resetBorderTop(); resetBorderRight(); resetBorderBottom(); resetBorderLeft(); resetBorderRadius(); }
+    void resetBorderTop() { SET_VAR(surround, border.top, BorderValue()) }
+    void resetBorderRight() { SET_VAR(surround, border.right, BorderValue()) }
+    void resetBorderBottom() { SET_VAR(surround, border.bottom, BorderValue()) }
+    void resetBorderLeft() { SET_VAR(surround, border.left, BorderValue()) }
+    void resetBorderImage() { SET_VAR(surround, border.image, NinePieceImage()) }
+    void resetBorderRadius() { resetBorderTopLeftRadius(); resetBorderTopRightRadius(); resetBorderBottomLeftRadius(); resetBorderBottomRightRadius(); }
+    void resetBorderTopLeftRadius() { SET_VAR(surround, border.topLeft, initialBorderRadius()) }
+    void resetBorderTopRightRadius() { SET_VAR(surround, border.topRight, initialBorderRadius()) }
+    void resetBorderBottomLeftRadius() { SET_VAR(surround, border.bottomLeft, initialBorderRadius()) }
+    void resetBorderBottomRightRadius() { SET_VAR(surround, border.bottomRight, initialBorderRadius()) }
+
+    void resetOutline() { SET_VAR(background, m_outline, OutlineValue()) }
+
+    void setBackgroundColor(const Color& v) { SET_VAR(background, m_color, v) }
+
+    void setBorderImage(const NinePieceImage& b) { SET_VAR(surround, border.image, b) }
+
+    void setBorderTopLeftRadius(const IntSize& s) { SET_VAR(surround, border.topLeft, s) }
+    void setBorderTopRightRadius(const IntSize& s) { SET_VAR(surround, border.topRight, s) }
+    void setBorderBottomLeftRadius(const IntSize& s) { SET_VAR(surround, border.bottomLeft, s) }
+    void setBorderBottomRightRadius(const IntSize& s) { SET_VAR(surround, border.bottomRight, s) }
+
+    void setBorderRadius(const IntSize& s)
+    {
+        setBorderTopLeftRadius(s);
+        setBorderTopRightRadius(s);
+        setBorderBottomLeftRadius(s);
+        setBorderBottomRightRadius(s);
+    }
+
+    void setBorderLeftWidth(unsigned short v) { SET_VAR(surround, border.left.width, v) }
+    void setBorderLeftStyle(EBorderStyle v) { SET_VAR(surround, border.left.m_style, v) }
+    void setBorderLeftColor(const Color& v) { SET_VAR(surround, border.left.color, v) }
+    void setBorderRightWidth(unsigned short v) { SET_VAR(surround, border.right.width, v) }
+    void setBorderRightStyle(EBorderStyle v) { SET_VAR(surround, border.right.m_style, v) }
+    void setBorderRightColor(const Color& v) { SET_VAR(surround, border.right.color, v) }
+    void setBorderTopWidth(unsigned short v) { SET_VAR(surround, border.top.width, v) }
+    void setBorderTopStyle(EBorderStyle v) { SET_VAR(surround, border.top.m_style, v) }
+    void setBorderTopColor(const Color& v) { SET_VAR(surround, border.top.color, v) }
+    void setBorderBottomWidth(unsigned short v) { SET_VAR(surround, border.bottom.width, v) }
+    void setBorderBottomStyle(EBorderStyle v) { SET_VAR(surround, border.bottom.m_style, v) }
+    void setBorderBottomColor(const Color& v) { SET_VAR(surround, border.bottom.color, v) }
+    void setOutlineWidth(unsigned short v) { SET_VAR(background, m_outline.width, v) }
+
+    void setOutlineStyle(EBorderStyle v, bool isAuto = false)
+    {
+        SET_VAR(background, m_outline.m_style, v)
+        SET_VAR(background, m_outline._auto, isAuto)
+    }
+
+    void setOutlineColor(const Color& v) { SET_VAR(background, m_outline.color, v) }
+
+    void setOverflowX(EOverflow v) { noninherited_flags._overflowX = v; }
+    void setOverflowY(EOverflow v) { noninherited_flags._overflowY = v; }
+    void setVisibility(EVisibility v) { inherited_flags._visibility = v; }
+    void setVerticalAlign(EVerticalAlign v) { noninherited_flags._vertical_align = v; }
+    void setVerticalAlignLength(Length l) { SET_VAR(box, vertical_align, l ) }
+
+    void setHasClip(bool b = true) { SET_VAR(visual, hasClip, b) }
+    void setClipLeft(Length v) { SET_VAR(visual, clip.m_left, v) }
+    void setClipRight(Length v) { SET_VAR(visual, clip.m_right, v) }
+    void setClipTop(Length v) { SET_VAR(visual, clip.m_top, v) }
+    void setClipBottom(Length v) { SET_VAR(visual, clip.m_bottom, v) }
+    void setClip(Length top, Length right, Length bottom, Length left);
+
+    void setUnicodeBidi( EUnicodeBidi b ) { noninherited_flags._unicodeBidi = b; }
+
+    void setClear(EClear v) { noninherited_flags._clear = v; }
+    void setTableLayout(ETableLayout v) { noninherited_flags._table_layout = v; }
+
+    bool setFontDescription(const FontDescription& v)
+    {
+        if (inherited->font.fontDescription() != v) {
+            inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing());
+            return true;
+        }
+        return false;
+    }
+
+    // Only used for blending font sizes when animating.
+    void setBlendedFontSize(int);
+
+    void setColor(const Color& v) { SET_VAR(inherited, color, v) }
+    void setTextIndent(Length v) { SET_VAR(inherited, indent, v) }
+    void setTextAlign(ETextAlign v) { inherited_flags._text_align = v; }
+    void setTextTransform(ETextTransform v) { inherited_flags._text_transform = v; }
+    void addToTextDecorationsInEffect(int v) { inherited_flags._text_decorations |= v; }
+    void setTextDecorationsInEffect(int v) { inherited_flags._text_decorations = v; }
+    void setTextDecoration(int v) { SET_VAR(visual, textDecoration, v); }
+    void setDirection(TextDirection v) { inherited_flags._direction = v; }
+    void setLineHeight(Length v) { SET_VAR(inherited, line_height, v) }
+    void setZoom(float f) { SET_VAR(visual, m_zoom, f); setEffectiveZoom(effectiveZoom() * zoom()); }
+    void setEffectiveZoom(float f) { SET_VAR(inherited, m_effectiveZoom, f) }
+
+    void setWhiteSpace(EWhiteSpace v) { inherited_flags._white_space = v; }
+
+    void setWordSpacing(int v) { inherited.access()->font.setWordSpacing(v); }
+    void setLetterSpacing(int v) { inherited.access()->font.setLetterSpacing(v); }
+
+    void clearBackgroundLayers() { background.access()->m_background = FillLayer(BackgroundFillLayer); }
+    void inheritBackgroundLayers(const FillLayer& parent) { background.access()->m_background = parent; }
+
+    void adjustBackgroundLayers()
+    {
+        if (backgroundLayers()->next()) {
+            accessBackgroundLayers()->cullEmptyLayers();
+            accessBackgroundLayers()->fillUnsetProperties();
+        }
+    }
+
+    void clearMaskLayers() { rareNonInheritedData.access()->m_mask = FillLayer(MaskFillLayer); }
+    void inheritMaskLayers(const FillLayer& parent) { rareNonInheritedData.access()->m_mask = parent; }
+
+    void adjustMaskLayers()
+    {
+        if (maskLayers()->next()) {
+            accessMaskLayers()->cullEmptyLayers();
+            accessMaskLayers()->fillUnsetProperties();
+        }
+    }
+
+    void setMaskBoxImage(const NinePieceImage& b) { SET_VAR(rareNonInheritedData, m_maskBoxImage, b) }
+
+    void setBorderCollapse(bool collapse) { inherited_flags._border_collapse = collapse; }
+    void setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v) }
+    void setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v) }
+    void setEmptyCells(EEmptyCell v) { inherited_flags._empty_cells = v; }
+    void setCaptionSide(ECaptionSide v) { inherited_flags._caption_side = v; }
+
+    void setCounterIncrement(short v) { SET_VAR(visual, counterIncrement, v) }
+    void setCounterReset(short v) { SET_VAR(visual, counterReset, v) }
+
+    void setListStyleType(EListStyleType v) { inherited_flags._list_style_type = v; }
+    void setListStyleImage(StyleImage* v) { if (inherited->list_style_image != v) inherited.access()->list_style_image = v; }
+    void setListStylePosition(EListStylePosition v) { inherited_flags._list_style_position = v; }
+
+    void resetMargin() { SET_VAR(surround, margin, LengthBox(Fixed)) }
+    void setMarginTop(Length v) { SET_VAR(surround, margin.m_top, v) }
+    void setMarginBottom(Length v) { SET_VAR(surround, margin.m_bottom, v) }
+    void setMarginLeft(Length v) { SET_VAR(surround, margin.m_left, v) }
+    void setMarginRight(Length v) { SET_VAR(surround, margin.m_right, v) }
+
+    void resetPadding() { SET_VAR(surround, padding, LengthBox(Auto)) }
+    void setPaddingBox(const LengthBox& b) { SET_VAR(surround, padding, b) }
+    void setPaddingTop(Length v) { SET_VAR(surround, padding.m_top, v) }
+    void setPaddingBottom(Length v) { SET_VAR(surround, padding.m_bottom, v) }
+    void setPaddingLeft(Length v) { SET_VAR(surround, padding.m_left, v) }
+    void setPaddingRight(Length v) { SET_VAR(surround, padding.m_right, v) }
+
+    void setCursor( ECursor c ) { inherited_flags._cursor_style = c; }
+    void addCursor(CachedImage*, const IntPoint& = IntPoint());
+    void setCursorList(PassRefPtr<CursorList>);
+    void clearCursorList();
+
+    bool forceBackgroundsToWhite() const { return inherited_flags._force_backgrounds_to_white; }
+    void setForceBackgroundsToWhite(bool b=true) { inherited_flags._force_backgrounds_to_white = b; }
+
+    bool htmlHacks() const { return inherited_flags._htmlHacks; }
+    void setHtmlHacks(bool b=true) { inherited_flags._htmlHacks = b; }
+
+    bool hasAutoZIndex() const { return box->z_auto; }
+    void setHasAutoZIndex() { SET_VAR(box, z_auto, true); SET_VAR(box, z_index, 0) }
+    int zIndex() const { return box->z_index; }
+    void setZIndex(int v) { SET_VAR(box, z_auto, false); SET_VAR(box, z_index, v) }
+
+    void setWidows(short w) { SET_VAR(inherited, widows, w); }
+    void setOrphans(short o) { SET_VAR(inherited, orphans, o); }
+    void setPageBreakInside(EPageBreak b) { SET_VAR(inherited, page_break_inside, b); }
+    void setPageBreakBefore(EPageBreak b) { noninherited_flags._page_break_before = b; }
+    void setPageBreakAfter(EPageBreak b) { noninherited_flags._page_break_after = b; }
+
+    // CSS3 Setters
+#if ENABLE(XBL)
+    void deleteBindingURIs() { SET_VAR(rareNonInheritedData, bindingURI, static_cast<BindingURI*>(0)); }
+    void inheritBindingURIs(BindingURI* other) { SET_VAR(rareNonInheritedData, bindingURI, other->copy()); }
+    void addBindingURI(StringImpl* uri);
+#endif
+
+    void setOutlineOffset(int v) { SET_VAR(background, m_outline._offset, v) }
+    void setTextShadow(ShadowData* val, bool add=false);
+    void setTextStrokeColor(const Color& c) { SET_VAR(rareInheritedData, textStrokeColor, c) }
+    void setTextStrokeWidth(float w) { SET_VAR(rareInheritedData, textStrokeWidth, w) }
+    void setTextFillColor(const Color& c) { SET_VAR(rareInheritedData, textFillColor, c) }
+    void setOpacity(float f) { SET_VAR(rareNonInheritedData, opacity, f); }
+    void setAppearance(ControlPart a) { SET_VAR(rareNonInheritedData, m_appearance, a); }
+    void setBoxAlign(EBoxAlignment a) { SET_VAR(rareNonInheritedData.access()->flexibleBox, align, a); }
+    void setBoxDirection(EBoxDirection d) { inherited_flags._box_direction = d; }
+    void setBoxFlex(float f) { SET_VAR(rareNonInheritedData.access()->flexibleBox, flex, f); }
+    void setBoxFlexGroup(unsigned int fg) { SET_VAR(rareNonInheritedData.access()->flexibleBox, flex_group, fg); }
+    void setBoxLines(EBoxLines l) { SET_VAR(rareNonInheritedData.access()->flexibleBox, lines, l); }
+    void setBoxOrdinalGroup(unsigned int og) { SET_VAR(rareNonInheritedData.access()->flexibleBox, ordinal_group, og); }
+    void setBoxOrient(EBoxOrient o) { SET_VAR(rareNonInheritedData.access()->flexibleBox, orient, o); }
+    void setBoxPack(EBoxAlignment p) { SET_VAR(rareNonInheritedData.access()->flexibleBox, pack, p); }
+    void setBoxShadow(ShadowData* val, bool add=false);
+    void setBoxReflect(PassRefPtr<StyleReflection> reflect) { if (rareNonInheritedData->m_boxReflect != reflect) rareNonInheritedData.access()->m_boxReflect = reflect; }
+    void setBoxSizing(EBoxSizing s) { SET_VAR(box, boxSizing, s); }
+    void setMarqueeIncrement(const Length& f) { SET_VAR(rareNonInheritedData.access()->marquee, increment, f); }
+    void setMarqueeSpeed(int f) { SET_VAR(rareNonInheritedData.access()->marquee, speed, f); }
+    void setMarqueeDirection(EMarqueeDirection d) { SET_VAR(rareNonInheritedData.access()->marquee, direction, d); }
+    void setMarqueeBehavior(EMarqueeBehavior b) { SET_VAR(rareNonInheritedData.access()->marquee, behavior, b); }
+    void setMarqueeLoopCount(int i) { SET_VAR(rareNonInheritedData.access()->marquee, loops, i); }
+    void setUserModify(EUserModify u) { SET_VAR(rareInheritedData, userModify, u); }
+    void setUserDrag(EUserDrag d) { SET_VAR(rareNonInheritedData, userDrag, d); }
+    void setUserSelect(EUserSelect s) { SET_VAR(rareInheritedData, userSelect, s); }
+    void setTextOverflow(bool b) { SET_VAR(rareNonInheritedData, textOverflow, b); }
+    void setMarginTopCollapse(EMarginCollapse c) { SET_VAR(rareNonInheritedData, marginTopCollapse, c); }
+    void setMarginBottomCollapse(EMarginCollapse c) { SET_VAR(rareNonInheritedData, marginBottomCollapse, c); }
+    void setWordBreak(EWordBreak b) { SET_VAR(rareInheritedData, wordBreak, b); }
+    void setWordWrap(EWordWrap b) { SET_VAR(rareInheritedData, wordWrap, b); }
+    void setNBSPMode(ENBSPMode b) { SET_VAR(rareInheritedData, nbspMode, b); }
+    void setKHTMLLineBreak(EKHTMLLineBreak b) { SET_VAR(rareInheritedData, khtmlLineBreak, b); }
+    void setMatchNearestMailBlockquoteColor(EMatchNearestMailBlockquoteColor c) { SET_VAR(rareNonInheritedData, matchNearestMailBlockquoteColor, c); }
+    void setHighlight(const AtomicString& h) { SET_VAR(rareInheritedData, highlight, h); }
+    void setBorderFit(EBorderFit b) { SET_VAR(rareNonInheritedData, m_borderFit, b); }
+    void setResize(EResize r) { SET_VAR(rareInheritedData, resize, r); }
+    void setColumnWidth(float f) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoWidth, false); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_width, f); }
+    void setHasAutoColumnWidth() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoWidth, true); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_width, 0); }
+    void setColumnCount(unsigned short c) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoCount, false); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_count, c); }
+    void setHasAutoColumnCount() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoCount, true); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_count, 0); }
+    void setColumnGap(float f) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_normalGap, false); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_gap, f); }
+    void setHasNormalColumnGap() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_normalGap, true); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_gap, 0); }
+    void setColumnRuleColor(const Color& c) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.color, c); }
+    void setColumnRuleStyle(EBorderStyle b) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.m_style, b); }
+    void setColumnRuleWidth(unsigned short w) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.width, w); }
+    void resetColumnRule() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule, BorderValue()) }
+    void setColumnBreakBefore(EPageBreak p) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakBefore, p); }
+    void setColumnBreakInside(EPageBreak p) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakInside, p); }
+    void setColumnBreakAfter(EPageBreak p) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakAfter, p); }
+    void setTransform(const TransformOperations& ops) { SET_VAR(rareNonInheritedData.access()->m_transform, m_operations, ops); }
+    void setTransformOriginX(Length l) { SET_VAR(rareNonInheritedData.access()->m_transform, m_x, l); }
+    void setTransformOriginY(Length l) { SET_VAR(rareNonInheritedData.access()->m_transform, m_y, l); }
+    // End CSS3 Setters
+
+    // Apple-specific property setters
+    void clearAnimations()
+    {
+        rareNonInheritedData.access()->m_animations.clear();
+    }
+
+    void clearTransitions()
+    {
+        rareNonInheritedData.access()->m_transitions.clear();
+    }
+
+    void inheritAnimations(const AnimationList* parent) { rareNonInheritedData.access()->m_animations.set(parent ? new AnimationList(*parent) : 0); }
+    void inheritTransitions(const AnimationList* parent) { rareNonInheritedData.access()->m_transitions.set(parent ? new AnimationList(*parent) : 0); }
+    void adjustAnimations();
+    void adjustTransitions();
+
+    void setLineClamp(int c) { SET_VAR(rareNonInheritedData, lineClamp, c); }
+    void setTextSizeAdjust(bool b) { SET_VAR(rareInheritedData, textSizeAdjust, b); }
+    void setTextSecurity(ETextSecurity aTextSecurity) { SET_VAR(rareInheritedData, textSecurity, aTextSecurity); }
+
+#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
+    void setTapHighlightColor(const Color& v) { SET_VAR(rareInheritedData, tapHighlightColor, v); }
+#endif
+
+#if ENABLE(SVG)
+    const SVGRenderStyle* svgStyle() const { return m_svgStyle.get(); }
+    SVGRenderStyle* accessSVGStyle() { return m_svgStyle.access(); }
+    
+    float fillOpacity() const { return svgStyle()->fillOpacity(); }
+    void setFillOpacity(float f) { accessSVGStyle()->setFillOpacity(f); }
+    
+    float strokeOpacity() const { return svgStyle()->strokeOpacity(); }
+    void setStrokeOpacity(float f) { accessSVGStyle()->setStrokeOpacity(f); }
+    
+    float floodOpacity() const { return svgStyle()->floodOpacity(); }
+    void setFloodOpacity(float f) { accessSVGStyle()->setFloodOpacity(f); }
+#endif
+
+    const ContentData* contentData() const { return rareNonInheritedData->m_content.get(); }
+    bool contentDataEquivalent(const RenderStyle* otherStyle) const;
+    void clearContent();
+    void setContent(StringImpl*, bool add = false);
+    void setContent(PassRefPtr<StyleImage>, bool add = false);
+    void setContent(CounterContent*, bool add = false);
+
+    const CounterDirectiveMap* counterDirectives() const;
+    CounterDirectiveMap& accessCounterDirectives();
+
+    bool inheritedNotEqual(RenderStyle*) const;
+
+    // The difference between two styles.  The following values are used:
+    // (1) Equal - The two styles are identical
+    // (2) Repaint - The object just needs to be repainted.
+    // (3) RepaintLayer - The layer and its descendant layers needs to be repainted.
+    // (4) Layout - A layout is required.
+    enum Diff { Equal, Repaint, RepaintLayer, LayoutPositionedMovementOnly, Layout };
+    Diff diff(const RenderStyle*) const;
+
+    bool isDisplayReplacedType() const
+    {
+        return display() == INLINE_BLOCK || display() == INLINE_BOX || display() == INLINE_TABLE;
+    }
+
+    bool isDisplayInlineType() const
+    {
+        return display() == INLINE || isDisplayReplacedType();
+    }
+
+    bool isOriginalDisplayInlineType() const
+    {
+        return originalDisplay() == INLINE || originalDisplay() == INLINE_BLOCK ||
+               originalDisplay() == INLINE_BOX || originalDisplay() == INLINE_TABLE;
+    }
+
+    // To obtain at any time the pseudo state for a given link.
+    PseudoState pseudoState() const { return static_cast<PseudoState>(m_pseudoState); }
+    void setPseudoState(PseudoState s) { m_pseudoState = s; }
+
+    // To tell if this style matched attribute selectors. This makes it impossible to share.
+    bool affectedByAttributeSelectors() const { return m_affectedByAttributeSelectors; }
+    void setAffectedByAttributeSelectors() { m_affectedByAttributeSelectors = true; }
+
+    bool unique() const { return m_unique; }
+    void setUnique() { m_unique = true; }
+
+    // Methods for indicating the style is affected by dynamic updates (e.g., children changing, our position changing in our sibling list, etc.)
+    bool affectedByEmpty() const { return m_affectedByEmpty; }
+    bool emptyState() const { return m_emptyState; }
+    void setEmptyState(bool b) { m_affectedByEmpty = true; m_unique = true; m_emptyState = b; }
+    bool childrenAffectedByPositionalRules() const { return childrenAffectedByForwardPositionalRules() || childrenAffectedByBackwardPositionalRules(); }
+    bool childrenAffectedByFirstChildRules() const { return m_childrenAffectedByFirstChildRules; }
+    void setChildrenAffectedByFirstChildRules() { m_childrenAffectedByFirstChildRules = true; }
+    bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; }
+    void setChildrenAffectedByLastChildRules() { m_childrenAffectedByLastChildRules = true; }
+    bool childrenAffectedByDirectAdjacentRules() const { return m_childrenAffectedByDirectAdjacentRules; }
+    void setChildrenAffectedByDirectAdjacentRules() { m_childrenAffectedByDirectAdjacentRules = true; }
+    bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; }
+    void setChildrenAffectedByForwardPositionalRules() { m_childrenAffectedByForwardPositionalRules = true; }
+    bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; }
+    void setChildrenAffectedByBackwardPositionalRules() { m_childrenAffectedByBackwardPositionalRules = true; }
+    bool firstChildState() const { return m_firstChildState; }
+    void setFirstChildState() { m_firstChildState = true; }
+    bool lastChildState() const { return m_lastChildState; }
+    void setLastChildState() { m_lastChildState = true; }
+    unsigned childIndex() const { return m_childIndex; }
+    void setChildIndex(unsigned index) { m_childIndex = index; }
+
+    // Initial values for all the properties
+    static bool initialBorderCollapse() { return false; }
+    static EBorderStyle initialBorderStyle() { return BNONE; }
+    static NinePieceImage initialNinePieceImage() { return NinePieceImage(); }
+    static IntSize initialBorderRadius() { return IntSize(0, 0); }
+    static ECaptionSide initialCaptionSide() { return CAPTOP; }
+    static EClear initialClear() { return CNONE; }
+    static TextDirection initialDirection() { return LTR; }
+    static EDisplay initialDisplay() { return INLINE; }
+    static EEmptyCell initialEmptyCells() { return SHOW; }
+    static EFloat initialFloating() { return FNONE; }
+    static EListStylePosition initialListStylePosition() { return OUTSIDE; }
+    static EListStyleType initialListStyleType() { return DISC; }
+    static EOverflow initialOverflowX() { return OVISIBLE; }
+    static EOverflow initialOverflowY() { return OVISIBLE; }
+    static EPageBreak initialPageBreak() { return PBAUTO; }
+    static EPosition initialPosition() { return StaticPosition; }
+    static ETableLayout initialTableLayout() { return TAUTO; }
+    static EUnicodeBidi initialUnicodeBidi() { return UBNormal; }
+    static ETextTransform initialTextTransform() { return TTNONE; }
+    static EVisibility initialVisibility() { return VISIBLE; }
+    static EWhiteSpace initialWhiteSpace() { return NORMAL; }
+    static short initialHorizontalBorderSpacing() { return 0; }
+    static short initialVerticalBorderSpacing() { return 0; }
+    static ECursor initialCursor() { return CURSOR_AUTO; }
+    static Color initialColor() { return Color::black; }
+    static StyleImage* initialListStyleImage() { return 0; }
+    static unsigned short initialBorderWidth() { return 3; }
+    static int initialLetterWordSpacing() { return 0; }
+    static Length initialSize() { return Length(); }
+    static Length initialMinSize() { return Length(0, Fixed); }
+    static Length initialMaxSize() { return Length(undefinedLength, Fixed); }
+    static Length initialOffset() { return Length(); }
+    static Length initialMargin() { return Length(Fixed); }
+    static Length initialPadding() { return Length(Fixed); }
+    static Length initialTextIndent() { return Length(Fixed); }
+    static EVerticalAlign initialVerticalAlign() { return BASELINE; }
+    static int initialWidows() { return 2; }
+    static int initialOrphans() { return 2; }
+    static Length initialLineHeight() { return Length(-100.0, Percent); }
+    static ETextAlign initialTextAlign() { return TAAUTO; }
+    static ETextDecoration initialTextDecoration() { return TDNONE; }
+    static float initialZoom() { return 1.0f; }
+    static int initialOutlineOffset() { return 0; }
+    static float initialOpacity() { return 1.0f; }
+    static EBoxAlignment initialBoxAlign() { return BSTRETCH; }
+    static EBoxDirection initialBoxDirection() { return BNORMAL; }
+    static EBoxLines initialBoxLines() { return SINGLE; }
+    static EBoxOrient initialBoxOrient() { return HORIZONTAL; }
+    static EBoxAlignment initialBoxPack() { return BSTART; }
+    static float initialBoxFlex() { return 0.0f; }
+    static int initialBoxFlexGroup() { return 1; }
+    static int initialBoxOrdinalGroup() { return 1; }
+    static EBoxSizing initialBoxSizing() { return CONTENT_BOX; }
+    static StyleReflection* initialBoxReflect() { return 0; }
+    static int initialMarqueeLoopCount() { return -1; }
+    static int initialMarqueeSpeed() { return 85; }
+    static Length initialMarqueeIncrement() { return Length(6, Fixed); }
+    static EMarqueeBehavior initialMarqueeBehavior() { return MSCROLL; }
+    static EMarqueeDirection initialMarqueeDirection() { return MAUTO; }
+    static EUserModify initialUserModify() { return READ_ONLY; }
+    static EUserDrag initialUserDrag() { return DRAG_AUTO; }
+    static EUserSelect initialUserSelect() { return SELECT_TEXT; }
+    static bool initialTextOverflow() { return false; }
+    static EMarginCollapse initialMarginTopCollapse() { return MCOLLAPSE; }
+    static EMarginCollapse initialMarginBottomCollapse() { return MCOLLAPSE; }
+    static EWordBreak initialWordBreak() { return NormalWordBreak; }
+    static EWordWrap initialWordWrap() { return NormalWordWrap; }
+    static ENBSPMode initialNBSPMode() { return NBNORMAL; }
+    static EKHTMLLineBreak initialKHTMLLineBreak() { return LBNORMAL; }
+    static EMatchNearestMailBlockquoteColor initialMatchNearestMailBlockquoteColor() { return BCNORMAL; }
+    static const AtomicString& initialHighlight() { return nullAtom; }
+    static EBorderFit initialBorderFit() { return BorderFitBorder; }
+    static EResize initialResize() { return RESIZE_NONE; }
+    static ControlPart initialAppearance() { return NoControlPart; }
+    static bool initialVisuallyOrdered() { return false; }
+    static float initialTextStrokeWidth() { return 0; }
+    static unsigned short initialColumnCount() { return 1; }
+    static const TransformOperations& initialTransform() { static TransformOperations ops; return ops; }
+    static Length initialTransformOriginX() { return Length(50.0, Percent); }
+    static Length initialTransformOriginY() { return Length(50.0, Percent); }
+
+    // Keep these at the end.
+    static float initialAnimationDelay() { return 0; }
+    static bool initialAnimationDirection() { return false; }
+    static double initialAnimationDuration() { return 0; }
+    static int initialAnimationIterationCount() { return 1; }
+    static String initialAnimationName() { return String(); }
+    static unsigned initialAnimationPlayState() { return AnimPlayStatePlaying; }
+    static int initialAnimationProperty() { return cAnimateAll; }
+    static TimingFunction initialAnimationTimingFunction() { return TimingFunction(); }
+    static int initialLineClamp() { return -1; }
+    static bool initialTextSizeAdjust() { return true; }
+    static ETextSecurity initialTextSecurity() { return TSNONE; }
+#if ENABLE(DASHBOARD_SUPPORT)
+    static const Vector<StyleDashboardRegion>& initialDashboardRegions();
+    static const Vector<StyleDashboardRegion>& noneDashboardRegions();
+#endif
+
+#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
+    static Color initialTapHighlightColor() { return Color::tap; }
+#endif
+};
+
+} // namespace WebCore
+
+#endif // RenderStyle_h
diff --git a/WebCore/rendering/style/RenderStyleConstants.h b/WebCore/rendering/style/RenderStyleConstants.h
new file mode 100644
index 0000000..37fbc1e
--- /dev/null
+++ b/WebCore/rendering/style/RenderStyleConstants.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderStyleConstants_h
+#define RenderStyleConstants_h
+
+namespace WebCore {
+
+/*
+ * WARNING:
+ * --------
+ *
+ * The order of the values in the enums have to agree with the order specified
+ * in CSSValueKeywords.in, otherwise some optimizations in the parser will fail,
+ * and produce invalid results.
+ */
+
+
+// These have been defined in the order of their precedence for border-collapsing. Do
+// not change this order!
+enum EBorderStyle { BNONE, BHIDDEN, INSET, GROOVE, RIDGE, OUTSET, DOTTED, DASHED, SOLID, DOUBLE };
+
+enum EBorderPrecedence { BOFF, BTABLE, BCOLGROUP, BCOL, BROWGROUP, BROW, BCELL };
+
+enum PseudoState { PseudoUnknown, PseudoNone, PseudoAnyLink, PseudoLink, PseudoVisited};
+
+enum EPosition {
+    StaticPosition, RelativePosition, AbsolutePosition, FixedPosition
+};
+
+enum EFloat {
+    FNONE = 0, FLEFT, FRIGHT
+};
+
+
+enum EMarginCollapse { MCOLLAPSE, MSEPARATE, MDISCARD };
+
+// Box attributes. Not inherited.
+
+enum EBoxSizing { CONTENT_BOX, BORDER_BOX };
+
+// Random visual rendering model attributes. Not inherited.
+
+enum EOverflow {
+    OVISIBLE, OHIDDEN, OSCROLL, OAUTO, OOVERLAY, OMARQUEE
+};
+
+enum EVerticalAlign {
+    BASELINE, MIDDLE, SUB, SUPER, TEXT_TOP,
+    TEXT_BOTTOM, TOP, BOTTOM, BASELINE_MIDDLE, LENGTH
+};
+
+enum EClear{
+    CNONE = 0, CLEFT = 1, CRIGHT = 2, CBOTH = 3
+};
+
+enum ETableLayout {
+    TAUTO, TFIXED
+};
+
+enum EUnicodeBidi {
+    UBNormal, Embed, Override
+};
+
+enum EFillBox {
+    BorderFillBox, PaddingFillBox, ContentFillBox, TextFillBox
+};
+
+enum EFillRepeat {
+    RepeatFill, RepeatXFill, RepeatYFill, NoRepeatFill
+};
+
+enum EFillLayerType {
+    BackgroundFillLayer, MaskFillLayer
+};
+
+// CSS3 Marquee Properties
+
+enum EMarqueeBehavior { MNONE, MSCROLL, MSLIDE, MALTERNATE };
+enum EMarqueeDirection { MAUTO = 0, MLEFT = 1, MRIGHT = -1, MUP = 2, MDOWN = -2, MFORWARD = 3, MBACKWARD = -3 };
+
+// CSS3 Flexible Box Properties
+
+enum EBoxAlignment { BSTRETCH, BSTART, BCENTER, BEND, BJUSTIFY, BBASELINE };
+enum EBoxOrient { HORIZONTAL, VERTICAL };
+enum EBoxLines { SINGLE, MULTIPLE };
+enum EBoxDirection { BNORMAL, BREVERSE };
+
+enum ETextSecurity {
+    TSNONE, TSDISC, TSCIRCLE, TSSQUARE
+};
+
+// CSS3 User Modify Properties
+
+enum EUserModify {
+    READ_ONLY, READ_WRITE, READ_WRITE_PLAINTEXT_ONLY
+};
+
+// CSS3 User Drag Values
+
+enum EUserDrag {
+    DRAG_AUTO, DRAG_NONE, DRAG_ELEMENT
+};
+
+// CSS3 User Select Values
+
+enum EUserSelect {
+    SELECT_NONE, SELECT_TEXT
+};
+
+// Word Break Values. Matches WinIE, rather than CSS3
+
+enum EWordBreak {
+    NormalWordBreak, BreakAllWordBreak, BreakWordBreak
+};
+
+enum EWordWrap {
+    NormalWordWrap, BreakWordWrap
+};
+
+enum ENBSPMode {
+    NBNORMAL, SPACE
+};
+
+enum EKHTMLLineBreak {
+    LBNORMAL, AFTER_WHITE_SPACE
+};
+
+enum EMatchNearestMailBlockquoteColor {
+    BCNORMAL, MATCH
+};
+
+enum EResize {
+    RESIZE_NONE, RESIZE_BOTH, RESIZE_HORIZONTAL, RESIZE_VERTICAL
+};
+
+enum EListStyleType {
+     DISC, CIRCLE, SQUARE, LDECIMAL, DECIMAL_LEADING_ZERO,
+     LOWER_ROMAN, UPPER_ROMAN, LOWER_GREEK,
+     LOWER_ALPHA, LOWER_LATIN, UPPER_ALPHA, UPPER_LATIN,
+     HEBREW, ARMENIAN, GEORGIAN, CJK_IDEOGRAPHIC,
+     HIRAGANA, KATAKANA, HIRAGANA_IROHA, KATAKANA_IROHA, LNONE
+};
+
+enum ContentType {
+    CONTENT_NONE, CONTENT_OBJECT, CONTENT_TEXT, CONTENT_COUNTER
+};
+
+enum EBorderFit { BorderFitBorder, BorderFitLines };
+
+enum ETimingFunctionType { LinearTimingFunction, CubicBezierTimingFunction };
+
+enum EAnimPlayState {
+    AnimPlayStatePlaying = 0x0,
+    AnimPlayStatePaused = 0x1
+};
+
+enum EWhiteSpace {
+    NORMAL, PRE, PRE_WRAP, PRE_LINE, NOWRAP, KHTML_NOWRAP
+};
+
+enum ETextAlign {
+    TAAUTO, LEFT, RIGHT, CENTER, JUSTIFY, WEBKIT_LEFT, WEBKIT_RIGHT, WEBKIT_CENTER
+};
+
+enum ETextTransform {
+    CAPITALIZE, UPPERCASE, LOWERCASE, TTNONE
+};
+
+enum ETextDecoration {
+    TDNONE = 0x0 , UNDERLINE = 0x1, OVERLINE = 0x2, LINE_THROUGH= 0x4, BLINK = 0x8
+};
+
+enum EPageBreak {
+    PBAUTO, PBALWAYS, PBAVOID
+};
+
+enum EEmptyCell {
+    SHOW, HIDE
+};
+
+enum ECaptionSide {
+    CAPTOP, CAPBOTTOM, CAPLEFT, CAPRIGHT
+};
+
+enum EListStylePosition { OUTSIDE, INSIDE };
+
+enum EVisibility { VISIBLE, HIDDEN, COLLAPSE };
+
+enum ECursor {
+    // The following must match the order in CSSValueKeywords.in.
+    CURSOR_AUTO,
+    CURSOR_CROSS,
+    CURSOR_DEFAULT,
+    CURSOR_POINTER,
+    CURSOR_MOVE,
+    CURSOR_VERTICAL_TEXT,
+    CURSOR_CELL,
+    CURSOR_CONTEXT_MENU,
+    CURSOR_ALIAS,
+    CURSOR_PROGRESS,
+    CURSOR_NO_DROP,
+    CURSOR_NOT_ALLOWED,
+    CURSOR_WEBKIT_ZOOM_IN,
+    CURSOR_WEBKIT_ZOOM_OUT,
+    CURSOR_E_RESIZE,
+    CURSOR_NE_RESIZE,
+    CURSOR_NW_RESIZE,
+    CURSOR_N_RESIZE,
+    CURSOR_SE_RESIZE,
+    CURSOR_SW_RESIZE,
+    CURSOR_S_RESIZE,
+    CURSOR_W_RESIZE,
+    CURSOR_EW_RESIZE,
+    CURSOR_NS_RESIZE,
+    CURSOR_NESW_RESIZE,
+    CURSOR_NWSE_RESIZE,
+    CURSOR_COL_RESIZE,
+    CURSOR_ROW_RESIZE,
+    CURSOR_TEXT,
+    CURSOR_WAIT,
+    CURSOR_HELP,
+    CURSOR_ALL_SCROLL,
+    CURSOR_WEBKIT_GRAB,
+    CURSOR_WEBKIT_GRABBING,
+
+    // The following are handled as exceptions so don't need to match.
+    CURSOR_COPY,
+    CURSOR_NONE
+};
+
+enum EDisplay {
+    INLINE, BLOCK, LIST_ITEM, RUN_IN, COMPACT, INLINE_BLOCK,
+    TABLE, INLINE_TABLE, TABLE_ROW_GROUP,
+    TABLE_HEADER_GROUP, TABLE_FOOTER_GROUP, TABLE_ROW,
+    TABLE_COLUMN_GROUP, TABLE_COLUMN, TABLE_CELL,
+    TABLE_CAPTION, BOX, INLINE_BOX, NONE
+};
+
+} // namespace WebCore
+
+#endif // RenderStyleConstants_h
diff --git a/WebCore/rendering/style/RotateTransformOperation.cpp b/WebCore/rendering/style/RotateTransformOperation.cpp
new file mode 100644
index 0000000..4887cee
--- /dev/null
+++ b/WebCore/rendering/style/RotateTransformOperation.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RotateTransformOperation.h"
+
+namespace WebCore {
+
+PassRefPtr<TransformOperation> RotateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
+{
+    if (from && !from->isSameType(*this))
+        return this;
+    
+    if (blendToIdentity)
+        return RotateTransformOperation::create(m_angle - m_angle * progress, m_type);
+    
+    const RotateTransformOperation* fromOp = static_cast<const RotateTransformOperation*>(from);
+    double fromAngle = fromOp ? fromOp->m_angle : 0;
+    return RotateTransformOperation::create(fromAngle + (m_angle - fromAngle) * progress, m_type);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/RotateTransformOperation.h b/WebCore/rendering/style/RotateTransformOperation.h
new file mode 100644
index 0000000..9cfc9c8
--- /dev/null
+++ b/WebCore/rendering/style/RotateTransformOperation.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RotateTransformOperation_h
+#define RotateTransformOperation_h
+
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class RotateTransformOperation : public TransformOperation {
+public:
+    static PassRefPtr<RotateTransformOperation> create(double angle, OperationType type)
+    {
+        return adoptRef(new RotateTransformOperation(angle, type));
+    }
+
+    virtual bool isIdentity() const { return m_angle == 0; }
+    virtual OperationType getOperationType() const { return m_type; }
+    virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
+
+    virtual bool operator==(const TransformOperation& o) const
+    {
+        if (!isSameType(o))
+            return false;
+        const RotateTransformOperation* r = static_cast<const RotateTransformOperation*>(&o);
+        return m_angle == r->m_angle;
+    }
+
+    virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
+    {
+        transform.rotate(m_angle);
+        return false;
+    }
+
+    virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
+
+    double angle() const { return m_angle; }
+
+private:
+    RotateTransformOperation(double angle, OperationType type)
+        : m_angle(angle)
+        , m_type(type)
+    {
+    }
+
+    double m_angle;
+    OperationType m_type;
+};
+
+} // namespace WebCore
+
+#endif // RotateTransformOperation_h
diff --git a/WebCore/rendering/style/SVGRenderStyle.cpp b/WebCore/rendering/style/SVGRenderStyle.cpp
new file mode 100644
index 0000000..1749978
--- /dev/null
+++ b/WebCore/rendering/style/SVGRenderStyle.cpp
@@ -0,0 +1,146 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005 Rob Buis <[email protected]>
+
+    Based on khtml code by:
+    Copyright (C) 1999 Antti Koivisto ([email protected])
+    Copyright (C) 1999-2003 Lars Knoll ([email protected])
+    Copyright (C) 2002-2003 Dirk Mueller ([email protected])
+    Copyright (C) 2002 Apple Computer, Inc.
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#if ENABLE(SVG)
+#include "SVGRenderStyle.h"
+
+#include "CSSPrimitiveValue.h"
+#include "CSSValueList.h"
+#include "RenderObject.h"
+#include "RenderStyle.h"
+#include "SVGStyledElement.h"
+
+namespace WebCore {
+
+SVGRenderStyle::SVGRenderStyle()
+{
+    static SVGRenderStyle* defaultStyle = new SVGRenderStyle(CreateDefault);
+
+    fill = defaultStyle->fill;
+    stroke = defaultStyle->stroke;
+    text = defaultStyle->text;
+    stops = defaultStyle->stops;
+    clip = defaultStyle->clip;
+    mask = defaultStyle->mask;
+    misc = defaultStyle->misc;
+    markers = defaultStyle->markers;
+
+    setBitDefaults();
+}
+
+SVGRenderStyle::SVGRenderStyle(CreateDefaultType)
+{
+    setBitDefaults();
+
+    fill.init();
+    stroke.init();
+    text.init();
+    stops.init();
+    clip.init();
+    mask.init();
+    misc.init();
+    markers.init();
+}
+
+SVGRenderStyle::SVGRenderStyle(const SVGRenderStyle& other)
+    : RefCounted<SVGRenderStyle>()
+{
+    fill = other.fill;
+    stroke = other.stroke;
+    text = other.text;
+    stops = other.stops;
+    clip = other.clip;
+    mask = other.mask;
+    misc = other.misc;
+    markers = other.markers;
+
+    svg_inherited_flags = other.svg_inherited_flags;
+    svg_noninherited_flags = other.svg_noninherited_flags;
+}
+
+SVGRenderStyle::~SVGRenderStyle()
+{
+}
+
+bool SVGRenderStyle::operator==(const SVGRenderStyle& o) const
+{
+    return (fill == o.fill && stroke == o.stroke && text == o.text &&
+        stops == o.stops && clip == o.clip && mask == o.mask &&
+        misc == o.misc && markers == o.markers &&
+        svg_inherited_flags == o.svg_inherited_flags &&
+        svg_noninherited_flags == o.svg_noninherited_flags);
+}
+
+bool SVGRenderStyle::inheritedNotEqual(const SVGRenderStyle* other) const
+{
+    return (fill != other->fill
+            || stroke != other->stroke
+            || markers != other->markers
+            || text != other->text
+            || svg_inherited_flags != other->svg_inherited_flags);
+}
+
+void SVGRenderStyle::inheritFrom(const SVGRenderStyle* svgInheritParent)
+{
+    if (!svgInheritParent)
+        return;
+
+    fill = svgInheritParent->fill;
+    stroke = svgInheritParent->stroke;
+    markers = svgInheritParent->markers;
+    text = svgInheritParent->text;
+
+    svg_inherited_flags = svgInheritParent->svg_inherited_flags;
+}
+
+float SVGRenderStyle::cssPrimitiveToLength(const RenderObject* item, CSSValue* value, float defaultValue)
+{
+    CSSPrimitiveValue* primitive = static_cast<CSSPrimitiveValue*>(value);
+
+    unsigned short cssType = (primitive ? primitive->primitiveType() : (unsigned short) CSSPrimitiveValue::CSS_UNKNOWN);
+    if (!(cssType > CSSPrimitiveValue::CSS_UNKNOWN && cssType <= CSSPrimitiveValue::CSS_PC))
+        return defaultValue;
+
+    if (cssType == CSSPrimitiveValue::CSS_PERCENTAGE) {
+        SVGStyledElement* element = static_cast<SVGStyledElement*>(item->element());
+        SVGElement* viewportElement = (element ? element->viewportElement() : 0);
+        if (viewportElement) {
+            float result = primitive->getFloatValue() / 100.0f;
+            return SVGLength::PercentageOfViewport(result, element, LengthModeOther);
+        }
+    }
+
+    return primitive->computeLengthFloat(const_cast<RenderStyle*>(item->style()));
+}
+
+}
+
+#endif // ENABLE(SVG)
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/style/SVGRenderStyle.h b/WebCore/rendering/style/SVGRenderStyle.h
new file mode 100644
index 0000000..5724621
--- /dev/null
+++ b/WebCore/rendering/style/SVGRenderStyle.h
@@ -0,0 +1,219 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005 Rob Buis <[email protected]>
+    Copyright (C) 2005, 2006 Apple Computer, Inc.
+
+     This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef SVGRenderStyle_h
+#define SVGRenderStyle_h
+
+#if ENABLE(SVG)
+#include "CSSValueList.h"
+#include "DataRef.h"
+#include "GraphicsTypes.h"
+#include "SVGPaint.h"
+#include "SVGRenderStyleDefs.h"
+
+#include <wtf/Platform.h>
+
+namespace WebCore {
+
+    class RenderObject;
+    class RenderStyle;
+
+    class SVGRenderStyle : public RefCounted<SVGRenderStyle> {    
+    public:
+        static PassRefPtr<SVGRenderStyle> create() { return adoptRef(new SVGRenderStyle); }
+        PassRefPtr<SVGRenderStyle> copy() const { return adoptRef(new SVGRenderStyle(*this));}
+        ~SVGRenderStyle();
+
+        bool inheritedNotEqual(const SVGRenderStyle*) const;
+        void inheritFrom(const SVGRenderStyle*);
+        
+        bool operator==(const SVGRenderStyle&) const;
+        bool operator!=(const SVGRenderStyle& o) const { return !(*this == o); }
+
+        // SVG CSS Properties
+        SVG_RS_DEFINE_ATTRIBUTE(EAlignmentBaseline, AlignmentBaseline, alignmentBaseline, AB_AUTO)
+        SVG_RS_DEFINE_ATTRIBUTE(EDominantBaseline, DominantBaseline, dominantBaseline, DB_AUTO)
+        SVG_RS_DEFINE_ATTRIBUTE(EBaselineShift, BaselineShift, baselineShift, BS_BASELINE)
+
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(LineCap, CapStyle, capStyle, ButtCap)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(WindRule, ClipRule, clipRule, RULE_NONZERO)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EColorInterpolation, ColorInterpolation, colorInterpolation, CI_SRGB)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EColorInterpolation, ColorInterpolationFilters, colorInterpolationFilters, CI_LINEARRGB)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EColorRendering, ColorRendering, colorRendering, CR_AUTO)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(WindRule, FillRule, fillRule, RULE_NONZERO)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EImageRendering, ImageRendering, imageRendering, IR_AUTO)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(LineJoin, JoinStyle, joinStyle, MiterJoin)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EPointerEvents, PointerEvents, pointerEvents, PE_VISIBLE_PAINTED)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EShapeRendering, ShapeRendering, shapeRendering, SR_AUTO)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(ETextAnchor, TextAnchor, textAnchor, TA_START)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(ETextRendering, TextRendering, textRendering, TR_AUTO)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EWritingMode, WritingMode, writingMode, WM_LRTB)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EGlyphOrientation, GlyphOrientationHorizontal, glyphOrientationHorizontal, GO_0DEG)
+        SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EGlyphOrientation, GlyphOrientationVertical, glyphOrientationVertical, GO_AUTO)
+
+        // SVG CSS Properties (using DataRef's)
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, fill, opacity, FillOpacity, fillOpacity, 1.0f)
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(SVGPaint, fill, paint, FillPaint, fillPaint, SVGPaint::defaultFill())
+
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, stroke, opacity, StrokeOpacity, strokeOpacity, 1.0f)
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(SVGPaint, stroke, paint, StrokePaint, strokePaint, SVGPaint::defaultStroke())
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(CSSValueList, stroke, dashArray, StrokeDashArray, strokeDashArray, 0)
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, stroke, miterLimit, StrokeMiterLimit, strokeMiterLimit, 4.0f)
+        
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(CSSValue, stroke, width, StrokeWidth, strokeWidth, 0)
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(CSSValue, stroke, dashOffset, StrokeDashOffset, strokeDashOffset, 0);
+
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(CSSValue, text, kerning, Kerning, kerning, 0)
+
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, stops, opacity, StopOpacity, stopOpacity, 1.0f)
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(Color, stops, color, StopColor, stopColor, Color(0, 0, 0))    
+
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, clip, clipPath, ClipPath, clipPath, String())
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, mask, maskElement, MaskElement, maskElement, String())
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, markers, startMarker, StartMarker, startMarker, String())
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, markers, midMarker, MidMarker, midMarker, String())
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, markers, endMarker, EndMarker, endMarker, String())
+
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, misc, filter, Filter, filter, String())
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, misc, floodOpacity, FloodOpacity, floodOpacity, 1.0f)
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(Color, misc, floodColor, FloodColor, floodColor, Color(0, 0, 0))
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(Color, misc, lightingColor, LightingColor, lightingColor, Color(255, 255, 255))
+        SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(CSSValue, misc, baselineShiftValue, BaselineShiftValue, baselineShiftValue, 0)
+
+        // convenience
+        bool hasStroke() const { return (strokePaint()->paintType() != SVGPaint::SVG_PAINTTYPE_NONE); }
+        bool hasFill() const { return (fillPaint()->paintType() != SVGPaint::SVG_PAINTTYPE_NONE); }
+
+        static float cssPrimitiveToLength(const RenderObject*, CSSValue*, float defaultValue = 0.0f);
+
+    protected:
+        // inherit
+        struct InheritedFlags {
+            bool operator==(const InheritedFlags& other) const
+            {
+                return (_colorRendering == other._colorRendering) &&
+                       (_imageRendering == other._imageRendering) &&
+                       (_shapeRendering == other._shapeRendering) &&
+                       (_textRendering == other._textRendering) &&
+                       (_clipRule == other._clipRule) &&
+                       (_fillRule == other._fillRule) &&
+                       (_capStyle == other._capStyle) &&
+                       (_joinStyle == other._joinStyle) &&
+                       (_textAnchor == other._textAnchor) &&
+                       (_colorInterpolation == other._colorInterpolation) &&
+                       (_colorInterpolationFilters == other._colorInterpolationFilters) &&
+                       (_pointerEvents == other._pointerEvents) &&
+                       (_writingMode == other._writingMode) &&
+                       (_glyphOrientationHorizontal == other._glyphOrientationHorizontal) &&
+                       (_glyphOrientationVertical == other._glyphOrientationVertical);
+            }
+
+            bool operator!=(const InheritedFlags& other) const
+            {
+                return !(*this == other);
+            }
+
+            unsigned _colorRendering : 2; // EColorRendering
+            unsigned _imageRendering : 2; // EImageRendering 
+            unsigned _shapeRendering : 2; // EShapeRendering 
+            unsigned _textRendering : 2; // ETextRendering
+            unsigned _clipRule : 1; // WindRule
+            unsigned _fillRule : 1; // WindRule
+            unsigned _capStyle : 2; // LineCap
+            unsigned _joinStyle : 2; // LineJoin
+            unsigned _textAnchor : 2; // ETextAnchor
+            unsigned _colorInterpolation : 2; // EColorInterpolation
+            unsigned _colorInterpolationFilters : 2; // EColorInterpolation
+            unsigned _pointerEvents : 4; // EPointerEvents
+            unsigned _writingMode : 3; // EWritingMode
+            unsigned _glyphOrientationHorizontal : 3; // EGlyphOrientation
+            unsigned _glyphOrientationVertical : 3; // EGlyphOrientation
+        } svg_inherited_flags;
+
+        // don't inherit
+        struct NonInheritedFlags {
+            // 32 bit non-inherited, don't add to the struct, or the operator will break.
+            bool operator==(const NonInheritedFlags &other) const { return _niflags == other._niflags; }
+            bool operator!=(const NonInheritedFlags &other) const { return _niflags != other._niflags; }
+
+            union {
+                struct {
+                    unsigned _alignmentBaseline : 4; // EAlignmentBaseline 
+                    unsigned _dominantBaseline : 4; // EDominantBaseline
+                    unsigned _baselineShift : 2; // EBaselineShift
+                    // 22 bits unused
+                } f;
+                uint32_t _niflags;
+            };
+        } svg_noninherited_flags;
+
+        // inherited attributes
+        DataRef<StyleFillData> fill;
+        DataRef<StyleStrokeData> stroke;
+        DataRef<StyleMarkerData> markers;
+        DataRef<StyleTextData> text;
+
+        // non-inherited attributes
+        DataRef<StyleStopData> stops;
+        DataRef<StyleClipData> clip;
+        DataRef<StyleMaskData> mask;
+        DataRef<StyleMiscData> misc;
+
+    private:
+        enum CreateDefaultType { CreateDefault };
+            
+        SVGRenderStyle();
+        SVGRenderStyle(const SVGRenderStyle&);
+        SVGRenderStyle(CreateDefaultType); // Used to create the default style.
+
+        void setBitDefaults()
+        {
+            svg_inherited_flags._clipRule = initialClipRule();
+            svg_inherited_flags._colorRendering = initialColorRendering();
+            svg_inherited_flags._fillRule = initialFillRule();
+            svg_inherited_flags._imageRendering = initialImageRendering();
+            svg_inherited_flags._shapeRendering = initialShapeRendering();
+            svg_inherited_flags._textRendering = initialTextRendering();
+            svg_inherited_flags._textAnchor = initialTextAnchor();
+            svg_inherited_flags._capStyle = initialCapStyle();
+            svg_inherited_flags._joinStyle = initialJoinStyle();
+            svg_inherited_flags._colorInterpolation = initialColorInterpolation();
+            svg_inherited_flags._colorInterpolationFilters = initialColorInterpolationFilters();
+            svg_inherited_flags._pointerEvents = initialPointerEvents();
+            svg_inherited_flags._writingMode = initialWritingMode();
+            svg_inherited_flags._glyphOrientationHorizontal = initialGlyphOrientationHorizontal();
+            svg_inherited_flags._glyphOrientationVertical = initialGlyphOrientationVertical();
+
+            svg_noninherited_flags._niflags = 0;
+            svg_noninherited_flags.f._alignmentBaseline = initialAlignmentBaseline();
+            svg_noninherited_flags.f._dominantBaseline = initialDominantBaseline();
+            svg_noninherited_flags.f._baselineShift = initialBaselineShift();
+        }
+    };
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // SVGRenderStyle_h
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/style/SVGRenderStyleDefs.cpp b/WebCore/rendering/style/SVGRenderStyleDefs.cpp
new file mode 100644
index 0000000..f5faad3
--- /dev/null
+++ b/WebCore/rendering/style/SVGRenderStyleDefs.cpp
@@ -0,0 +1,218 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005, 2007 Rob Buis <[email protected]>
+
+    Based on khtml code by:
+    Copyright (C) 1999 Antti Koivisto ([email protected])
+    Copyright (C) 1999-2003 Lars Knoll ([email protected])
+    Copyright (C) 2002-2003 Dirk Mueller ([email protected])
+    Copyright (C) 2002 Apple Computer, Inc.
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#if ENABLE(SVG)
+#include "SVGRenderStyleDefs.h"
+
+#include "RenderStyle.h"
+#include "SVGRenderStyle.h"
+
+using namespace WebCore;
+
+StyleFillData::StyleFillData()
+{
+    paint = SVGRenderStyle::initialFillPaint();
+    opacity = SVGRenderStyle::initialFillOpacity();
+}
+
+StyleFillData::StyleFillData(const StyleFillData& other)
+    : RefCounted<StyleFillData>()
+{
+    paint = other.paint;
+    opacity = other.opacity;
+}
+
+bool StyleFillData::operator==(const StyleFillData &other) const
+{
+    if (opacity != other.opacity)
+        return false;
+
+    if (!paint || !other.paint)
+        return paint == other.paint;
+
+    if (paint->paintType() != other.paint->paintType())
+        return false;
+
+    if (paint->paintType() == SVGPaint::SVG_PAINTTYPE_URI)
+        return paint->uri() == other.paint->uri();
+
+    if (paint->paintType() == SVGPaint::SVG_PAINTTYPE_RGBCOLOR)
+        return paint->color() == other.paint->color();
+
+    return paint == other.paint;
+}
+
+StyleStrokeData::StyleStrokeData()
+{
+    width = SVGRenderStyle::initialStrokeWidth();
+    paint = SVGRenderStyle::initialStrokePaint();
+    opacity = SVGRenderStyle::initialStrokeOpacity();
+    miterLimit = SVGRenderStyle::initialStrokeMiterLimit();
+    dashOffset = SVGRenderStyle::initialStrokeDashOffset();
+    dashArray = SVGRenderStyle::initialStrokeDashArray();
+}
+
+StyleStrokeData::StyleStrokeData(const StyleStrokeData& other)
+    : RefCounted<StyleStrokeData>()
+{
+    width = other.width;
+    paint = other.paint;
+    opacity = other.opacity;
+    miterLimit = other.miterLimit;
+    dashOffset = other.dashOffset;
+    dashArray = other.dashArray;
+}
+
+bool StyleStrokeData::operator==(const StyleStrokeData &other) const
+{
+    return (paint == other.paint) &&
+           (width == other.width) &&
+           (opacity == other.opacity) &&
+           (miterLimit == other.miterLimit) &&
+           (dashOffset == other.dashOffset) &&
+           (dashArray == other.dashArray);
+}
+
+StyleStopData::StyleStopData()
+{
+    color = SVGRenderStyle::initialStopColor();
+    opacity = SVGRenderStyle::initialStopOpacity();
+}
+
+StyleStopData::StyleStopData(const StyleStopData& other)
+    : RefCounted<StyleStopData>()
+{
+    color = other.color;
+    opacity = other.opacity;
+}
+
+bool StyleStopData::operator==(const StyleStopData &other) const
+{
+    return (color == other.color) &&
+           (opacity == other.opacity);
+}
+
+StyleTextData::StyleTextData()
+{
+    kerning = SVGRenderStyle::initialKerning();
+}
+
+StyleTextData::StyleTextData(const StyleTextData& other)
+    : RefCounted<StyleTextData>()
+{
+    kerning = other.kerning;
+}
+
+bool StyleTextData::operator==(const StyleTextData& other) const
+{
+    return kerning == other.kerning;
+}
+
+StyleClipData::StyleClipData()
+{
+    clipPath = SVGRenderStyle::initialClipPath();
+}
+
+StyleClipData::StyleClipData(const StyleClipData& other)
+    : RefCounted<StyleClipData>()
+{
+    clipPath = other.clipPath;
+}
+
+bool StyleClipData::operator==(const StyleClipData &other) const
+{
+    return (clipPath == other.clipPath);
+}
+
+StyleMaskData::StyleMaskData()
+{
+    maskElement = SVGRenderStyle::initialMaskElement();
+}
+
+StyleMaskData::StyleMaskData(const StyleMaskData& other)
+    : RefCounted<StyleMaskData>()
+{
+    maskElement = other.maskElement;
+}
+
+bool StyleMaskData::operator==(const StyleMaskData &other) const
+{
+    return (maskElement == other.maskElement);
+}
+
+StyleMarkerData::StyleMarkerData()
+{
+    startMarker = SVGRenderStyle::initialStartMarker();
+    midMarker = SVGRenderStyle::initialMidMarker();
+    endMarker = SVGRenderStyle::initialEndMarker();
+}
+
+StyleMarkerData::StyleMarkerData(const StyleMarkerData& other)
+    : RefCounted<StyleMarkerData>()
+{
+    startMarker = other.startMarker;
+    midMarker = other.midMarker;
+    endMarker = other.endMarker;
+}
+
+bool StyleMarkerData::operator==(const StyleMarkerData &other) const
+{
+    return (startMarker == other.startMarker && midMarker == other.midMarker && endMarker == other.endMarker);
+}
+
+StyleMiscData::StyleMiscData()
+{
+    floodColor = SVGRenderStyle::initialFloodColor();
+    floodOpacity = SVGRenderStyle::initialFloodOpacity();
+    lightingColor = SVGRenderStyle::initialLightingColor();
+    baselineShiftValue = SVGRenderStyle::initialBaselineShiftValue();
+}
+
+StyleMiscData::StyleMiscData(const StyleMiscData& other)
+    : RefCounted<StyleMiscData>()
+{
+    filter = other.filter;
+    floodColor = other.floodColor;
+    floodOpacity = other.floodOpacity;
+    lightingColor = other.lightingColor;
+    baselineShiftValue = other.baselineShiftValue;
+}
+
+bool StyleMiscData::operator==(const StyleMiscData &other) const
+{
+    return filter == other.filter
+           && floodOpacity == other.floodOpacity
+           && floodColor == other.floodColor
+           && lightingColor == other.lightingColor
+           && baselineShiftValue == other.baselineShiftValue;
+}
+
+#endif // ENABLE(SVG)
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/style/SVGRenderStyleDefs.h b/WebCore/rendering/style/SVGRenderStyleDefs.h
new file mode 100644
index 0000000..12a70d3
--- /dev/null
+++ b/WebCore/rendering/style/SVGRenderStyleDefs.h
@@ -0,0 +1,297 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+                  2004, 2005 Rob Buis <[email protected]>
+
+    Based on khtml code by:
+    Copyright (C) 2000-2003 Lars Knoll ([email protected])
+              (C) 2000 Antti Koivisto ([email protected])
+              (C) 2000-2003 Dirk Mueller ([email protected])
+              (C) 2002-2003 Apple Computer, Inc.
+
+    This file is part of the KDE project
+
+    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, or (at your option) any later version.
+
+    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., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef SVGRenderStyleDefs_h
+#define SVGRenderStyleDefs_h
+
+#if ENABLE(SVG)
+#include "Color.h"
+#include "Path.h"
+#include "PlatformString.h"
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+// Helper macros for 'SVGRenderStyle'
+#define SVG_RS_DEFINE_ATTRIBUTE(Data, Type, Name, Initial) \
+    void set##Type(Data val) { svg_noninherited_flags.f._##Name = val; } \
+    Data Name() const { return (Data) svg_noninherited_flags.f._##Name; } \
+    static Data initial##Type() { return Initial; }
+
+#define SVG_RS_DEFINE_ATTRIBUTE_INHERITED(Data, Type, Name, Initial) \
+    void set##Type(Data val) { svg_inherited_flags._##Name = val; } \
+    Data Name() const { return (Data) svg_inherited_flags._##Name; } \
+    static Data initial##Type() { return Initial; }
+
+// "Helper" macros for SVG's RenderStyle properties
+// FIXME: These are impossible to work with or debug.
+#define SVG_RS_DEFINE_ATTRIBUTE_DATAREF(Data, Group, Variable, Type, Name) \
+    Data Name() const { return Group->Variable; } \
+    void set##Type(Data obj) { SVG_RS_SET_VARIABLE(Group, Variable, obj) }
+
+#define SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(Data, Group, Variable, Type, Name, Initial) \
+    SVG_RS_DEFINE_ATTRIBUTE_DATAREF(Data, Group, Variable, Type, Name) \
+    static Data initial##Type() { return Initial; }
+
+#define SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(Data, Group, Variable, Type, Name, Initial) \
+    Data* Name() const { return Group->Variable.get(); } \
+    void set##Type(PassRefPtr<Data> obj) { \
+        if(!(Group->Variable == obj)) \
+            Group.access()->Variable = obj; \
+    } \
+    static Data* initial##Type() { return Initial; }
+
+#define SVG_RS_SET_VARIABLE(Group, Variable, Value) \
+    if(!(Group->Variable == Value)) \
+        Group.access()->Variable = Value;
+
+namespace WebCore {
+
+    enum EBaselineShift {
+        BS_BASELINE, BS_SUB, BS_SUPER, BS_LENGTH
+    };
+
+    enum ETextAnchor {
+        TA_START, TA_MIDDLE, TA_END
+    };
+
+    enum EColorInterpolation {
+        CI_AUTO, CI_SRGB, CI_LINEARRGB
+    };
+
+    enum EColorRendering {
+        CR_AUTO, CR_OPTIMIZESPEED, CR_OPTIMIZEQUALITY
+    };
+    
+    enum EImageRendering {
+        IR_AUTO, IR_OPTIMIZESPEED, IR_OPTIMIZEQUALITY
+    };
+
+    enum EShapeRendering {
+        SR_AUTO, SR_OPTIMIZESPEED, SR_CRISPEDGES, SR_GEOMETRICPRECISION
+    };
+
+    enum ETextRendering {
+        TR_AUTO, TR_OPTIMIZESPEED, TR_OPTIMIZELEGIBILITY, TR_GEOMETRICPRECISION
+    };
+
+    enum EWritingMode {
+        WM_LRTB, WM_LR, WM_RLTB, WM_RL, WM_TBRL, WM_TB
+    };
+
+    enum EGlyphOrientation {
+        GO_0DEG, GO_90DEG, GO_180DEG, GO_270DEG, GO_AUTO
+    };
+
+    enum EAlignmentBaseline {
+        AB_AUTO, AB_BASELINE, AB_BEFORE_EDGE, AB_TEXT_BEFORE_EDGE,
+        AB_MIDDLE, AB_CENTRAL, AB_AFTER_EDGE, AB_TEXT_AFTER_EDGE,
+        AB_IDEOGRAPHIC, AB_ALPHABETIC, AB_HANGING, AB_MATHEMATICAL
+    };
+
+    enum EDominantBaseline {
+        DB_AUTO, DB_USE_SCRIPT, DB_NO_CHANGE, DB_RESET_SIZE,
+        DB_IDEOGRAPHIC, DB_ALPHABETIC, DB_HANGING, DB_MATHEMATICAL,
+        DB_CENTRAL, DB_MIDDLE, DB_TEXT_AFTER_EDGE, DB_TEXT_BEFORE_EDGE
+    };
+
+    enum EPointerEvents {
+        PE_NONE, PE_STROKE, PE_FILL, PE_PAINTED, PE_VISIBLE,
+        PE_VISIBLE_STROKE, PE_VISIBLE_FILL, PE_VISIBLE_PAINTED, PE_ALL
+    };
+    
+    class CSSValue;
+    class CSSValueList;
+    class SVGPaint;
+
+    // Inherited/Non-Inherited Style Datastructures
+    class StyleFillData : public RefCounted<StyleFillData> {
+    public:
+        static PassRefPtr<StyleFillData> create() { return adoptRef(new StyleFillData); }
+        PassRefPtr<StyleFillData> copy() const { return adoptRef(new StyleFillData(*this)); }
+        
+        bool operator==(const StyleFillData &other) const;
+        bool operator!=(const StyleFillData &other) const
+        {
+            return !(*this == other);
+        }
+
+        float opacity;
+        RefPtr<SVGPaint> paint;
+
+    private:
+        StyleFillData();
+        StyleFillData(const StyleFillData&);
+    };
+
+    class StyleStrokeData : public RefCounted<StyleStrokeData> {
+    public:
+        static PassRefPtr<StyleStrokeData> create() { return adoptRef(new StyleStrokeData); }
+        PassRefPtr<StyleStrokeData> copy() const { return adoptRef(new StyleStrokeData(*this)); }
+
+        bool operator==(const StyleStrokeData&) const;
+        bool operator!=(const StyleStrokeData& other) const
+        {
+            return !(*this == other);
+        }
+
+        float opacity;
+        float miterLimit;
+
+        RefPtr<CSSValue> width;
+        RefPtr<CSSValue> dashOffset;
+
+        RefPtr<SVGPaint> paint;
+        RefPtr<CSSValueList> dashArray;
+
+    private:        
+        StyleStrokeData();
+        StyleStrokeData(const StyleStrokeData&);
+    };
+
+    class StyleStopData : public RefCounted<StyleStopData> {
+    public:
+        static PassRefPtr<StyleStopData> create() { return adoptRef(new StyleStopData); }
+        PassRefPtr<StyleStopData> copy() const { return adoptRef(new StyleStopData(*this)); }
+
+        bool operator==(const StyleStopData &other) const;
+        bool operator!=(const StyleStopData &other) const
+        {
+            return !(*this == other);
+        }
+
+        float opacity;
+        Color color;
+
+    private:        
+        StyleStopData();
+        StyleStopData(const StyleStopData&);
+    };
+
+    class StyleTextData : public RefCounted<StyleTextData> {
+    public:
+        static PassRefPtr<StyleTextData> create() { return adoptRef(new StyleTextData); }
+        PassRefPtr<StyleTextData> copy() const { return adoptRef(new StyleTextData(*this)); }
+        
+        bool operator==(const StyleTextData& other) const;
+        bool operator!=(const StyleTextData& other) const
+        {
+            return !(*this == other);
+        }
+
+        RefPtr<CSSValue> kerning;
+
+    private:
+        StyleTextData();
+        StyleTextData(const StyleTextData& other);
+    };
+
+    class StyleClipData : public RefCounted<StyleClipData> {
+    public:
+        static PassRefPtr<StyleClipData> create() { return adoptRef(new StyleClipData); }
+        PassRefPtr<StyleClipData> copy() const { return adoptRef(new StyleClipData(*this)); }
+
+        bool operator==(const StyleClipData &other) const;
+        bool operator!=(const StyleClipData &other) const
+        {
+            return !(*this == other);
+        }
+
+        String clipPath;
+
+    private:
+        StyleClipData();
+        StyleClipData(const StyleClipData&);
+    };
+
+    class StyleMaskData : public RefCounted<StyleMaskData> {
+    public:
+        static PassRefPtr<StyleMaskData> create() { return adoptRef(new StyleMaskData); }
+        PassRefPtr<StyleMaskData> copy() const { return adoptRef(new StyleMaskData(*this)); }
+
+        bool operator==(const StyleMaskData &other) const;
+        bool operator!=(const StyleMaskData &other) const { return !(*this == other); }
+
+        String maskElement;
+
+    private:        
+        StyleMaskData();
+        StyleMaskData(const StyleMaskData&);
+    };
+
+    class StyleMarkerData : public RefCounted<StyleMarkerData> {
+    public:
+        static PassRefPtr<StyleMarkerData> create() { return adoptRef(new StyleMarkerData); }
+        PassRefPtr<StyleMarkerData> copy() const { return adoptRef(new StyleMarkerData(*this)); }
+
+        bool operator==(const StyleMarkerData &other) const;
+        bool operator!=(const StyleMarkerData &other) const
+        {
+            return !(*this == other);
+        }
+
+        String startMarker;
+        String midMarker;
+        String endMarker;
+
+    private:
+        StyleMarkerData();
+        StyleMarkerData(const StyleMarkerData&);
+    };
+
+    // Note : the rule for this class is, *no inheritance* of these props
+    class StyleMiscData : public RefCounted<StyleMiscData> {
+    public:
+        static PassRefPtr<StyleMiscData> create() { return adoptRef(new StyleMiscData); }
+        PassRefPtr<StyleMiscData> copy() const { return adoptRef(new StyleMiscData(*this)); }
+
+        bool operator==(const StyleMiscData &other) const;
+        bool operator!=(const StyleMiscData &other) const
+        {
+            return !(*this == other);
+        }
+
+        String filter;
+        Color floodColor;
+        float floodOpacity;
+
+        Color lightingColor;
+
+        // non-inherited text stuff lives here not in StyleTextData.
+        RefPtr<CSSValue> baselineShiftValue;
+
+    private:
+        StyleMiscData();
+        StyleMiscData(const StyleMiscData&);
+    };
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // SVGRenderStyleDefs_h
+
+// vim:ts=4:noet
diff --git a/WebCore/rendering/style/ScaleTransformOperation.cpp b/WebCore/rendering/style/ScaleTransformOperation.cpp
new file mode 100644
index 0000000..49a8fd8
--- /dev/null
+++ b/WebCore/rendering/style/ScaleTransformOperation.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ScaleTransformOperation.h"
+
+namespace WebCore {
+
+PassRefPtr<TransformOperation> ScaleTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
+{
+    if (from && !from->isSameType(*this))
+        return this;
+    
+    if (blendToIdentity)
+        return ScaleTransformOperation::create(m_x + (1. - m_x) * progress, m_y + (1. - m_y) * progress, m_type);
+    
+    const ScaleTransformOperation* fromOp = static_cast<const ScaleTransformOperation*>(from);
+    double fromX = fromOp ? fromOp->m_x : 1.;
+    double fromY = fromOp ? fromOp->m_y : 1.;
+    return ScaleTransformOperation::create(fromX + (m_x - fromX) * progress, fromY + (m_y - fromY) * progress, m_type);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/ScaleTransformOperation.h b/WebCore/rendering/style/ScaleTransformOperation.h
new file mode 100644
index 0000000..787f067
--- /dev/null
+++ b/WebCore/rendering/style/ScaleTransformOperation.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ScaleTransformOperation_h
+#define ScaleTransformOperation_h
+
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class ScaleTransformOperation : public TransformOperation {
+public:
+    static PassRefPtr<ScaleTransformOperation> create(double sx, double sy, OperationType type)
+    {
+        return adoptRef(new ScaleTransformOperation(sx, sy, type));
+    }
+
+    virtual bool isIdentity() const { return m_x == 1 &&  m_y == 1; }
+    virtual OperationType getOperationType() const { return m_type; }
+    virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
+
+    virtual bool operator==(const TransformOperation& o) const
+    {
+        if (!isSameType(o))
+            return false;
+        const ScaleTransformOperation* s = static_cast<const ScaleTransformOperation*>(&o);
+        return m_x == s->m_x && m_y == s->m_y;
+    }
+
+    virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
+    {
+        transform.scale(m_x, m_y);
+        return false;
+    }
+
+    virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
+
+private:
+    ScaleTransformOperation(double sx, double sy, OperationType type)
+        : m_x(sx)
+        , m_y(sy)
+        , m_type(type)
+    {
+    }
+        
+    double m_x;
+    double m_y;
+    OperationType m_type;
+};
+
+} // namespace WebCore
+
+#endif // ScaleTransformOperation_h
diff --git a/WebCore/rendering/style/ShadowData.cpp b/WebCore/rendering/style/ShadowData.cpp
new file mode 100644
index 0000000..75fb9dc
--- /dev/null
+++ b/WebCore/rendering/style/ShadowData.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ShadowData.h"
+
+namespace WebCore {
+
+ShadowData::ShadowData(const ShadowData& o)
+    : x(o.x)
+    , y(o.y)
+    , blur(o.blur)
+    , color(o.color)
+{
+    next = o.next ? new ShadowData(*o.next) : 0;
+}
+
+bool ShadowData::operator==(const ShadowData& o) const
+{
+    if ((next && !o.next) || (!next && o.next) ||
+        (next && o.next && *next != *o.next))
+        return false;
+    
+    return x == o.x && y == o.y && blur == o.blur && color == o.color;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/ShadowData.h b/WebCore/rendering/style/ShadowData.h
new file mode 100644
index 0000000..dac2b18
--- /dev/null
+++ b/WebCore/rendering/style/ShadowData.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ShadowData_h
+#define ShadowData_h
+
+#include "Color.h"
+
+namespace WebCore {
+
+// This struct holds information about shadows for the text-shadow and box-shadow properties.
+
+struct ShadowData {
+    ShadowData()
+        : x(0)
+        , y(0)
+        , blur(0)
+        , next(0)
+    {
+    }
+
+    ShadowData(int _x, int _y, int _blur, const Color& _color)
+        : x(_x)
+        , y(_y)
+        , blur(_blur)
+        , color(_color)
+        , next(0)
+    {
+    }
+
+    ShadowData(const ShadowData& o);
+
+    ~ShadowData() { delete next; }
+
+    bool operator==(const ShadowData& o) const;
+    bool operator!=(const ShadowData& o) const
+    {
+        return !(*this == o);
+    }
+    
+    int x;
+    int y;
+    int blur;
+    Color color;
+    ShadowData* next;
+};
+
+} // namespace WebCore
+
+#endif // ShadowData_h
diff --git a/WebCore/rendering/style/SkewTransformOperation.cpp b/WebCore/rendering/style/SkewTransformOperation.cpp
new file mode 100644
index 0000000..2a430e9
--- /dev/null
+++ b/WebCore/rendering/style/SkewTransformOperation.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "SkewTransformOperation.h"
+
+namespace WebCore {
+
+PassRefPtr<TransformOperation> SkewTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
+{
+    if (from && !from->isSameType(*this))
+        return this;
+    
+    if (blendToIdentity)
+        return SkewTransformOperation::create(m_angleX - m_angleX * progress, m_angleY - m_angleY * progress, m_type);
+    
+    const SkewTransformOperation* fromOp = static_cast<const SkewTransformOperation*>(from);
+    double fromAngleX = fromOp ? fromOp->m_angleX : 0;
+    double fromAngleY = fromOp ? fromOp->m_angleY : 0;
+    return SkewTransformOperation::create(fromAngleX + (m_angleX - fromAngleX) * progress, fromAngleY + (m_angleY - fromAngleY) * progress, m_type);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/SkewTransformOperation.h b/WebCore/rendering/style/SkewTransformOperation.h
new file mode 100644
index 0000000..a7879e8
--- /dev/null
+++ b/WebCore/rendering/style/SkewTransformOperation.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SkewTransformOperation_h
+#define SkewTransformOperation_h
+
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class SkewTransformOperation : public TransformOperation {
+public:
+    static PassRefPtr<SkewTransformOperation> create(double angleX, double angleY, OperationType type)
+    {
+        return adoptRef(new SkewTransformOperation(angleX, angleY, type));
+    }
+
+    virtual bool isIdentity() const { return m_angleX == 0 && m_angleY == 0; }
+    virtual OperationType getOperationType() const { return m_type; }
+    virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
+
+    virtual bool operator==(const TransformOperation& o) const
+    {
+        if (!isSameType(o))
+            return false;
+        const SkewTransformOperation* s = static_cast<const SkewTransformOperation*>(&o);
+        return m_angleX == s->m_angleX && m_angleY == s->m_angleY;
+    }
+
+    virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
+    {
+        transform.skew(m_angleX, m_angleY);
+        return false;
+    }
+
+    virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
+    
+private:
+    SkewTransformOperation(double angleX, double angleY, OperationType type)
+        : m_angleX(angleX)
+        , m_angleY(angleY)
+        , m_type(type)
+    {
+    }
+    
+    double m_angleX;
+    double m_angleY;
+    OperationType m_type;
+};
+
+} // namespace WebCore
+
+#endif // SkewTransformOperation_h
diff --git a/WebCore/rendering/style/StyleBackgroundData.cpp b/WebCore/rendering/style/StyleBackgroundData.cpp
new file mode 100644
index 0000000..68a9ddd
--- /dev/null
+++ b/WebCore/rendering/style/StyleBackgroundData.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleBackgroundData.h"
+
+#include "RenderStyleConstants.h"
+
+namespace WebCore {
+
+StyleBackgroundData::StyleBackgroundData()
+    : m_background(BackgroundFillLayer)
+{
+}
+
+StyleBackgroundData::StyleBackgroundData(const StyleBackgroundData& o)
+    : RefCounted<StyleBackgroundData>()
+    , m_background(o.m_background)
+    , m_color(o.m_color)
+    , m_outline(o.m_outline)
+{
+}
+
+bool StyleBackgroundData::operator==(const StyleBackgroundData& o) const
+{
+    return m_background == o.m_background && m_color == o.m_color && m_outline == o.m_outline;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleBackgroundData.h b/WebCore/rendering/style/StyleBackgroundData.h
new file mode 100644
index 0000000..8f2da36
--- /dev/null
+++ b/WebCore/rendering/style/StyleBackgroundData.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleBackgroundData_h
+#define StyleBackgroundData_h
+
+#include "Color.h"
+#include "FillLayer.h"
+#include "OutlineValue.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class StyleBackgroundData : public RefCounted<StyleBackgroundData> {
+public:
+    static PassRefPtr<StyleBackgroundData> create() { return adoptRef(new StyleBackgroundData); }
+    PassRefPtr<StyleBackgroundData> copy() const { return adoptRef(new StyleBackgroundData(*this)); }
+    ~StyleBackgroundData() { }
+
+    bool operator==(const StyleBackgroundData& o) const;
+    bool operator!=(const StyleBackgroundData& o) const
+    {
+        return !(*this == o);
+    }
+
+    FillLayer m_background;
+    Color m_color;
+    OutlineValue m_outline;
+
+private:
+    StyleBackgroundData();
+    StyleBackgroundData(const StyleBackgroundData&);    
+};
+
+} // namespace WebCore
+
+#endif // StyleBackgroundData_h
diff --git a/WebCore/rendering/style/StyleBoxData.cpp b/WebCore/rendering/style/StyleBoxData.cpp
new file mode 100644
index 0000000..d9734d1
--- /dev/null
+++ b/WebCore/rendering/style/StyleBoxData.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleBoxData.h"
+
+#include "RenderStyle.h"
+#include "RenderStyleConstants.h"
+
+namespace WebCore {
+
+StyleBoxData::StyleBoxData()
+    : z_index(0)
+    , z_auto(true)
+    , boxSizing(CONTENT_BOX)
+{
+    // Initialize our min/max widths/heights.
+    min_width = min_height = RenderStyle::initialMinSize();
+    max_width = max_height = RenderStyle::initialMaxSize();
+}
+
+StyleBoxData::StyleBoxData(const StyleBoxData& o)
+    : RefCounted<StyleBoxData>()
+    , width(o.width)
+    , height(o.height)
+    , min_width(o.min_width)
+    , max_width(o.max_width)
+    , min_height(o.min_height)
+    , max_height(o.max_height)
+    , z_index(o.z_index)
+    , z_auto(o.z_auto)
+    , boxSizing(o.boxSizing)
+{
+}
+
+bool StyleBoxData::operator==(const StyleBoxData& o) const
+{
+    return width == o.width &&
+           height == o.height &&
+           min_width == o.min_width &&
+           max_width == o.max_width &&
+           min_height == o.min_height &&
+           max_height == o.max_height &&
+           z_index == o.z_index &&
+           z_auto == o.z_auto &&
+           boxSizing == o.boxSizing;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleBoxData.h b/WebCore/rendering/style/StyleBoxData.h
new file mode 100644
index 0000000..a5bd2ff
--- /dev/null
+++ b/WebCore/rendering/style/StyleBoxData.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleBoxData_h
+#define StyleBoxData_h
+
+#include "Length.h"
+#include <wtf/RefCounted.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class StyleBoxData : public RefCounted<StyleBoxData> {
+public:
+    static PassRefPtr<StyleBoxData> create() { return adoptRef(new StyleBoxData); }
+    PassRefPtr<StyleBoxData> copy() const { return adoptRef(new StyleBoxData(*this)); }
+
+    bool operator==(const StyleBoxData& o) const;
+    bool operator!=(const StyleBoxData& o) const
+    {
+        return !(*this == o);
+    }
+
+    Length width;
+    Length height;
+
+    Length min_width;
+    Length max_width;
+
+    Length min_height;
+    Length max_height;
+
+    Length vertical_align;
+
+    int z_index;
+    bool z_auto : 1;
+    unsigned boxSizing : 1; // EBoxSizing
+    
+private:
+    StyleBoxData();
+    StyleBoxData(const StyleBoxData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleBoxData_h
diff --git a/WebCore/rendering/style/StyleCachedImage.cpp b/WebCore/rendering/style/StyleCachedImage.cpp
new file mode 100644
index 0000000..17ebce9
--- /dev/null
+++ b/WebCore/rendering/style/StyleCachedImage.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleCachedImage.h"
+
+#include "CachedImage.h"
+#include "RenderObject.h"
+
+namespace WebCore {
+
+PassRefPtr<CSSValue> StyleCachedImage::cssValue()
+{
+    return CSSPrimitiveValue::create(m_image->url(), CSSPrimitiveValue::CSS_URI);
+}
+
+bool StyleCachedImage::canRender(float multiplier) const
+{
+    return m_image->canRender(multiplier);
+}
+
+bool StyleCachedImage::isLoaded() const
+{
+    return m_image->isLoaded();
+}
+
+bool StyleCachedImage::errorOccurred() const
+{
+    return m_image->errorOccurred();
+}
+
+IntSize StyleCachedImage::imageSize(const RenderObject* /*renderer*/, float multiplier) const
+{
+    return m_image->imageSize(multiplier);
+}
+
+bool StyleCachedImage::imageHasRelativeWidth() const
+{
+    return m_image->imageHasRelativeWidth();
+}
+
+bool StyleCachedImage::imageHasRelativeHeight() const
+{
+    return m_image->imageHasRelativeHeight();
+}
+
+bool StyleCachedImage::usesImageContainerSize() const
+{
+    return m_image->usesImageContainerSize();
+}
+
+void StyleCachedImage::setImageContainerSize(const IntSize& size)
+{
+    return m_image->setImageContainerSize(size);
+}
+
+void StyleCachedImage::addClient(RenderObject* renderer)
+{
+    return m_image->addClient(renderer);
+}
+
+void StyleCachedImage::removeClient(RenderObject* renderer)
+{
+    return m_image->removeClient(renderer);
+}
+
+Image* StyleCachedImage::image(RenderObject* renderer, const IntSize&) const
+{
+    return m_image->image();
+}
+
+}
diff --git a/WebCore/rendering/style/StyleCachedImage.h b/WebCore/rendering/style/StyleCachedImage.h
new file mode 100644
index 0000000..3d22868
--- /dev/null
+++ b/WebCore/rendering/style/StyleCachedImage.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleCachedImage_h
+#define StyleCachedImage_h
+
+#include "CachedResourceHandle.h"
+#include "StyleImage.h"
+
+namespace WebCore {
+
+class CachedImage;
+
+class StyleCachedImage : public StyleImage {
+public:
+    static PassRefPtr<StyleCachedImage> create(CachedImage* image) { return adoptRef(new StyleCachedImage(image)); }
+    virtual WrappedImagePtr data() const { return m_image.get(); }
+
+    virtual bool isCachedImage() const { return true; }
+    
+    virtual PassRefPtr<CSSValue> cssValue();
+    
+    CachedImage* cachedImage() const { return m_image.get(); }
+
+    virtual bool canRender(float multiplier) const;
+    virtual bool isLoaded() const;
+    virtual bool errorOccurred() const;
+    virtual IntSize imageSize(const RenderObject*, float multiplier) const;
+    virtual bool imageHasRelativeWidth() const;
+    virtual bool imageHasRelativeHeight() const;
+    virtual bool usesImageContainerSize() const;
+    virtual void setImageContainerSize(const IntSize&);
+    virtual void addClient(RenderObject*);
+    virtual void removeClient(RenderObject*);
+    virtual Image* image(RenderObject*, const IntSize&) const;
+    
+private:
+    StyleCachedImage(CachedImage* image)
+        : m_image(image)
+    {
+    }
+    
+    CachedResourceHandle<CachedImage> m_image;
+};
+
+}
+#endif
diff --git a/WebCore/rendering/style/StyleDashboardRegion.h b/WebCore/rendering/style/StyleDashboardRegion.h
new file mode 100644
index 0000000..bbb0cda
--- /dev/null
+++ b/WebCore/rendering/style/StyleDashboardRegion.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleDashboardRegion_h
+#define StyleDashboardRegion_h
+#if ENABLE(DASHBOARD_SUPPORT)
+
+#include "LengthBox.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+// Dashboard region attributes. Not inherited.
+
+struct StyleDashboardRegion {
+    String label;
+    LengthBox offset;
+    int type;
+
+    enum {
+        None,
+        Circle,
+        Rectangle
+    };
+
+    bool operator==(const StyleDashboardRegion& o) const
+    {
+        return type == o.type && offset == o.offset && label == o.label;
+    }
+
+    bool operator!=(const StyleDashboardRegion& o) const
+    {
+        return !(*this == o);
+    }
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(DASHBOARD_SUPPORT)
+#endif // StyleDashboardRegion_h
diff --git a/WebCore/rendering/style/StyleFlexibleBoxData.cpp b/WebCore/rendering/style/StyleFlexibleBoxData.cpp
new file mode 100644
index 0000000..7c00080
--- /dev/null
+++ b/WebCore/rendering/style/StyleFlexibleBoxData.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleFlexibleBoxData.h"
+
+#include "RenderStyle.h"
+
+namespace WebCore {
+
+StyleFlexibleBoxData::StyleFlexibleBoxData()
+    : flex(RenderStyle::initialBoxFlex())
+    , flex_group(RenderStyle::initialBoxFlexGroup())
+    , ordinal_group(RenderStyle::initialBoxOrdinalGroup())
+    , align(RenderStyle::initialBoxAlign())
+    , pack(RenderStyle::initialBoxPack())
+    , orient(RenderStyle::initialBoxOrient())
+    , lines(RenderStyle::initialBoxLines())
+{
+}
+
+StyleFlexibleBoxData::StyleFlexibleBoxData(const StyleFlexibleBoxData& o)
+    : RefCounted<StyleFlexibleBoxData>()
+    , flex(o.flex)
+    , flex_group(o.flex_group)
+    , ordinal_group(o.ordinal_group)
+    , align(o.align)
+    , pack(o.pack)
+    , orient(o.orient)
+    , lines(o.lines)
+{
+}
+
+bool StyleFlexibleBoxData::operator==(const StyleFlexibleBoxData& o) const
+{
+    return flex == o.flex && flex_group == o.flex_group &&
+           ordinal_group == o.ordinal_group && align == o.align &&
+           pack == o.pack && orient == o.orient && lines == o.lines;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleFlexibleBoxData.h b/WebCore/rendering/style/StyleFlexibleBoxData.h
new file mode 100644
index 0000000..f5d5e74
--- /dev/null
+++ b/WebCore/rendering/style/StyleFlexibleBoxData.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleFlexibleBoxData_h
+#define StyleFlexibleBoxData_h
+
+#include <wtf/RefCounted.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class StyleFlexibleBoxData : public RefCounted<StyleFlexibleBoxData> {
+public:
+    static PassRefPtr<StyleFlexibleBoxData> create() { return adoptRef(new StyleFlexibleBoxData); }
+    PassRefPtr<StyleFlexibleBoxData> copy() const { return adoptRef(new StyleFlexibleBoxData(*this)); }
+    
+    bool operator==(const StyleFlexibleBoxData& o) const;
+    bool operator!=(const StyleFlexibleBoxData& o) const
+    {
+        return !(*this == o);
+    }
+
+    float flex;
+    unsigned int flex_group;
+    unsigned int ordinal_group;
+
+    unsigned align : 3; // EBoxAlignment
+    unsigned pack: 3; // EBoxAlignment
+    unsigned orient: 1; // EBoxOrient
+    unsigned lines : 1; // EBoxLines
+    
+private:
+    StyleFlexibleBoxData();
+    StyleFlexibleBoxData(const StyleFlexibleBoxData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleFlexibleBoxData_h
diff --git a/WebCore/rendering/style/StyleGeneratedImage.cpp b/WebCore/rendering/style/StyleGeneratedImage.cpp
new file mode 100644
index 0000000..fa361e8
--- /dev/null
+++ b/WebCore/rendering/style/StyleGeneratedImage.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleGeneratedImage.h"
+
+#include "CSSImageGeneratorValue.h"
+#include "RenderObject.h"
+
+namespace WebCore {
+
+PassRefPtr<CSSValue> StyleGeneratedImage::cssValue()
+{
+    return m_generator;
+}
+
+IntSize StyleGeneratedImage::imageSize(const RenderObject* renderer, float /* multiplier */) const
+{
+    // We can ignore the multiplier, since we always store a raw zoomed size.
+    if (m_fixedSize)
+        return m_generator->fixedSize(renderer);
+    return m_containerSize;
+}
+
+void StyleGeneratedImage::setImageContainerSize(const IntSize& size)
+{
+    m_containerSize = size;
+}
+
+void StyleGeneratedImage::addClient(RenderObject* renderer)
+{
+    m_generator->addClient(renderer, IntSize());
+}
+
+void StyleGeneratedImage::removeClient(RenderObject* renderer)
+{
+    m_generator->removeClient(renderer);
+}
+
+Image* StyleGeneratedImage::image(RenderObject* renderer, const IntSize& size) const
+{
+    return m_generator->image(renderer, size);
+}
+
+}
diff --git a/WebCore/rendering/style/StyleGeneratedImage.h b/WebCore/rendering/style/StyleGeneratedImage.h
new file mode 100644
index 0000000..532e383
--- /dev/null
+++ b/WebCore/rendering/style/StyleGeneratedImage.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleGeneratedImage_h
+#define StyleGeneratedImage_h
+
+#include "StyleImage.h"
+
+namespace WebCore {
+
+class CSSValue;
+class CSSImageGeneratorValue;
+
+class StyleGeneratedImage : public StyleImage {
+public:
+    static PassRefPtr<StyleGeneratedImage> create(CSSImageGeneratorValue* val, bool fixedSize)
+    {
+        return adoptRef(new StyleGeneratedImage(val, fixedSize));
+    }
+
+    virtual WrappedImagePtr data() const { return m_generator; }
+
+    virtual bool isGeneratedImage() const { return true; }
+    
+    virtual PassRefPtr<CSSValue> cssValue();
+
+    virtual IntSize imageSize(const RenderObject*, float multiplier) const;
+    virtual bool imageHasRelativeWidth() const { return !m_fixedSize; }
+    virtual bool imageHasRelativeHeight() const { return !m_fixedSize; }
+    virtual bool usesImageContainerSize() const { return !m_fixedSize; }
+    virtual void setImageContainerSize(const IntSize&);
+    virtual void addClient(RenderObject*);
+    virtual void removeClient(RenderObject*);
+    virtual Image* image(RenderObject*, const IntSize&) const;
+    
+private:
+    StyleGeneratedImage(CSSImageGeneratorValue* val, bool fixedSize)
+        : m_generator(val)
+        , m_fixedSize(fixedSize)
+    {
+    }
+    
+    CSSImageGeneratorValue* m_generator; // The generator holds a reference to us.
+    IntSize m_containerSize;
+    bool m_fixedSize;
+};
+
+}
+#endif
diff --git a/WebCore/rendering/style/StyleImage.h b/WebCore/rendering/style/StyleImage.h
new file mode 100644
index 0000000..4bdba6e
--- /dev/null
+++ b/WebCore/rendering/style/StyleImage.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleImage_h
+#define StyleImage_h
+
+#include "IntSize.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSValue;
+class Image;
+class RenderObject;
+
+typedef void* WrappedImagePtr;
+
+class StyleImage : public RefCounted<StyleImage> {
+public:
+    virtual ~StyleImage() { }
+
+    bool operator==(const StyleImage& other)
+    {
+        return data() == other.data();
+    }
+    
+    virtual PassRefPtr<CSSValue> cssValue() = 0;
+
+    virtual bool canRender(float multiplier) const { return true; }
+    virtual bool isLoaded() const { return true; }
+    virtual bool errorOccurred() const { return false; }
+    virtual IntSize imageSize(const RenderObject*, float multiplier) const = 0;
+    virtual bool imageHasRelativeWidth() const = 0;
+    virtual bool imageHasRelativeHeight() const = 0;
+    virtual bool usesImageContainerSize() const = 0;
+    virtual void setImageContainerSize(const IntSize&) = 0;
+    virtual void addClient(RenderObject*) = 0;
+    virtual void removeClient(RenderObject*) = 0;
+    virtual Image* image(RenderObject*, const IntSize&) const = 0;
+    virtual WrappedImagePtr data() const = 0;
+    virtual bool isCachedImage() const { return false; }
+    virtual bool isGeneratedImage() const { return false; }
+    
+    static  bool imagesEquivalent(StyleImage* image1, StyleImage* image2)
+    {
+        if (image1 != image2) {
+            if (!image1 || !image2)
+                return false;
+            return *image1 == *image2;
+        }
+        return true;
+    }
+
+protected:
+    StyleImage() { }
+};
+
+}
+#endif
diff --git a/WebCore/rendering/style/StyleInheritedData.cpp b/WebCore/rendering/style/StyleInheritedData.cpp
new file mode 100644
index 0000000..56d2686
--- /dev/null
+++ b/WebCore/rendering/style/StyleInheritedData.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleRareInheritedData.h"
+
+#include "RenderStyle.h"
+#include "StyleImage.h"
+
+namespace WebCore {
+
+StyleInheritedData::StyleInheritedData()
+    : indent(RenderStyle::initialTextIndent())
+    , line_height(RenderStyle::initialLineHeight())
+    , list_style_image(RenderStyle::initialListStyleImage())
+    , color(RenderStyle::initialColor())
+    , m_effectiveZoom(RenderStyle::initialZoom())
+    , horizontal_border_spacing(RenderStyle::initialHorizontalBorderSpacing())
+    , vertical_border_spacing(RenderStyle::initialVerticalBorderSpacing())
+    , widows(RenderStyle::initialWidows())
+    , orphans(RenderStyle::initialOrphans())
+    , page_break_inside(RenderStyle::initialPageBreak())
+{
+}
+
+StyleInheritedData::~StyleInheritedData()
+{
+}
+
+StyleInheritedData::StyleInheritedData(const StyleInheritedData& o)
+    : RefCounted<StyleInheritedData>()
+    , indent(o.indent)
+    , line_height(o.line_height)
+    , list_style_image(o.list_style_image)
+    , cursorData(o.cursorData)
+    , font(o.font)
+    , color(o.color)
+    , m_effectiveZoom(o.m_effectiveZoom)
+    , horizontal_border_spacing(o.horizontal_border_spacing)
+    , vertical_border_spacing(o.vertical_border_spacing)
+    , widows(o.widows)
+    , orphans(o.orphans)
+    , page_break_inside(o.page_break_inside)
+{
+}
+
+static bool cursorDataEquivalent(const CursorList* c1, const CursorList* c2)
+{
+    if (c1 == c2)
+        return true;
+    if (!c1 && c2 || c1 && !c2)
+        return false;
+    return (*c1 == *c2);
+}
+
+bool StyleInheritedData::operator==(const StyleInheritedData& o) const
+{
+    return
+        indent == o.indent &&
+        line_height == o.line_height &&
+        StyleImage::imagesEquivalent(list_style_image.get(), o.list_style_image.get()) &&
+        cursorDataEquivalent(cursorData.get(), o.cursorData.get()) &&
+        font == o.font &&
+        color == o.color &&
+        m_effectiveZoom == o.m_effectiveZoom &&
+        horizontal_border_spacing == o.horizontal_border_spacing &&
+        vertical_border_spacing == o.vertical_border_spacing &&
+        widows == o.widows &&
+        orphans == o.orphans &&
+        page_break_inside == o.page_break_inside;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleInheritedData.h b/WebCore/rendering/style/StyleInheritedData.h
new file mode 100644
index 0000000..5f1077e
--- /dev/null
+++ b/WebCore/rendering/style/StyleInheritedData.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleInheritedData_h
+#define StyleInheritedData_h
+
+#include "Color.h"
+#include "Font.h"
+#include "Length.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class StyleImage;
+class CursorList;
+
+class StyleInheritedData : public RefCounted<StyleInheritedData> {
+public:
+    static PassRefPtr<StyleInheritedData> create() { return adoptRef(new StyleInheritedData); }
+    PassRefPtr<StyleInheritedData> copy() const { return adoptRef(new StyleInheritedData(*this)); }
+    ~StyleInheritedData();
+
+    bool operator==(const StyleInheritedData& o) const;
+    bool operator!=( const StyleInheritedData& o) const
+    {
+        return !(*this == o);
+    }
+
+    Length indent;
+    // could be packed in a short but doesn't
+    // make a difference currently because of padding
+    Length line_height;
+
+    RefPtr<StyleImage> list_style_image;
+    RefPtr<CursorList> cursorData;
+
+    Font font;
+    Color color;
+    
+    float m_effectiveZoom;
+
+    short horizontal_border_spacing;
+    short vertical_border_spacing;
+    
+    // Paged media properties.
+    short widows;
+    short orphans;
+    unsigned page_break_inside : 2; // EPageBreak
+    
+private:
+    StyleInheritedData();
+    StyleInheritedData(const StyleInheritedData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleInheritedData_h
diff --git a/WebCore/rendering/style/StyleMarqueeData.cpp b/WebCore/rendering/style/StyleMarqueeData.cpp
new file mode 100644
index 0000000..f0e824d
--- /dev/null
+++ b/WebCore/rendering/style/StyleMarqueeData.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleBackgroundData.h"
+
+#include "RenderStyle.h"
+
+namespace WebCore {
+
+StyleMarqueeData::StyleMarqueeData()
+    : increment(RenderStyle::initialMarqueeIncrement())
+    , speed(RenderStyle::initialMarqueeSpeed())
+    , loops(RenderStyle::initialMarqueeLoopCount())
+    , behavior(RenderStyle::initialMarqueeBehavior())
+    , direction(RenderStyle::initialMarqueeDirection())
+{
+}
+
+StyleMarqueeData::StyleMarqueeData(const StyleMarqueeData& o)
+    : RefCounted<StyleMarqueeData>()
+    , increment(o.increment)
+    , speed(o.speed)
+    , loops(o.loops)
+    , behavior(o.behavior)
+    , direction(o.direction) 
+{
+}
+
+bool StyleMarqueeData::operator==(const StyleMarqueeData& o) const
+{
+    return increment == o.increment && speed == o.speed && direction == o.direction &&
+           behavior == o.behavior && loops == o.loops;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleMarqueeData.h b/WebCore/rendering/style/StyleMarqueeData.h
new file mode 100644
index 0000000..5765f5d
--- /dev/null
+++ b/WebCore/rendering/style/StyleMarqueeData.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleMarqueeData_h
+#define StyleMarqueeData_h
+
+#include "Length.h"
+#include "RenderStyleConstants.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class StyleMarqueeData : public RefCounted<StyleMarqueeData> {
+public:
+    static PassRefPtr<StyleMarqueeData> create() { return adoptRef(new StyleMarqueeData); }
+    PassRefPtr<StyleMarqueeData> copy() const { return adoptRef(new StyleMarqueeData(*this)); }
+
+    bool operator==(const StyleMarqueeData& o) const;
+    bool operator!=(const StyleMarqueeData& o) const
+    {
+        return !(*this == o);
+    }
+
+    Length increment;
+    int speed;
+
+    int loops; // -1 means infinite.
+
+    unsigned behavior : 2; // EMarqueeBehavior 
+    EMarqueeDirection direction : 3; // not unsigned because EMarqueeDirection has negative values
+
+private:
+    StyleMarqueeData();
+    StyleMarqueeData(const StyleMarqueeData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleMarqueeData_h
diff --git a/WebCore/rendering/style/StyleMultiColData.cpp b/WebCore/rendering/style/StyleMultiColData.cpp
new file mode 100644
index 0000000..bff4fb3
--- /dev/null
+++ b/WebCore/rendering/style/StyleMultiColData.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleMultiColData.h"
+
+#include "RenderStyle.h"
+
+namespace WebCore {
+
+StyleMultiColData::StyleMultiColData()
+    : m_width(0)
+    , m_count(RenderStyle::initialColumnCount())
+    , m_gap(0)
+    , m_autoWidth(true)
+    , m_autoCount(true)
+    , m_normalGap(true)
+    , m_breakBefore(RenderStyle::initialPageBreak())
+    , m_breakAfter(RenderStyle::initialPageBreak())
+    , m_breakInside(RenderStyle::initialPageBreak())
+{
+}
+
+StyleMultiColData::StyleMultiColData(const StyleMultiColData& o)
+    : RefCounted<StyleMultiColData>()
+    , m_width(o.m_width)
+    , m_count(o.m_count)
+    , m_gap(o.m_gap)
+    , m_rule(o.m_rule)
+    , m_autoWidth(o.m_autoWidth)
+    , m_autoCount(o.m_autoCount)
+    , m_normalGap(o.m_normalGap)
+    , m_breakBefore(o.m_breakBefore)
+    , m_breakAfter(o.m_breakAfter)
+    , m_breakInside(o.m_breakInside)
+{
+}
+
+bool StyleMultiColData::operator==(const StyleMultiColData& o) const
+{
+    return m_width == o.m_width && m_count == o.m_count && m_gap == o.m_gap &&
+           m_rule == o.m_rule && m_breakBefore == o.m_breakBefore && 
+           m_autoWidth == o.m_autoWidth && m_autoCount == o.m_autoCount && m_normalGap == o.m_normalGap &&
+           m_breakAfter == o.m_breakAfter && m_breakInside == o.m_breakInside;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleMultiColData.h b/WebCore/rendering/style/StyleMultiColData.h
new file mode 100644
index 0000000..dec0a55
--- /dev/null
+++ b/WebCore/rendering/style/StyleMultiColData.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleMultiColData_h
+#define StyleMultiColData_h
+
+#include "BorderValue.h"
+#include "Length.h"
+#include "RenderStyleConstants.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+// CSS3 Multi Column Layout
+
+class StyleMultiColData : public RefCounted<StyleMultiColData> {
+public:
+    static PassRefPtr<StyleMultiColData> create() { return adoptRef(new StyleMultiColData); }
+    PassRefPtr<StyleMultiColData> copy() const { return adoptRef(new StyleMultiColData(*this)); }
+    
+    bool operator==(const StyleMultiColData& o) const;
+    bool operator!=(const StyleMultiColData &o) const
+    {
+        return !(*this == o);
+    }
+
+    unsigned short ruleWidth() const
+    {
+        if (m_rule.style() == BNONE || m_rule.style() == BHIDDEN)
+            return 0; 
+        return m_rule.width;
+    }
+
+    float m_width;
+    unsigned short m_count;
+    float m_gap;
+    BorderValue m_rule;
+    
+    bool m_autoWidth : 1;
+    bool m_autoCount : 1;
+    bool m_normalGap : 1;
+    unsigned m_breakBefore : 2; // EPageBreak
+    unsigned m_breakAfter : 2; // EPageBreak
+    unsigned m_breakInside : 2; // EPageBreak
+    
+private:
+    StyleMultiColData();
+    StyleMultiColData(const StyleMultiColData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleMultiColData_h
diff --git a/WebCore/rendering/style/StyleRareInheritedData.cpp b/WebCore/rendering/style/StyleRareInheritedData.cpp
new file mode 100644
index 0000000..2294568
--- /dev/null
+++ b/WebCore/rendering/style/StyleRareInheritedData.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleRareInheritedData.h"
+
+#include "RenderStyle.h"
+#include "RenderStyleConstants.h"
+
+namespace WebCore {
+
+StyleRareInheritedData::StyleRareInheritedData()
+    : textStrokeWidth(RenderStyle::initialTextStrokeWidth())
+    , textShadow(0)
+    , textSecurity(RenderStyle::initialTextSecurity())
+    , userModify(READ_ONLY)
+    , wordBreak(RenderStyle::initialWordBreak())
+    , wordWrap(RenderStyle::initialWordWrap())
+    , nbspMode(NBNORMAL)
+    , khtmlLineBreak(LBNORMAL)
+    , textSizeAdjust(RenderStyle::initialTextSizeAdjust())
+#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
+    , tapHighlightColor(RenderStyle::initialTapHighlightColor())
+#endif
+    , resize(RenderStyle::initialResize())
+    , userSelect(RenderStyle::initialUserSelect())
+{
+}
+
+StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o)
+    : RefCounted<StyleRareInheritedData>()
+    , textStrokeColor(o.textStrokeColor)
+    , textStrokeWidth(o.textStrokeWidth)
+    , textFillColor(o.textFillColor)
+    , textShadow(o.textShadow ? new ShadowData(*o.textShadow) : 0)
+    , highlight(o.highlight)
+    , textSecurity(o.textSecurity)
+    , userModify(o.userModify)
+    , wordBreak(o.wordBreak)
+    , wordWrap(o.wordWrap)
+    , nbspMode(o.nbspMode)
+    , khtmlLineBreak(o.khtmlLineBreak)
+    , textSizeAdjust(o.textSizeAdjust)
+#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
+    , tapHighlightColor(o.tapHighlightColor)
+#endif
+    , resize(o.resize)
+    , userSelect(o.userSelect)
+{
+}
+
+StyleRareInheritedData::~StyleRareInheritedData()
+{
+    delete textShadow;
+}
+
+bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
+{
+    return textStrokeColor == o.textStrokeColor
+        && textStrokeWidth == o.textStrokeWidth
+        && textFillColor == o.textFillColor
+        && shadowDataEquivalent(o)
+        && highlight == o.highlight
+        && textSecurity == o.textSecurity
+        && userModify == o.userModify
+        && wordBreak == o.wordBreak
+        && wordWrap == o.wordWrap
+        && nbspMode == o.nbspMode
+        && khtmlLineBreak == o.khtmlLineBreak
+        && textSizeAdjust == o.textSizeAdjust
+#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
+        && tapHighlightColor == o.tapHighlightColor
+#endif
+        && userSelect == o.userSelect;
+}
+
+bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData& o) const
+{
+    if (!textShadow && o.textShadow || textShadow && !o.textShadow)
+        return false;
+    if (textShadow && o.textShadow && (*textShadow != *o.textShadow))
+        return false;
+    return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleRareInheritedData.h b/WebCore/rendering/style/StyleRareInheritedData.h
new file mode 100644
index 0000000..4abd3cf
--- /dev/null
+++ b/WebCore/rendering/style/StyleRareInheritedData.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleRareInheritedData_h
+#define StyleRareInheritedData_h
+
+#include "AtomicString.h"
+#include "Color.h"
+#include <wtf/RefCounted.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+struct ShadowData;
+
+// This struct is for rarely used inherited CSS3, CSS2, and WebKit-specific properties.
+// By grouping them together, we save space, and only allocate this object when someone
+// actually uses one of these properties.
+class StyleRareInheritedData : public RefCounted<StyleRareInheritedData> {
+public:
+    static PassRefPtr<StyleRareInheritedData> create() { return adoptRef(new StyleRareInheritedData); }
+    PassRefPtr<StyleRareInheritedData> copy() const { return adoptRef(new StyleRareInheritedData(*this)); }
+    ~StyleRareInheritedData();
+
+    bool operator==(const StyleRareInheritedData& o) const;
+    bool operator!=(const StyleRareInheritedData& o) const
+    {
+        return !(*this == o);
+    }
+    bool shadowDataEquivalent(const StyleRareInheritedData&) const;
+
+    Color textStrokeColor;
+    float textStrokeWidth;
+    Color textFillColor;
+#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
+    Color tapHighlightColor;
+#endif
+
+    ShadowData* textShadow; // Our text shadow information for shadowed text drawing.
+    AtomicString highlight; // Apple-specific extension for custom highlight rendering.
+    unsigned textSecurity : 2; // ETextSecurity
+    unsigned userModify : 2; // EUserModify (editing)
+    unsigned wordBreak : 2; // EWordBreak
+    unsigned wordWrap : 1; // EWordWrap 
+    unsigned nbspMode : 1; // ENBSPMode
+    unsigned khtmlLineBreak : 1; // EKHTMLLineBreak
+    bool textSizeAdjust : 1; // An Apple extension.
+    unsigned resize : 2; // EResize
+    unsigned userSelect : 1;  // EUserSelect
+    
+private:
+    StyleRareInheritedData();
+    StyleRareInheritedData(const StyleRareInheritedData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleRareInheritedData_h
diff --git a/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/WebCore/rendering/style/StyleRareNonInheritedData.cpp
new file mode 100644
index 0000000..e8ceeeb
--- /dev/null
+++ b/WebCore/rendering/style/StyleRareNonInheritedData.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleRareNonInheritedData.h"
+
+#include "CSSStyleSelector.h"
+#include "RenderStyle.h"
+
+namespace WebCore {
+
+StyleRareNonInheritedData::StyleRareNonInheritedData()
+    : lineClamp(RenderStyle::initialLineClamp())
+    , opacity(RenderStyle::initialOpacity())
+    , m_content(0)
+    , m_counterDirectives(0)
+    , userDrag(RenderStyle::initialUserDrag())
+    , textOverflow(RenderStyle::initialTextOverflow())
+    , marginTopCollapse(MCOLLAPSE)
+    , marginBottomCollapse(MCOLLAPSE)
+    , matchNearestMailBlockquoteColor(RenderStyle::initialMatchNearestMailBlockquoteColor())
+    , m_appearance(RenderStyle::initialAppearance())
+    , m_borderFit(RenderStyle::initialBorderFit())
+    , m_boxShadow(0)
+    , m_animations(0)
+    , m_transitions(0)
+    , m_mask(FillLayer(MaskFillLayer))
+#if ENABLE(XBL)
+    , bindingURI(0)
+#endif
+{
+}
+
+StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInheritedData& o)
+    : RefCounted<StyleRareNonInheritedData>()
+    , lineClamp(o.lineClamp)
+    , opacity(o.opacity)
+    , flexibleBox(o.flexibleBox)
+    , marquee(o.marquee)
+    , m_multiCol(o.m_multiCol)
+    , m_transform(o.m_transform)
+    , m_content(0)
+    , m_counterDirectives(0)
+    , userDrag(o.userDrag)
+    , textOverflow(o.textOverflow)
+    , marginTopCollapse(o.marginTopCollapse)
+    , marginBottomCollapse(o.marginBottomCollapse)
+    , matchNearestMailBlockquoteColor(o.matchNearestMailBlockquoteColor)
+    , m_appearance(o.m_appearance)
+    , m_borderFit(o.m_borderFit)
+    , m_boxShadow(o.m_boxShadow ? new ShadowData(*o.m_boxShadow) : 0)
+    , m_boxReflect(o.m_boxReflect)
+    , m_animations(o.m_animations ? new AnimationList(*o.m_animations) : 0)
+    , m_transitions(o.m_transitions ? new AnimationList(*o.m_transitions) : 0)
+    , m_mask(o.m_mask)
+    , m_maskBoxImage(o.m_maskBoxImage)
+#if ENABLE(XBL)
+    , bindingURI(o.bindingURI ? o.bindingURI->copy() : 0)
+#endif
+{
+}
+
+StyleRareNonInheritedData::~StyleRareNonInheritedData()
+{
+}
+
+#if ENABLE(XBL)
+bool StyleRareNonInheritedData::bindingsEquivalent(const StyleRareNonInheritedData& o) const
+{
+    if (this == &o) return true;
+    if (!bindingURI && o.bindingURI || bindingURI && !o.bindingURI)
+        return false;
+    if (bindingURI && o.bindingURI && (*bindingURI != *o.bindingURI))
+        return false;
+    return true;
+}
+#endif
+
+bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) const
+{
+    return lineClamp == o.lineClamp
+#if ENABLE(DASHBOARD_SUPPORT)
+        && m_dashboardRegions == o.m_dashboardRegions
+#endif
+        && opacity == o.opacity
+        && flexibleBox == o.flexibleBox
+        && marquee == o.marquee
+        && m_multiCol == o.m_multiCol
+        && m_transform == o.m_transform
+        && m_content == o.m_content
+        && m_counterDirectives == o.m_counterDirectives
+        && userDrag == o.userDrag
+        && textOverflow == o.textOverflow
+        && marginTopCollapse == o.marginTopCollapse
+        && marginBottomCollapse == o.marginBottomCollapse
+        && matchNearestMailBlockquoteColor == o.matchNearestMailBlockquoteColor
+        && m_appearance == o.m_appearance
+        && m_borderFit == o.m_borderFit
+        && shadowDataEquivalent(o)
+        && reflectionDataEquivalent(o)
+        && animationDataEquivalent(o)
+        && transitionDataEquivalent(o)
+        && m_mask == o.m_mask
+        && m_maskBoxImage == o.m_maskBoxImage
+#if ENABLE(XBL)
+        && bindingsEquivalent(o)
+#endif
+        ;
+}
+
+bool StyleRareNonInheritedData::shadowDataEquivalent(const StyleRareNonInheritedData& o) const
+{
+    if (!m_boxShadow && o.m_boxShadow || m_boxShadow && !o.m_boxShadow)
+        return false;
+    if (m_boxShadow && o.m_boxShadow && (*m_boxShadow != *o.m_boxShadow))
+        return false;
+    return true;
+}
+
+bool StyleRareNonInheritedData::reflectionDataEquivalent(const StyleRareNonInheritedData& o) const
+{
+    if (m_boxReflect != o.m_boxReflect) {
+        if (!m_boxReflect || !o.m_boxReflect)
+            return false;
+        return *m_boxReflect == *o.m_boxReflect;
+    }
+    return true;
+
+}
+
+bool StyleRareNonInheritedData::animationDataEquivalent(const StyleRareNonInheritedData& o) const
+{
+    if (!m_animations && o.m_animations || m_animations && !o.m_animations)
+        return false;
+    if (m_animations && o.m_animations && (*m_animations != *o.m_animations))
+        return false;
+    return true;
+}
+
+bool StyleRareNonInheritedData::transitionDataEquivalent(const StyleRareNonInheritedData& o) const
+{
+    if (!m_transitions && o.m_transitions || m_transitions && !o.m_transitions)
+        return false;
+    if (m_transitions && o.m_transitions && (*m_transitions != *o.m_transitions))
+        return false;
+    return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleRareNonInheritedData.h b/WebCore/rendering/style/StyleRareNonInheritedData.h
new file mode 100644
index 0000000..6ce6a33
--- /dev/null
+++ b/WebCore/rendering/style/StyleRareNonInheritedData.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleRareNonInheritedData_h
+#define StyleRareNonInheritedData_h
+
+#include "CounterDirectives.h"
+#include "CursorData.h"
+#include "DataRef.h"
+#include "FillLayer.h"
+#include "NinePieceImage.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class AnimationList;
+class CSSStyleSelector;
+class StyleFlexibleBoxData;
+class StyleMarqueeData;
+class StyleMultiColData;
+class StyleReflection;
+class StyleTransformData;
+struct ContentData;
+struct ShadowData;
+
+#if ENABLE(DASHBOARD_SUPPORT)
+class StyleDashboardRegion;
+#endif
+
+#if ENABLE(XBL)
+class BindingURI;
+#endif
+
+// This struct is for rarely used non-inherited CSS3, CSS2, and WebKit-specific properties.
+// By grouping them together, we save space, and only allocate this object when someone
+// actually uses one of these properties.
+class StyleRareNonInheritedData : public RefCounted<StyleRareNonInheritedData> {
+public:
+    static PassRefPtr<StyleRareNonInheritedData> create() { return adoptRef(new StyleRareNonInheritedData); }
+    PassRefPtr<StyleRareNonInheritedData> copy() const { return adoptRef(new StyleRareNonInheritedData(*this)); }
+    ~StyleRareNonInheritedData();
+    
+#if ENABLE(XBL)
+    bool bindingsEquivalent(const StyleRareNonInheritedData&) const;
+#endif
+
+    bool operator==(const StyleRareNonInheritedData&) const;
+    bool operator!=(const StyleRareNonInheritedData& o) const { return !(*this == o); }
+ 
+    bool shadowDataEquivalent(const StyleRareNonInheritedData& o) const;
+    bool reflectionDataEquivalent(const StyleRareNonInheritedData& o) const;
+    bool animationDataEquivalent(const StyleRareNonInheritedData&) const;
+    bool transitionDataEquivalent(const StyleRareNonInheritedData&) const;
+
+    int lineClamp; // An Apple extension.
+#if ENABLE(DASHBOARD_SUPPORT)
+    Vector<StyleDashboardRegion> m_dashboardRegions;
+#endif
+    float opacity; // Whether or not we're transparent.
+
+    DataRef<StyleFlexibleBoxData> flexibleBox; // Flexible box properties 
+    DataRef<StyleMarqueeData> marquee; // Marquee properties
+    DataRef<StyleMultiColData> m_multiCol; //  CSS3 multicol properties
+    DataRef<StyleTransformData> m_transform; // Transform properties (rotate, scale, skew, etc.)
+
+    OwnPtr<ContentData> m_content;
+    OwnPtr<CounterDirectiveMap> m_counterDirectives;
+
+    unsigned userDrag : 2; // EUserDrag
+    bool textOverflow : 1; // Whether or not lines that spill out should be truncated with "..."
+    unsigned marginTopCollapse : 2; // EMarginCollapse
+    unsigned marginBottomCollapse : 2; // EMarginCollapse
+    unsigned matchNearestMailBlockquoteColor : 1; // EMatchNearestMailBlockquoteColor, FIXME: This property needs to be eliminated. It should never have been added.
+    unsigned m_appearance : 6; // EAppearance
+    unsigned m_borderFit : 1; // EBorderFit
+    OwnPtr<ShadowData> m_boxShadow;  // For box-shadow decorations.
+    
+    RefPtr<StyleReflection> m_boxReflect;
+
+    OwnPtr<AnimationList> m_animations;
+    OwnPtr<AnimationList> m_transitions;
+
+    FillLayer m_mask;
+    NinePieceImage m_maskBoxImage;
+
+#if ENABLE(XBL)
+    OwnPtr<BindingURI> bindingURI; // The XBL binding URI list.
+#endif
+    
+private:
+    StyleRareNonInheritedData();
+    StyleRareNonInheritedData(const StyleRareNonInheritedData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleRareNonInheritedData_h
diff --git a/WebCore/rendering/style/StyleReflection.h b/WebCore/rendering/style/StyleReflection.h
new file mode 100644
index 0000000..455d1b7
--- /dev/null
+++ b/WebCore/rendering/style/StyleReflection.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleReflection_h
+#define StyleReflection_h
+
+#include "CSSReflectionDirection.h"
+#include "Length.h"
+#include "NinePieceImage.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class StyleReflection : public RefCounted<StyleReflection> {
+public:
+    static PassRefPtr<StyleReflection> create()
+    {
+        return adoptRef(new StyleReflection);
+    }
+
+    bool operator==(const StyleReflection& o) const
+    {
+        return m_direction == o.m_direction && m_offset == o.m_offset && m_mask == o.m_mask;
+    }
+    bool operator!=(const StyleReflection& o) const { return !(*this == o); }
+
+    CSSReflectionDirection direction() const { return m_direction; }
+    Length offset() const { return m_offset; }
+    const NinePieceImage& mask() const { return m_mask; }
+
+    void setDirection(CSSReflectionDirection dir) { m_direction = dir; }
+    void setOffset(const Length& l) { m_offset = l; }
+    void setMask(const NinePieceImage& image) { m_mask = image; }
+
+private:
+    StyleReflection()
+        : m_direction(ReflectionBelow)
+        , m_offset(0, Fixed)
+    {
+    }
+    
+    CSSReflectionDirection m_direction;
+    Length m_offset;
+    NinePieceImage m_mask;
+};
+
+} // namespace WebCore
+
+#endif // StyleReflection_h
diff --git a/WebCore/rendering/style/StyleSurroundData.cpp b/WebCore/rendering/style/StyleSurroundData.cpp
new file mode 100644
index 0000000..8d5e79c
--- /dev/null
+++ b/WebCore/rendering/style/StyleSurroundData.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleSurroundData.h"
+
+namespace WebCore {
+
+StyleSurroundData::StyleSurroundData()
+    : margin(Fixed)
+    , padding(Fixed)
+{
+}
+
+StyleSurroundData::StyleSurroundData(const StyleSurroundData& o)
+    : RefCounted<StyleSurroundData>()
+    , offset(o.offset)
+    , margin(o.margin)
+    , padding(o.padding)
+    , border(o.border)
+{
+}
+
+bool StyleSurroundData::operator==(const StyleSurroundData& o) const
+{
+    return offset == o.offset && margin == o.margin && padding == o.padding && border == o.border;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleSurroundData.h b/WebCore/rendering/style/StyleSurroundData.h
new file mode 100644
index 0000000..b8f21e4
--- /dev/null
+++ b/WebCore/rendering/style/StyleSurroundData.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleSurroundData_h
+#define StyleSurroundData_h
+
+#include "BorderData.h"
+#include "LengthBox.h"
+#include <wtf/RefCounted.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class StyleSurroundData : public RefCounted<StyleSurroundData> {
+public:
+    static PassRefPtr<StyleSurroundData> create() { return adoptRef(new StyleSurroundData); }
+    PassRefPtr<StyleSurroundData> copy() const { return adoptRef(new StyleSurroundData(*this)); }
+    
+    bool operator==(const StyleSurroundData& o) const;
+    bool operator!=(const StyleSurroundData& o) const
+    {
+        return !(*this == o);
+    }
+
+    LengthBox offset;
+    LengthBox margin;
+    LengthBox padding;
+    BorderData border;
+    
+private:
+    StyleSurroundData();
+    StyleSurroundData(const StyleSurroundData&);    
+};
+
+} // namespace WebCore
+
+#endif // StyleSurroundData_h
diff --git a/WebCore/rendering/style/StyleTransformData.cpp b/WebCore/rendering/style/StyleTransformData.cpp
new file mode 100644
index 0000000..de20e77
--- /dev/null
+++ b/WebCore/rendering/style/StyleTransformData.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleTransformData.h"
+
+#include "RenderStyle.h"
+
+namespace WebCore {
+
+StyleTransformData::StyleTransformData()
+    : m_operations(RenderStyle::initialTransform())
+    , m_x(RenderStyle::initialTransformOriginX())
+    , m_y(RenderStyle::initialTransformOriginY())
+{
+}
+
+StyleTransformData::StyleTransformData(const StyleTransformData& o)
+    : RefCounted<StyleTransformData>()
+    , m_operations(o.m_operations)
+    , m_x(o.m_x)
+    , m_y(o.m_y)
+{
+}
+
+bool StyleTransformData::operator==(const StyleTransformData& o) const
+{
+    return m_x == o.m_x && m_y == o.m_y && m_operations == o.m_operations;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleTransformData.h b/WebCore/rendering/style/StyleTransformData.h
new file mode 100644
index 0000000..157e600
--- /dev/null
+++ b/WebCore/rendering/style/StyleTransformData.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleTransformData_h
+#define StyleTransformData_h
+
+#include "Length.h"
+#include "TransformOperations.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class StyleTransformData : public RefCounted<StyleTransformData> {
+public:
+    static PassRefPtr<StyleTransformData> create() { return adoptRef(new StyleTransformData); }
+    PassRefPtr<StyleTransformData> copy() const { return adoptRef(new StyleTransformData(*this)); }
+
+    bool operator==(const StyleTransformData& o) const;
+    bool operator!=(const StyleTransformData& o) const
+    {
+        return !(*this == o);
+    }
+
+    TransformOperations m_operations;
+    Length m_x;
+    Length m_y;
+
+private:
+    StyleTransformData();
+    StyleTransformData(const StyleTransformData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleTransformData_h
diff --git a/WebCore/rendering/style/StyleVisualData.cpp b/WebCore/rendering/style/StyleVisualData.cpp
new file mode 100644
index 0000000..91690cf
--- /dev/null
+++ b/WebCore/rendering/style/StyleVisualData.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StyleVisualData.h"
+
+#include "RenderStyle.h"
+
+namespace WebCore {
+
+StyleVisualData::StyleVisualData()
+    : hasClip(false)
+    , textDecoration(RenderStyle::initialTextDecoration())
+    , counterIncrement(0)
+    , counterReset(0)
+    , m_zoom(RenderStyle::initialZoom())
+{
+}
+
+StyleVisualData::~StyleVisualData()
+{
+}
+
+StyleVisualData::StyleVisualData(const StyleVisualData& o)
+    : RefCounted<StyleVisualData>()
+    , clip(o.clip)
+    , hasClip(o.hasClip)
+    , textDecoration(o.textDecoration)
+    , counterIncrement(o.counterIncrement)
+    , counterReset(o.counterReset)
+    , m_zoom(RenderStyle::initialZoom())
+{
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleVisualData.h b/WebCore/rendering/style/StyleVisualData.h
new file mode 100644
index 0000000..613ef2f
--- /dev/null
+++ b/WebCore/rendering/style/StyleVisualData.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleVisualData_h
+#define StyleVisualData_h
+
+#include "LengthBox.h"
+#include <wtf/RefCounted.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class StyleVisualData : public RefCounted<StyleVisualData> {
+public:
+    static PassRefPtr<StyleVisualData> create() { return adoptRef(new StyleVisualData); }
+    PassRefPtr<StyleVisualData> copy() const { return adoptRef(new StyleVisualData(*this)); }
+    ~StyleVisualData();
+
+    bool operator==(const StyleVisualData& o) const
+    {
+        return ( clip == o.clip &&
+                 hasClip == o.hasClip &&
+                 counterIncrement == o.counterIncrement &&
+                 counterReset == o.counterReset &&
+                 textDecoration == o.textDecoration &&
+                 m_zoom == o.m_zoom);
+    }
+    bool operator!=(const StyleVisualData& o) const { return !(*this == o); }
+
+    LengthBox clip;
+    bool hasClip : 1;
+    unsigned textDecoration : 4; // Text decorations defined *only* by this element.
+    
+    short counterIncrement; // ok, so these are not visual mode specific
+    short counterReset;     // can't go to inherited, since these are not inherited
+
+    float m_zoom;
+
+private:
+    StyleVisualData();
+    StyleVisualData(const StyleVisualData&);    
+};
+
+} // namespace WebCore
+
+#endif // StyleVisualData_h
diff --git a/WebCore/rendering/style/TimingFunction.h b/WebCore/rendering/style/TimingFunction.h
new file mode 100644
index 0000000..f114596
--- /dev/null
+++ b/WebCore/rendering/style/TimingFunction.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TimingFunction_h
+#define TimingFunction_h
+
+#include "RenderStyleConstants.h"
+
+namespace WebCore {
+
+struct TimingFunction {
+    TimingFunction()
+        : m_type(CubicBezierTimingFunction)
+        , m_x1(0.25)
+        , m_y1(0.1)
+        , m_x2(0.25)
+        , m_y2(1.0)
+    {
+    }
+
+    TimingFunction(ETimingFunctionType timingFunction, double x1 = 0.0, double y1 = 0.0, double x2 = 1.0, double y2 = 1.0)
+        : m_type(timingFunction)
+        , m_x1(x1)
+        , m_y1(y1)
+        , m_x2(x2)
+        , m_y2(y2)
+    {
+    }
+
+    bool operator==(const TimingFunction& o) const
+    {
+        return m_type == o.m_type && m_x1 == o.m_x1 && m_y1 == o.m_y1 && m_x2 == o.m_x2 && m_y2 == o.m_y2;
+    }
+
+    double x1() const { return m_x1; }
+    double y1() const { return m_y1; }
+    double x2() const { return m_x2; }
+    double y2() const { return m_y2; }
+
+    ETimingFunctionType type() const { return m_type; }
+
+private:
+    ETimingFunctionType m_type;
+
+    double m_x1;
+    double m_y1;
+    double m_x2;
+    double m_y2;
+};
+
+} // namespace WebCore
+
+#endif // TimingFunction_h
diff --git a/WebCore/rendering/style/TransformOperation.h b/WebCore/rendering/style/TransformOperation.h
new file mode 100644
index 0000000..1baa67d
--- /dev/null
+++ b/WebCore/rendering/style/TransformOperation.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TransformOperation_h
+#define TransformOperation_h
+
+#include "AffineTransform.h"
+#include "IntSize.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+// CSS Transforms (may become part of CSS3)
+
+class TransformOperation : public RefCounted<TransformOperation> {
+public:
+    enum OperationType {
+        SCALE_X, SCALE_Y, SCALE, 
+        TRANSLATE_X, TRANSLATE_Y, TRANSLATE, 
+        ROTATE, 
+        SKEW_X, SKEW_Y, SKEW, 
+        MATRIX, IDENTITY, NONE
+    };
+
+    virtual ~TransformOperation() { }
+
+    virtual bool operator==(const TransformOperation&) const = 0;
+    bool operator!=(const TransformOperation& o) const { return !(*this == o); }
+
+    virtual bool isIdentity() const = 0;
+
+    virtual bool apply(AffineTransform&, const IntSize& borderBoxSize) const = 0;
+
+    virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false) = 0;
+
+    virtual OperationType getOperationType() const = 0;
+    virtual bool isSameType(const TransformOperation& o) const { return false; }
+};
+
+} // namespace WebCore
+
+#endif // TransformOperation_h
diff --git a/WebCore/rendering/style/TransformOperations.cpp b/WebCore/rendering/style/TransformOperations.cpp
new file mode 100644
index 0000000..3d71480
--- /dev/null
+++ b/WebCore/rendering/style/TransformOperations.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "TransformOperations.h"
+
+#include "IdentityTransformOperation.h"
+
+namespace WebCore {
+
+TransformOperations::TransformOperations(bool makeIdentity)
+{
+    if (makeIdentity)
+        m_operations.append(IdentityTransformOperation::create());
+}
+
+bool TransformOperations::operator==(const TransformOperations& o) const
+{
+    if (m_operations.size() != o.m_operations.size())
+        return false;
+        
+    unsigned s = m_operations.size();
+    for (unsigned i = 0; i < s; i++) {
+        if (*m_operations[i] != *o.m_operations[i])
+            return false;
+    }
+    
+    return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/TransformOperations.h b/WebCore/rendering/style/TransformOperations.h
new file mode 100644
index 0000000..d558a4e
--- /dev/null
+++ b/WebCore/rendering/style/TransformOperations.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TransformOperations_h
+#define TransformOperations_h
+
+#include "TransformOperation.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class TransformOperations {
+public:
+    TransformOperations(bool makeIdentity = false);
+    
+    bool operator==(const TransformOperations& o) const;
+    bool operator!=(const TransformOperations& o) const
+    {
+        return !(*this == o);
+    }
+    
+    void apply(const IntSize& sz, AffineTransform& t) const
+    {
+        for (unsigned i = 0; i < m_operations.size(); ++i)
+            m_operations[i]->apply(t, sz);
+    }
+    
+    Vector<RefPtr<TransformOperation> >& operations() { return m_operations; }
+    const Vector<RefPtr<TransformOperation> >& operations() const { return m_operations; }
+
+private:
+    Vector<RefPtr<TransformOperation> > m_operations;
+};
+
+} // namespace WebCore
+
+#endif // TransformOperations_h
diff --git a/WebCore/rendering/style/TranslateTransformOperation.cpp b/WebCore/rendering/style/TranslateTransformOperation.cpp
new file mode 100644
index 0000000..47471c4
--- /dev/null
+++ b/WebCore/rendering/style/TranslateTransformOperation.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto ([email protected])
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "TranslateTransformOperation.h"
+
+namespace WebCore {
+
+PassRefPtr<TransformOperation> TranslateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
+{
+    if (from && !from->isSameType(*this))
+        return this;
+    
+    if (blendToIdentity)
+        return TranslateTransformOperation::create(Length(m_x.type()).blend(m_x, progress), Length(m_y.type()).blend(m_y, progress), m_type);
+
+    const TranslateTransformOperation* fromOp = static_cast<const TranslateTransformOperation*>(from);
+    Length fromX = fromOp ? fromOp->m_x : Length(m_x.type());
+    Length fromY = fromOp ? fromOp->m_y : Length(m_y.type());
+    return TranslateTransformOperation::create(m_x.blend(fromX, progress), m_y.blend(fromY, progress), m_type);
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/style/TranslateTransformOperation.h b/WebCore/rendering/style/TranslateTransformOperation.h
new file mode 100644
index 0000000..c292ae7
--- /dev/null
+++ b/WebCore/rendering/style/TranslateTransformOperation.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2000 Lars Knoll ([email protected])
+ *           (C) 2000 Antti Koivisto ([email protected])
+ *           (C) 2000 Dirk Mueller ([email protected])
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis ([email protected])
+ *
+ * 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, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TranslateTransformOperation_h
+#define TranslateTransformOperation_h
+
+#include "Length.h"
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class TranslateTransformOperation : public TransformOperation {
+public:
+    static PassRefPtr<TranslateTransformOperation> create(const Length& tx, const Length& ty, OperationType type)
+    {
+        return adoptRef(new TranslateTransformOperation(tx, ty, type));
+    }
+
+    virtual bool isIdentity() const { return m_x.calcFloatValue(1) == 0 && m_y.calcFloatValue(1) == 0; }
+    virtual OperationType getOperationType() const { return m_type; }
+    virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
+
+    virtual bool operator==(const TransformOperation& o) const
+    {
+        if (!isSameType(o))
+            return false;
+        const TranslateTransformOperation* t = static_cast<const TranslateTransformOperation*>(&o);
+        return m_x == t->m_x && m_y == t->m_y;
+    }
+
+    virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
+    {
+        transform.translate(m_x.calcFloatValue(borderBoxSize.width()), m_y.calcFloatValue(borderBoxSize.height()));
+        return m_x.type() == Percent || m_y.type() == Percent;
+    }
+
+    virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
+
+private:
+    TranslateTransformOperation(const Length& tx, const Length& ty, OperationType type)
+        : m_x(tx)
+        , m_y(ty)
+        , m_type(type)
+    {
+    }
+
+    Length m_x;
+    Length m_y;
+    OperationType m_type;
+};
+
+} // namespace WebCore
+
+#endif // TranslateTransformOperation_h